<commit_before>'use strict';

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

const Exchange = require ('./base/Exchange');
const { ExchangeError, AuthenticationError, InsufficientFunds } = require ('./base/errors');

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

module.exports = class bcex extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bcex',
            'name': 'BCEX',
            'countries': [ 'CN', 'CA' ],
            'version': '1',
            'has': {
                'fetchBalance': true,
                'fetchMarkets': true,
                'createOrder': true,
                'cancelOrder': true,
                'fetchTicker': true,
                'fetchTickers': false,
                'fetchTrades': true,
                'fetchOrder': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/43362240-21c26622-92ee-11e8-9464-5801ec526d77.jpg',
                'api': 'https://www.bcex.top',
                'www': 'https://www.bcex.top',
                'doc': 'https://www.bcex.top/api_market/market/',
                'fees': 'http://bcex.udesk.cn/hc/articles/57085',
                'referral': 'https://www.bcex.top/user/reg/type/2/pid/758978',
            },
            'api': {
                'public': {
                    'get': [
                        'Api_Market/getPriceList', // tickers
                        'Api_Order/ticker', // last ohlcv candle (ticker)
                        'Api_Order/depth', // orderbook
                        'Api_Market/getCoinTrade', // ticker
                        'Api_Order/marketOrder', // trades...
                    ],
                    'post': [
                        'Api_Market/getPriceList', // tickers
                        'Api_Order/ticker', // last ohlcv candle (ticker)
                        'Api_Order/depth', // orderbook
                        'Api_Market/getCoinTrade', // ticker
                        'Api_Order/marketOrder', // trades...
                    ],
                },
                'private': {
                    'post': [
                        'Api_Order/cancel',
                        'Api_Order/coinTrust', // limit order
                        'Api_Order/orderList', // open / all orders (my trades?)
                        'Api_Order/orderInfo',
                        'Api_Order/tradeList', // open / all orders
                        'Api_Order/trustList', // ?
                        'Api_User/userBalance',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'maker': 0.0,
                    'taker': 0.2 / 100,
                },
                'funding': {
                    'tierBased': false,
                    'percentage': false,
                    'withdraw': {
                        'ckusd': 0.0,
                        'other': 0.05 / 100,
                    },
                    'deposit': {},
                },
            },
            'exceptions': {
                '该币不存在,非法操作': ExchangeError, // { code: 1, msg: "该币不存在,非法操作" } - returned when a required symbol parameter is missing in the request (also, maybe on other types of errors as well)
                '公钥不合法': AuthenticationError, // { code: 1, msg: '公钥不合法' } - wrong public key
                '您的可用余额不足': InsufficientFunds, // { code: 1, msg: '您的可用余额不足' } - your available balance is insufficient
            },
        });
    }

    async fetchMarkets () {
        let response = await this.publicGetApiMarketGetPriceList ();
        let result = [];
        let keys = Object.keys (response);
        for (let i = 0; i < keys.length; i++) {
            let currentMarketId = keys[i];
            let currentMarkets = response[currentMarketId];
            for (let j = 0; j < currentMarkets.length; j++) {
                let market = currentMarkets[j];
                let baseId = market['coin_from'];
                let quoteId = market['coin_to'];
                let base = baseId.toUpperCase ();
                let quote = quoteId.toUpperCase ();
                base = this.commonCurrencyCode (base);
                quote = this.commonCurrencyCode (quote);
                let id = baseId + '2' + quoteId;
                let symbol = base + '/' + quote;
                let active = true;
                let precision = {
                    'amount': 8, // todo: Look for a better way to find a value. A value is needed for order placement, 8 used as default.
                    'price': len(market['current'].split('.')[1]), // todo: Look for a better way. For the moment, get number of decimals from last price
                };
                let limits = {
                    'amount': {
                        'min': undefined, // todo
                        'max': undefined,
                    },
                    'price': {
                        'min': undefined, // todo
                        'max': undefined,
                    },
                    'cost': {
                        'min': undefined, // todo
                        'max': undefined,
                    },
                };
                result.push ({
                    'id': id,
                    'symbol': symbol,
                    'base': base,
                    'quote': quote,
                    'baseId': baseId,
                    'quoteId': quoteId,
                    'active': active,
                    'precision': precision,
                    'limits': limits,
                    'info': market,
                });
            }
        }
        return result;
    }

    parseTrade (trade, market = undefined) {
        let symbol = undefined;
        if (typeof market !== 'undefined') {
            symbol = market['symbol'];
        }
        let timestamp = this.safeInteger2 (trade, 'date', 'created');
        if (typeof timestamp !== 'undefined') {
            timestamp = timestamp * 1000;
        }
        let id = this.safeString (trade, 'tid');
        let orderId = this.safeString (trade, 'order_id');
        let amount = this.safeFloat2 (trade, 'number', 'amount');
        let price = this.safeFloat (trade, 'price');
        let cost = undefined;
        if (typeof price !== 'undefined') {
            if (typeof amount !== 'undefined') {
                cost = amount * price;
            }
        }
        let side = this.safeString (trade, 'type');
        return {
            'info': trade,
            'id': id,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'type': undefined,
            'side': side,
            'price': price,
            'amount': amount,
            'cost': cost,
            'order': orderId,
            'fee': undefined,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'symbol': this.marketId (symbol),
        };
        if (typeof limit !== 'undefined') {
            request['limit'] = limit;
        }
        let market = this.market (symbol);
        let response = await this.publicPostApiOrderMarketOrder (this.extend (request, params));
        return this.parseTrades (response['data'], market, since, limit);
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let response = await this.privatePostApiUserUserBalance (params);
        let data = response['data'];
        let keys = Object.keys (data);
        let result = { };
        for (let i = 0; i < keys.length; i++) {
            let key = keys[i];
            let amount = this.safeFloat (data, key);
            let parts = key.split ('_');
            let currencyId = parts[0];
            let lockOrOver = parts[1];
            let code = currencyId.toUpperCase ();
            if (currencyId in this.currencies_by_id) {
                code = this.currencies_by_id[currencyId]['code'];
            } else {
                code = this.commonCurrencyCode (code);
            }
            if (!(code in result)) {
                let account = this.account ();
                result[code] = account;
            }
            if (lockOrOver === 'lock') {
                result[code]['used'] = parseFloat (amount);
            } else {
                result[code]['free'] = parseFloat (amount);
            }
        }
        keys = Object.keys (result);
        for (let i = 0; i < keys.length; i++) {
            let key = keys[i];
            let total = this.sum (result[key]['used'], result[key]['total']);
            result[key]['total'] = total;
        }
        result['info'] = data;
        return this.parseBalance (result);
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.markets[symbol];
        let request = {
            'part': market['quoteId'],
            'coin': market['baseId'],
        };
        let response = await this.publicPostApiMarketGetCoinTrade (this.extend (request, params));
        let timestamp = this.milliseconds ();
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (response, 'max'),
            'low': this.safeFloat (response, 'min'),
            'bid': this.safeFloat (response, 'buy'),
            'bidVolume': undefined,
            'ask': this.safeFloat (response, 'sale'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': this.safeFloat (response, 'price'),
            'last': this.safeFloat (response, 'price'),
            'previousClose': undefined,
            'change': undefined,
            'percentage': this.safeFloat (response, 'change_24h'),
            'average': undefined,
            'baseVolume': this.safeFloat (response, 'volume_24h'),
            'quoteVolume': undefined,
            'info': response,
        };
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let marketId = this.marketId (symbol);
        let request = {
            'symbol': marketId,
        };
        let response = await this.publicPostApiOrderDepth (this.extend (request, params));
        let data = response['data'];
        let orderbook = this.parseOrderBook (data, data['date'] * 1000);
        return orderbook;
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'symbol': market['id'],
        };
        let response = await this.privatePostApiOrderOrderList (this.extend (request, params));
        return this.parseTrades (response['data'], market, since, limit);
    }

    parseOrderStatus (status) {
        let statuses = {
            '0': 'open',
            '1': 'open', // partially filled
            '2': 'closed',
            '3': 'canceled',
        };
        if (status in statuses) {
            return statuses[status];
        }
        return status;
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'symbol': this.marketId (symbol),
            'trust_id': id,
        };
        let response = await this.privatePostApiOrderOrderInfo (this.extend (request, params));
        let order = response['data'];
        let timestamp = order['created'] * 1000;
        let status = this.parseOrderStatus (order['status']);
        let result = {
            'info': order,
            'id': id,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'lastTradeTimestamp': undefined,
            'symbol': symbol,
            'type': order['flag'],
            'side': undefined,
            'price': order['price'],
            'cost': undefined,
            'average': undefined,
            'amount': order['number'],
            'filled': order['numberdeal'],
            'remaining': order['numberover'],
            'status': status,
            'fee': undefined,
        };
        return result;
    }

    parseOrder (order, market = undefined) {
        let id = this.safeString (order, 'id');
        let timestamp = order['datetime'] * 1000;
        let iso8601 = this.iso8601 (timestamp);
        let symbol = market['symbol'];
        let type = undefined;
        let side = order['type'];
        let price = order['price'];
        let average = order['avg_price'];
        let amount = order['amount'];
        let remaining = order['amount_outstanding'];
        let filled = amount - remaining;
        let status = this.safeString (order, 'status');
        status = this.parseOrderStatus (status);
        let cost = filled * price;
        let fee = undefined;
        let result = {
            'info': order,
            'id': id,
            'timestamp': timestamp,
            'datetime': iso8601,
            'lastTradeTimestamp': undefined,
            'symbol': symbol,
            'type': type,
            'side': side,
            'price': price,
            'cost': cost,
            'average': average,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'status': status,
            'fee': fee,
        };
        return result;
    }

    async fetchOrdersByType (type, symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'type': type,
        };
        let market = undefined;
        if (typeof symbol !== 'undefined') {
            market = this.market (symbol);
            request['symbol'] = market['id'];
        }
        let response = await this.privatePostApiOrderTradeList (this.extend (request, params));
        if ('data' in response) {
            return this.parseOrders (response['data'], market, since, limit);
        }
        return [];
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrdersByType ('open', symbol, since, limit, params);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrdersByType ('all', symbol, since, limit, params);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let order = {
            'symbol': this.marketId (symbol),
            'type': side,
            'price': price,
            'number': amount,
        };
        let response = await this.privatePostApiOrderCoinTrust (this.extend (order, params));
        let data = response['data'];
        return {
            'info': response,
            'id': this.safeString (data, 'order_id'),
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {};
        if (typeof symbol !== 'undefined') {
            request['symbol'] = this.marketId (symbol);
        }
        if (typeof id !== 'undefined') {
            request['order_id'] = id;
        }
        let response = await this.privatePostApiOrderCancel (this.extend (request, params));
        return response;
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'] + '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (api === 'public') {
            if (Object.keys (query).length) {
                url += '?' + this.urlencode (query);
            }
        } else {
            this.checkRequiredCredentials ();
            let payload = this.urlencode ({ 'api_key': this.apiKey });
            if (Object.keys (query).length) {
                payload += '&' + this.urlencode (this.keysort (query));
            }
            let auth = payload + '&secret_key=' + this.secret;
            let signature = this.hash (this.encode (auth));
            body = payload + '&sign=' + signature;
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (code, reason, url, method, headers, body) {
        if (typeof body !== 'string')
            return; // fallback to default error handler
        if (body.length < 2)
            return; // fallback to default error handler
        if ((body[0] === '{') || (body[0] === '[')) {
            let response = JSON.parse (body);
            let feedback = this.id + ' ' + body;
            let code = this.safeValue (response, 'code');
            if (typeof code !== 'undefined') {
                if (code !== 0) {
                    //
                    // { code: 1, msg: "该币不存在,非法操作" } - returned when a required symbol parameter is missing in the request (also, maybe on other types of errors as well)
                    // { code: 1, msg: '公钥不合法' } - wrong public key
                    //
                    let message = this.safeString (response, 'msg');
                    let exceptions = this.exceptions;
                    if (message in exceptions) {
                        throw new exceptions[message] (feedback);
                    } else {
                        throw new ExchangeError (feedback);
                    }
                }
            }
        }
    }
};
<commit_msg>Fix python len used instead of .length, amount precision correction<commit_after>'use strict';

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

const Exchange = require ('./base/Exchange');
const { ExchangeError, AuthenticationError, InsufficientFunds } = require ('./base/errors');

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

module.exports = class bcex extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bcex',
            'name': 'BCEX',
            'countries': [ 'CN', 'CA' ],
            'version': '1',
            'has': {
                'fetchBalance': true,
                'fetchMarkets': true,
                'createOrder': true,
                'cancelOrder': true,
                'fetchTicker': true,
                'fetchTickers': false,
                'fetchTrades': true,
                'fetchOrder': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/43362240-21c26622-92ee-11e8-9464-5801ec526d77.jpg',
                'api': 'https://www.bcex.top',
                'www': 'https://www.bcex.top',
                'doc': 'https://www.bcex.top/api_market/market/',
                'fees': 'http://bcex.udesk.cn/hc/articles/57085',
                'referral': 'https://www.bcex.top/user/reg/type/2/pid/758978',
            },
            'api': {
                'public': {
                    'get': [
                        'Api_Market/getPriceList', // tickers
                        'Api_Order/ticker', // last ohlcv candle (ticker)
                        'Api_Order/depth', // orderbook
                        'Api_Market/getCoinTrade', // ticker
                        'Api_Order/marketOrder', // trades...
                    ],
                    'post': [
                        'Api_Market/getPriceList', // tickers
                        'Api_Order/ticker', // last ohlcv candle (ticker)
                        'Api_Order/depth', // orderbook
                        'Api_Market/getCoinTrade', // ticker
                        'Api_Order/marketOrder', // trades...
                    ],
                },
                'private': {
                    'post': [
                        'Api_Order/cancel',
                        'Api_Order/coinTrust', // limit order
                        'Api_Order/orderList', // open / all orders (my trades?)
                        'Api_Order/orderInfo',
                        'Api_Order/tradeList', // open / all orders
                        'Api_Order/trustList', // ?
                        'Api_User/userBalance',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'maker': 0.0,
                    'taker': 0.2 / 100,
                },
                'funding': {
                    'tierBased': false,
                    'percentage': false,
                    'withdraw': {
                        'ckusd': 0.0,
                        'other': 0.05 / 100,
                    },
                    'deposit': {},
                },
            },
            'exceptions': {
                '该币不存在,非法操作': ExchangeError, // { code: 1, msg: "该币不存在,非法操作" } - returned when a required symbol parameter is missing in the request (also, maybe on other types of errors as well)
                '公钥不合法': AuthenticationError, // { code: 1, msg: '公钥不合法' } - wrong public key
                '您的可用余额不足': InsufficientFunds, // { code: 1, msg: '您的可用余额不足' } - your available balance is insufficient
            },
        });
    }

    async fetchMarkets () {
        let response = await this.publicGetApiMarketGetPriceList ();
        let result = [];
        let keys = Object.keys (response);
        for (let i = 0; i < keys.length; i++) {
            let currentMarketId = keys[i];
            let currentMarkets = response[currentMarketId];
            for (let j = 0; j < currentMarkets.length; j++) {
                let market = currentMarkets[j];
                let baseId = market['coin_from'];
                let quoteId = market['coin_to'];
                let base = baseId.toUpperCase ();
                let quote = quoteId.toUpperCase ();
                base = this.commonCurrencyCode (base);
                quote = this.commonCurrencyCode (quote);
                let id = baseId + '2' + quoteId;
                let symbol = base + '/' + quote;
                let active = true;
                let precision = {
                    'amount': undefined, // todo: Look for a way to find a value.
                    'price': market['current'].split('.')[1].length, // todo: Look for a better way. For the moment, get number of decimals from last price
                };
                let limits = {
                    'amount': {
                        'min': undefined, // todo
                        'max': undefined,
                    },
                    'price': {
                        'min': undefined, // todo
                        'max': undefined,
                    },
                    'cost': {
                        'min': undefined, // todo
                        'max': undefined,
                    },
                };
                result.push ({
                    'id': id,
                    'symbol': symbol,
                    'base': base,
                    'quote': quote,
                    'baseId': baseId,
                    'quoteId': quoteId,
                    'active': active,
                    'precision': precision,
                    'limits': limits,
                    'info': market,
                });
            }
        }
        return result;
    }

    parseTrade (trade, market = undefined) {
        let symbol = undefined;
        if (typeof market !== 'undefined') {
            symbol = market['symbol'];
        }
        let timestamp = this.safeInteger2 (trade, 'date', 'created');
        if (typeof timestamp !== 'undefined') {
            timestamp = timestamp * 1000;
        }
        let id = this.safeString (trade, 'tid');
        let orderId = this.safeString (trade, 'order_id');
        let amount = this.safeFloat2 (trade, 'number', 'amount');
        let price = this.safeFloat (trade, 'price');
        let cost = undefined;
        if (typeof price !== 'undefined') {
            if (typeof amount !== 'undefined') {
                cost = amount * price;
            }
        }
        let side = this.safeString (trade, 'type');
        return {
            'info': trade,
            'id': id,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'type': undefined,
            'side': side,
            'price': price,
            'amount': amount,
            'cost': cost,
            'order': orderId,
            'fee': undefined,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'symbol': this.marketId (symbol),
        };
        if (typeof limit !== 'undefined') {
            request['limit'] = limit;
        }
        let market = this.market (symbol);
        let response = await this.publicPostApiOrderMarketOrder (this.extend (request, params));
        return this.parseTrades (response['data'], market, since, limit);
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let response = await this.privatePostApiUserUserBalance (params);
        let data = response['data'];
        let keys = Object.keys (data);
        let result = { };
        for (let i = 0; i < keys.length; i++) {
            let key = keys[i];
            let amount = this.safeFloat (data, key);
            let parts = key.split ('_');
            let currencyId = parts[0];
            let lockOrOver = parts[1];
            let code = currencyId.toUpperCase ();
            if (currencyId in this.currencies_by_id) {
                code = this.currencies_by_id[currencyId]['code'];
            } else {
                code = this.commonCurrencyCode (code);
            }
            if (!(code in result)) {
                let account = this.account ();
                result[code] = account;
            }
            if (lockOrOver === 'lock') {
                result[code]['used'] = parseFloat (amount);
            } else {
                result[code]['free'] = parseFloat (amount);
            }
        }
        keys = Object.keys (result);
        for (let i = 0; i < keys.length; i++) {
            let key = keys[i];
            let total = this.sum (result[key]['used'], result[key]['total']);
            result[key]['total'] = total;
        }
        result['info'] = data;
        return this.parseBalance (result);
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.markets[symbol];
        let request = {
            'part': market['quoteId'],
            'coin': market['baseId'],
        };
        let response = await this.publicPostApiMarketGetCoinTrade (this.extend (request, params));
        let timestamp = this.milliseconds ();
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (response, 'max'),
            'low': this.safeFloat (response, 'min'),
            'bid': this.safeFloat (response, 'buy'),
            'bidVolume': undefined,
            'ask': this.safeFloat (response, 'sale'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': this.safeFloat (response, 'price'),
            'last': this.safeFloat (response, 'price'),
            'previousClose': undefined,
            'change': undefined,
            'percentage': this.safeFloat (response, 'change_24h'),
            'average': undefined,
            'baseVolume': this.safeFloat (response, 'volume_24h'),
            'quoteVolume': undefined,
            'info': response,
        };
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let marketId = this.marketId (symbol);
        let request = {
            'symbol': marketId,
        };
        let response = await this.publicPostApiOrderDepth (this.extend (request, params));
        let data = response['data'];
        let orderbook = this.parseOrderBook (data, data['date'] * 1000);
        return orderbook;
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'symbol': market['id'],
        };
        let response = await this.privatePostApiOrderOrderList (this.extend (request, params));
        return this.parseTrades (response['data'], market, since, limit);
    }

    parseOrderStatus (status) {
        let statuses = {
            '0': 'open',
            '1': 'open', // partially filled
            '2': 'closed',
            '3': 'canceled',
        };
        if (status in statuses) {
            return statuses[status];
        }
        return status;
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'symbol': this.marketId (symbol),
            'trust_id': id,
        };
        let response = await this.privatePostApiOrderOrderInfo (this.extend (request, params));
        let order = response['data'];
        let timestamp = order['created'] * 1000;
        let status = this.parseOrderStatus (order['status']);
        let result = {
            'info': order,
            'id': id,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'lastTradeTimestamp': undefined,
            'symbol': symbol,
            'type': order['flag'],
            'side': undefined,
            'price': order['price'],
            'cost': undefined,
            'average': undefined,
            'amount': order['number'],
            'filled': order['numberdeal'],
            'remaining': order['numberover'],
            'status': status,
            'fee': undefined,
        };
        return result;
    }

    parseOrder (order, market = undefined) {
        let id = this.safeString (order, 'id');
        let timestamp = order['datetime'] * 1000;
        let iso8601 = this.iso8601 (timestamp);
        let symbol = market['symbol'];
        let type = undefined;
        let side = order['type'];
        let price = order['price'];
        let average = order['avg_price'];
        let amount = order['amount'];
        let remaining = order['amount_outstanding'];
        let filled = amount - remaining;
        let status = this.safeString (order, 'status');
        status = this.parseOrderStatus (status);
        let cost = filled * price;
        let fee = undefined;
        let result = {
            'info': order,
            'id': id,
            'timestamp': timestamp,
            'datetime': iso8601,
            'lastTradeTimestamp': undefined,
            'symbol': symbol,
            'type': type,
            'side': side,
            'price': price,
            'cost': cost,
            'average': average,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'status': status,
            'fee': fee,
        };
        return result;
    }

    async fetchOrdersByType (type, symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'type': type,
        };
        let market = undefined;
        if (typeof symbol !== 'undefined') {
            market = this.market (symbol);
            request['symbol'] = market['id'];
        }
        let response = await this.privatePostApiOrderTradeList (this.extend (request, params));
        if ('data' in response) {
            return this.parseOrders (response['data'], market, since, limit);
        }
        return [];
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrdersByType ('open', symbol, since, limit, params);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrdersByType ('all', symbol, since, limit, params);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let order = {
            'symbol': this.marketId (symbol),
            'type': side,
            'price': price,
            'number': amount,
        };
        let response = await this.privatePostApiOrderCoinTrust (this.extend (order, params));
        let data = response['data'];
        return {
            'info': response,
            'id': this.safeString (data, 'order_id'),
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {};
        if (typeof symbol !== 'undefined') {
            request['symbol'] = this.marketId (symbol);
        }
        if (typeof id !== 'undefined') {
            request['order_id'] = id;
        }
        let response = await this.privatePostApiOrderCancel (this.extend (request, params));
        return response;
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'] + '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (api === 'public') {
            if (Object.keys (query).length) {
                url += '?' + this.urlencode (query);
            }
        } else {
            this.checkRequiredCredentials ();
            let payload = this.urlencode ({ 'api_key': this.apiKey });
            if (Object.keys (query).length) {
                payload += '&' + this.urlencode (this.keysort (query));
            }
            let auth = payload + '&secret_key=' + this.secret;
            let signature = this.hash (this.encode (auth));
            body = payload + '&sign=' + signature;
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (code, reason, url, method, headers, body) {
        if (typeof body !== 'string')
            return; // fallback to default error handler
        if (body.length < 2)
            return; // fallback to default error handler
        if ((body[0] === '{') || (body[0] === '[')) {
            let response = JSON.parse (body);
            let feedback = this.id + ' ' + body;
            let code = this.safeValue (response, 'code');
            if (typeof code !== 'undefined') {
                if (code !== 0) {
                    //
                    // { code: 1, msg: "该币不存在,非法操作" } - returned when a required symbol parameter is missing in the request (also, maybe on other types of errors as well)
                    // { code: 1, msg: '公钥不合法' } - wrong public key
                    //
                    let message = this.safeString (response, 'msg');
                    let exceptions = this.exceptions;
                    if (message in exceptions) {
                        throw new exceptions[message] (feedback);
                    } else {
                        throw new ExchangeError (feedback);
                    }
                }
            }
        }
    }
};
<|endoftext|>


<commit_before>document.getElementById("calculate_button").addEventListener("click", doCalculations);

function doCalculations() {
  var variablePF = getVariablePF();
  console.log(variablePF);
  setVariablePF();
  var a = sanitizeInput(document.getElementById('entry_price').value);
  var b = sanitizeInput(document.getElementById('exit_price').value);
  var decimalLength = getDecimalLength(a,b);
  a *= Math.pow(10,decimalLength);
  a = Math.round(a)
  b *= Math.pow(10,decimalLength);
  b = Math.round(b)
  var e = a+(b-a)*variablePF;//*0.6;
  var f = b+(b-a)/2;
  var g = a-(b-a);
  a /= Math.pow(10,decimalLength);
  b /= Math.pow(10,decimalLength);
  e /= Math.pow(10,decimalLength);
  f /= Math.pow(10,decimalLength);
  g /= Math.pow(10,decimalLength);

  var c = sanitizeInput(document.getElementById('tick_size').value);
  var d = sanitizeInput(document.getElementById('dollars_per_tick').value);

  document.getElementById("0%_profit_price").innerHTML = a;
  document.getElementById("60%_profit_price").innerHTML = e;
  document.getElementById("100%_profit_price").innerHTML = b;
  document.getElementById("150%_profit_price").innerHTML = f;
  document.getElementById("-100%_profit_price").innerHTML = g;

  if (document.getElementById('tick_size').value != null &&
    document.getElementById('tick_size').value != "" &&
    document.getElementById('dollars_per_tick').value != null &&
    document.getElementById('dollars_per_tick').value != "") {
    var profit60 = Math.abs(e-a)*d/c;
    document.getElementById("60%_profit").innerHTML = "$" + profit60.toFixed(2);
    var profit100 = Math.abs((a-b)*d/c);
    document.getElementById("100%_profit").innerHTML = "$" + profit100.toFixed(2);
    var profit150 = Math.abs((a-f)*d/c);
    document.getElementById("150%_profit").innerHTML = "$" + profit150.toFixed(2);
    var profitNeg100 = -1*Math.abs((a-g)*d/c);
    var profitNeg100String = profitNeg100.toFixed(2).toString();
    document.getElementById("-100%_profit").innerHTML ="$" + profitNeg100String;
  } else {
    document.getElementById("60%_profit").innerHTML = '';
    document.getElementById("100%_profit").innerHTML = '';
    document.getElementById("150%_profit").innerHTML = '';
    document.getElementById("-100%_profit").innerHTML = '';
  }
}

function sanitizeVariablePF(variablePF) {
  var result = variablePF.trim();
  result = result.replace(/[^0-9]+?$/, "");

  if(isNaN(result) === true || result === '') {return 60};

  return result;
}

function getVariablePF() {
  var variablePF = document.getElementById("variable_pf").value;
  variablePF = sanitizeVariablePF(variablePF);

  // covert from percent to decimal number
  variablePF /= 100;

  return variablePF;
}

function setVariablePF() {
  var valueToSet = Math.round(getVariablePF()*100) + "%";

  // set in UI
  document.getElementById("variable_pf").value = valueToSet;

  // set in browser cache
  localStorage.setItem("variablePF", valueToSet);
}

function getDecimalLength(a,b) {
  var a = a.toString(10);
  var b = b.toString(10);
  var decimalLength = 0;
  if (a.split('.')[1]) {
    decimalLength = Math.max(decimalLength,a.split('.')[1].length);
  }
  if (b.split('.')[1]) {
    decimalLength = Math.max(decimalLength,b.split('.')[1].length);
  }
  var result = decimalLength + 1;
  return result;
}

function sanitizeInput(input) {
  if(input === null || input === '') {return input;}
  input = input.trim();
  if(input[0] === '$') {
    input = input.substr(1);
  }
  return input;
}

var input1 = document.getElementById("entry_price");
input1.addEventListener("keyup", runCalculateButton);

var input2 = document.getElementById("exit_price");
input2.addEventListener("keyup", runCalculateButton);

var input3 = document.getElementById("tick_size");
input3.addEventListener("keyup", runCalculateButton);

var input4 = document.getElementById("dollars_per_tick");
input4.addEventListener("keyup", runCalculateButton);

var input5 = document.getElementById("variable_pf");
input5.addEventListener("keyup", runCalculateButton);

// check browser cache for variable profit factor
if(localStorage.getItem("variablePF") !== null) {
  input5.value = localStorage.getItem("variablePF");
}

function runCalculateButton(event) {
  event.preventDefault();
  if (event.keyCode === 13) {
    document.getElementById("calculate_button").click();
  }
}
<commit_msg>account for ones place of profit factor<commit_after>document.getElementById("calculate_button").addEventListener("click", doCalculations);

function doCalculations() {
  var variablePF = getVariablePF();
  console.log(variablePF);
  setVariablePF();
  var a = sanitizeInput(document.getElementById('entry_price').value);
  var b = sanitizeInput(document.getElementById('exit_price').value);
  var decimalLength = getDecimalLength(a,b);
  a *= Math.pow(10,decimalLength);
  a = Math.round(a)
  b *= Math.pow(10,decimalLength);
  b = Math.round(b)
  var e = a+(b-a)*variablePF;//*0.6;
  var f = b+(b-a)/2;
  var g = a-(b-a);
  a /= Math.pow(10,decimalLength);
  b /= Math.pow(10,decimalLength);
  e /= Math.pow(10,decimalLength);
  f /= Math.pow(10,decimalLength);
  g /= Math.pow(10,decimalLength);

  var c = sanitizeInput(document.getElementById('tick_size').value);
  var d = sanitizeInput(document.getElementById('dollars_per_tick').value);

  document.getElementById("0%_profit_price").innerHTML = a;
  document.getElementById("60%_profit_price").innerHTML = e;
  document.getElementById("100%_profit_price").innerHTML = b;
  document.getElementById("150%_profit_price").innerHTML = f;
  document.getElementById("-100%_profit_price").innerHTML = g;

  if (document.getElementById('tick_size').value != null &&
    document.getElementById('tick_size').value != "" &&
    document.getElementById('dollars_per_tick').value != null &&
    document.getElementById('dollars_per_tick').value != "") {
    var profit60 = Math.abs(e-a)*d/c;
    document.getElementById("60%_profit").innerHTML = "$" + profit60.toFixed(2);
    var profit100 = Math.abs((a-b)*d/c);
    document.getElementById("100%_profit").innerHTML = "$" + profit100.toFixed(2);
    var profit150 = Math.abs((a-f)*d/c);
    document.getElementById("150%_profit").innerHTML = "$" + profit150.toFixed(2);
    var profitNeg100 = -1*Math.abs((a-g)*d/c);
    var profitNeg100String = profitNeg100.toFixed(2).toString();
    document.getElementById("-100%_profit").innerHTML ="$" + profitNeg100String;
  } else {
    document.getElementById("60%_profit").innerHTML = '';
    document.getElementById("100%_profit").innerHTML = '';
    document.getElementById("150%_profit").innerHTML = '';
    document.getElementById("-100%_profit").innerHTML = '';
  }
}

function sanitizeVariablePF(variablePF) {
  var result = variablePF.trim();
  result = result.replace(/[^0-9]+?$/, "");

  if(isNaN(result) === true || result === '') {return 60};

  return result;
}

function getVariablePF() {
  var variablePF = document.getElementById("variable_pf").value;
  variablePF = sanitizeVariablePF(variablePF);

  // covert from percent to decimal number
  variablePF /= 100;

  return variablePF;
}

function setVariablePF() {
  var valueToSet = Math.round(getVariablePF()*100) + "%";

  // set in UI
  document.getElementById("variable_pf").value = valueToSet;

  // set in browser cache
  localStorage.setItem("variablePF", valueToSet);
}

function getDecimalLength(a,b) {
  var a = a.toString(10);
  var b = b.toString(10);
  var decimalLength = 0;
  if (a.split('.')[1]) {
    decimalLength = Math.max(decimalLength,a.split('.')[1].length);
  }
  if (b.split('.')[1]) {
    decimalLength = Math.max(decimalLength,b.split('.')[1].length);
  }
  var result = decimalLength + 2;
  return result;
}

function sanitizeInput(input) {
  if(input === null || input === '') {return input;}
  input = input.trim();
  if(input[0] === '$') {
    input = input.substr(1);
  }
  return input;
}

var input1 = document.getElementById("entry_price");
input1.addEventListener("keyup", runCalculateButton);

var input2 = document.getElementById("exit_price");
input2.addEventListener("keyup", runCalculateButton);

var input3 = document.getElementById("tick_size");
input3.addEventListener("keyup", runCalculateButton);

var input4 = document.getElementById("dollars_per_tick");
input4.addEventListener("keyup", runCalculateButton);

var input5 = document.getElementById("variable_pf");
input5.addEventListener("keyup", runCalculateButton);

// check browser cache for variable profit factor
if(localStorage.getItem("variablePF") !== null) {
  input5.value = localStorage.getItem("variablePF");
}

function runCalculateButton(event) {
  event.preventDefault();
  if (event.keyCode === 13) {
    document.getElementById("calculate_button").click();
  }
}
<|endoftext|>


<commit_before>var Ball = function(forceX, forceY, x, y){
  this.x = x || startX;
  this.y = y || startY;
  this.gravity = gravity * Math.random();
  this.speedX = 0;
  this.speedY = 0;
  this.forceX = forceX + Math.random() * .05;
  this.forceY = forceY + Math.random() * .05;
  this.lastX = this.x;
  this.lastY = this.y;
  // this.lifetime = lifetime;
}

Ball.prototype.draw = function(){
  if(Math.abs(this.speedX) < .1 && Math.abs(this.y - cv.height) < 1 && Math.abs(this.speedY) < 1){
    this.die();
  }

  var speed = Math.sqrt(this.speedX**2 + this.speedY**2);

  this.gravity = gravity * Math.random();
  //Initial Force
  if(this.forceX != 0){
    this.speedX += this.forceX;
    this.forceX = 0;
  }

  if(this.forceY != 0){
    this.speedY += this.forceY;
    this.forceY = 0;
  }

  //Reduce horizontal speed
  if(this.speedX > 0){
    this.speedX -= drag;
  } else {
    this.speedX += drag;
  }

  for(var i in obstaclesCircles){
    var obs = obstaclesCircles[i]
    var x = obs.x - this.x
    var y = obs.y - this.y
    var distance = Math.floor(Math.sqrt( x*x + y*y ))

    if(distance < 50 * obs.size){
      var normalizeFactor = Math.max(Math.abs(this.speedX), Math.abs(this.speedY))
      var noramlizedX = (this.speedX / normalizeFactor)
      var noramlizedY = (this.speedY / normalizeFactor)
      while(distance < 50 * obs.size){
        this.x -= noramlizedX
        this.y -= noramlizedY
        x = obs.x - this.x
        y = obs.y - this.y
        distance = Math.floor(Math.sqrt( x*x + y*y ))
      }

      var xFactor = this.x - obs.x
      var yFactor = this.y - obs.y

      this.speedX += (xFactor/15)
      this.speedY += (yFactor/15)
    }
  }

  //Apply Gravity
  for(var i in centersOfGravity){
    var x = Math.floor(centersOfGravity[i].x) - this.x
    var y = Math.floor(centersOfGravity[i].y) - this.y
    var distance = Math.max(Math.floor(Math.sqrt( x*x + y*y )), 1);
    if(distance < 1000 * centersOfGravity[i].strength){
      if(distance < 50 * centersOfGravity[i].strength && centersOfGravity[i].absorb){
        centersOfGravity[i].strength += .001;
        this.die();
      }else{
        this.speedX += x/(distance*10) * centersOfGravity[i].strength
        this.speedY += y/(distance*10) * centersOfGravity[i].strength
      }
    }
  }
  this.speedY += this.gravity;

  //Bounce Off Walls
  if(borderOn){
    if(this.x > cv.width){
      this.x = cv.width;
      this.speedX *= -1;
    }
    if(this.x < 0){
      this.x = 0
      this.speedX *= -1;
    }
    if(this.y >= cv.height){
      this.y = cv.height;
      this.speedY *= dampY;
      this.speedX *= dampX;
    }
    if(this.y <= 0){
      this.y = 0;
      this.speedY *= dampY;
      this.speedX *= dampX;
    }
  } else {
    if(this.x > cv.width*2 || this.x < -(cv.width*2) || this.y >= cv.height*2 || this.y < (-cv.height*2)){
      this.die()
    }
  }

  //Apply speeds to coordinates
  this.x += this.speedX;
  this.y += this.speedY;

  // Color based on speed
  var colorFactor = Math.min(speed, 8) / 8;
  var color = mixColor(minColor, maxColor, colorFactor);
  cv.ctx.strokeStyle = color;

  // Circular front - Looks good but is resource intensive
  // cv.ctx.beginPath();
  // cv.ctx.arc(this.x, this.y, thickness/2, 0, 2 * Math.PI, false);
  // cv.ctx.fillStyle = color;
  // cv.ctx.fill();

  // Draw path
  cv.ctx.beginPath();
  cv.ctx.moveTo(this.lastX, this.lastY);
  cv.ctx.lineTo(this.x, this.y);
  cv.ctx.stroke();
  cv.ctx.closePath();

  this.lastX = this.x;
  this.lastY = this.y;
};

Ball.prototype.die = function(){
  balls.splice(balls.indexOf(this), 1);
}

<commit_msg>Normalize obstacle forces based on ball speed<commit_after>var Ball = function(forceX, forceY, x, y){
  this.x = x || startX;
  this.y = y || startY;
  this.gravity = gravity * Math.random();
  this.speedX = 0;
  this.speedY = 0;
  this.forceX = forceX + Math.random() * .05;
  this.forceY = forceY + Math.random() * .05;
  this.lastX = this.x;
  this.lastY = this.y;
  // this.lifetime = lifetime;
}

Ball.prototype.draw = function(){
  if(Math.abs(this.speedX) < .1 && Math.abs(this.y - cv.height) < 1 && Math.abs(this.speedY) < 1){
    this.die();
  }

  var speed = Math.sqrt(this.speedX**2 + this.speedY**2);

  this.gravity = gravity * Math.random();
  //Initial Force
  if(this.forceX != 0){
    this.speedX += this.forceX;
    this.forceX = 0;
  }

  if(this.forceY != 0){
    this.speedY += this.forceY;
    this.forceY = 0;
  }

  //Reduce horizontal speed
  if(this.speedX > 0){
    this.speedX -= drag;
  } else {
    this.speedX += drag;
  }

  for(var i in obstaclesCircles){
    var obs = obstaclesCircles[i]
    var x = obs.x - this.x
    var y = obs.y - this.y
    var distance = Math.floor(Math.sqrt( x*x + y*y ))

    if(distance < 50 * obs.size){
      var normalizeFactor = Math.max(Math.abs(this.speedX), Math.abs(this.speedY))
      var noramlizedX = (this.speedX / normalizeFactor)
      var noramlizedY = (this.speedY / normalizeFactor)
      while(distance < 50 * obs.size){
        this.x -= noramlizedX
        this.y -= noramlizedY
        x = obs.x - this.x
        y = obs.y - this.y
        distance = Math.floor(Math.sqrt( x*x + y*y ))
      }

      var xFactor = this.x - obs.x
      var yFactor = this.y - obs.y

      this.speedX += (xFactor*(speed / 35  ) )
      this.speedY += (yFactor*(speed / 35  ) )
    }
  }

  //Apply Gravity
  for(var i in centersOfGravity){
    var x = Math.floor(centersOfGravity[i].x) - this.x
    var y = Math.floor(centersOfGravity[i].y) - this.y
    var distance = Math.max(Math.floor(Math.sqrt( x*x + y*y )), 1);
    if(distance < 1000 * centersOfGravity[i].strength){
      if(distance < 50 * centersOfGravity[i].strength && centersOfGravity[i].absorb){
        centersOfGravity[i].strength += .001;
        this.die();
      }else{
        this.speedX += x/(distance*10) * centersOfGravity[i].strength
        this.speedY += y/(distance*10) * centersOfGravity[i].strength
      }
    }
  }
  this.speedY += this.gravity;

  //Bounce Off Walls
  if(borderOn){
    if(this.x > cv.width){
      this.x = cv.width;
      this.speedX *= -1;
    }
    if(this.x < 0){
      this.x = 0
      this.speedX *= -1;
    }
    if(this.y >= cv.height){
      this.y = cv.height;
      this.speedY *= dampY;
      this.speedX *= dampX;
    }
    if(this.y <= 0){
      this.y = 0;
      this.speedY *= dampY;
      this.speedX *= dampX;
    }
  } else {
    if(this.x > cv.width*2 || this.x < -(cv.width*2) || this.y >= cv.height*2 || this.y < (-cv.height*2)){
      this.die()
    }
  }

  //Apply speeds to coordinates
  this.x += this.speedX;
  this.y += this.speedY;

  // Color based on speed
  var colorFactor = Math.min(speed, 8) / 8;
  var color = mixColor(minColor, maxColor, colorFactor);
  cv.ctx.strokeStyle = color;

  // Circular front - Looks good but is resource intensive
  // cv.ctx.beginPath();
  // cv.ctx.arc(this.x, this.y, thickness/2, 0, 2 * Math.PI, false);
  // cv.ctx.fillStyle = color;
  // cv.ctx.fill();

  // Draw path
  cv.ctx.beginPath();
  cv.ctx.moveTo(this.lastX, this.lastY);
  cv.ctx.lineTo(this.x, this.y);
  cv.ctx.stroke();
  cv.ctx.closePath();

  this.lastX = this.x;
  this.lastY = this.y;
};

Ball.prototype.die = function(){
  balls.splice(balls.indexOf(this), 1);
}

<|endoftext|>


<commit_before>var Promise = TrelloPowerUp.Promise;
var t = TrelloPowerUp.iframe();

//var oauthUrl = 'https://trello.com/1/authorize?expiration=never' +
//  '&name=[APPNAME]&scope=read&key=[APIKEY]&callback_method=fragment' +
//  '&return_url=[RETURNURL]';

  var oauthUrl = 'https://martinm78.github.io/loginFromTrello.html';

var tokenLooksValid = function(token) {
  //return /^[0-9a-f]{64}$/.test(token);
  return true;
}

var authorizeOpts = {
  height: 680,
  width: 580,
  validToken: tokenLooksValid
};

var authBtn = document.getElementById('authorize');

authBtn.addEventListener('click', function() {

  t.authorize(oauthUrl, authorizeOpts)
  .then(function(token) {
	console.log('then token:' + token);
    return t.set('organization', 'private', 'token', token)
    .catch(t.NotHandled, function() {
      // fall back to storing at board level
      return t.set('board', 'private', 'token', token);
    });
  })
  .then(function() {
	console.log('then closePopup');
    // now that the token is stored, we can close this popup
    // you might alternatively choose to open a new popup
		console.log(this.token);
	$.ajax({

		url:"https://martinm78.github.io/ajax.html?token="+t.get('board', 'private', 'token'),
		dataType: 'json',
		success:function(json){
			// do stuff with json (in this case an array)
			alert("Success");
		},
		error:function(jqXHR,textStatus){
			alert("Error:"+textStatus);
		}
	});

	//return t.closePopup();
  });
});

<commit_msg>cambio prueba<commit_after>var Promise = TrelloPowerUp.Promise;
var t = TrelloPowerUp.iframe();

//var oauthUrl = 'https://trello.com/1/authorize?expiration=never' +
//  '&name=[APPNAME]&scope=read&key=[APIKEY]&callback_method=fragment' +
//  '&return_url=[RETURNURL]';

  var oauthUrl = 'https://martinm78.github.io/loginFromTrello.html';

var tokenLooksValid = function(token) {
  //return /^[0-9a-f]{64}$/.test(token);
  return true;
}

var authorizeOpts = {
  height: 680,
  width: 580,
  validToken: tokenLooksValid
};

var authBtn = document.getElementById('authorize');

authBtn.addEventListener('click', function() {

  t.authorize(oauthUrl, authorizeOpts)
  .then(function(token) {
	console.log('then token:' + token);
    return t.set('organization', 'private', 'token', token)
    .catch(t.NotHandled, function() {
      // fall back to storing at board level
      return t.set('board', 'private', 'token', token);
    });
  })
  .then(function(v) {
	console.log('then closePopup');
    // now that the token is stored, we can close this popup
    // you might alternatively choose to open a new popup
		console.log(v);
	$.ajax({

		url:"https://martinm78.github.io/ajax.html?token="+t.get('board', 'private', 'token'),
		dataType: 'json',
		success:function(json){
			// do stuff with json (in this case an array)
			alert("Success");
		},
		error:function(jqXHR,textStatus){
			alert("Error:"+textStatus);
		}
	});

	//return t.closePopup();
  });
});

<|endoftext|>


<commit_before>$(document).ready(function() {
    // keep widgets ordered
    keepWidgetOrdered();

    // hide localstored hidden widgets
    keepWidgetHidden();

    // enable popovers
    $(".pop").popover();

   // activate tooltips on hover
   $("[data-toggle='tooltip']").tooltip({trigger: 'hover', placement:'right'});

    dashboard.getAll();
}).on("click", ".js-smoothscroll", function(event) {
    event.preventDefault();
    var target = $(this.hash).parent();
    pulseElement(target, 8, 400);

    $("html,body").animate({
        scrollTop: target.offset().top - 130
    }, 1000);
}).on("click", ".js-refresh-info", function(event) {
    event.preventDefault();
    var target = event.target;
    var item = target.id.split("-").splice(-1)[0];

    // if the refresh icon is click (where in a ) target will not have an id, so grab its parent instead
    if(target.id == "") {
        var parent = $(target).parent()[0];
        item = parent.id.split("-").splice(-1)[0];
    }

    dashboard.fnMap[item]();
});

// Handle for cancelling active effect.
var pulsing = {
    element: null,
    timeoutIDs: [],
    resetfn: function() {
        pulsing.element = null;
        pulsing.timeoutIDs = [];
    }
};

/**
 * Applies a pulse effect to the specified element. If triggered while already
 * active the ongoing effect is cancelled immediately.
 *
 * @param {HTMLElement} element The element to apply the effect to.
 * @param {Number} times How many pulses.
 * @param {Number} interval Milliseconds between pulses.
 */
function pulseElement(element, times, interval) {
    if (pulsing.element) {
        pulsing.element.removeClass("pulse").
            parent().removeClass("pulse-border");
        pulsing.timeoutIDs.forEach(function(ID) {
            clearTimeout(ID);
        });
        pulsing.timeoutIDs = [];
    }
    pulsing.element = element;
    var parent = element.parent();
    var f = function() {
        element.toggleClass("pulse");
        parent.toggleClass("pulse-border");
    };

    pulsing.timeoutIDs.push(setTimeout(pulsing.resetfn,
                                       (times + 1) * interval));
    for (; times > 0; --times) {
        pulsing.timeoutIDs.push(setTimeout(f, times * interval));
    }
}

/**
 * Adds jQuery UI sortable portlet functionality to widgets
 *
 *
 */

$( "#widgets" ).sortable({
      handle: ".widget-header",
      cancel: "#filter-ps",
      cursor: "move",
      opacity: 0.7,
      scrollSensitivity:10,
      tolerance: 'pointer',
      stop: function(event, ui) {
            // save widget order in localstorage
            var newOrder = new Array();
            $('.widget').each(function() {
                newOrder.push($(this).attr("id"));
            });
            localStorage.setItem('positions', JSON.stringify(newOrder));
        }
 });

/**
 *
 * Widget hide functionality
 *
**/
// general cached DOM objects
closedWidgetCount = $('#closed-widget-count'),
closedWidgets = $('#closed-widget-list');
allWidgets = $('.widget');

// Close all widgets
$('#close-all-widgets').click(function(){

    allWidgets.each(function(index){
	hideWidget($(this), 400);
    });

});

// Open all widgets
$('#open-all-widgets').click(function(){

    allWidgets.each(function(index){
	openWidget($(this), $(this).attr('id'), 500);
    });
});

// attach a close button to all widget headers
$('.widget-header').append('

');

// hide / close widget function
$('.hide-widget').live('click',function(){
    var widget = $(this).parent().parent();
    hideWidget(widget, 300);
});

// unhide closed widget
$('.open-widget').live('click',function(){
    // cache DOM objects/data used in this function
    var widgetIdentifier = $(this).data('id');
    var widget = $( "#" + widgetIdentifier );
    var navItem = $(this).parent();

    openWidget(widget,widgetIdentifier,500);

    // remove item from closed-widget-list
    navItem.remove();

});

function openWidget(widget, widgetIdentifier, speed){

    // decrement closed-widget-count
    if(widget.is(":hidden")) {
        closedWidgetCount.text( Number(closedWidgetCount.text()) - 1);
    }

    // unhide widget
    widget.show(500);

     // remove widget from localstorage
    var localData = JSON.parse(window.localStorage.getItem('hidden'));
    for(var i = localData.length; i--;){
        if (localData[i] == widgetIdentifier) {
            localData.splice(i, 1);
        }
    }
    localStorage.setItem('hidden', JSON.stringify(localData));
}

function hideWidget(widget, speed){
    // cache DOM objects/data used in this function
    var widgetName = widget.find('.widget-header h3').text();
    var widgetIdentifier = widget.attr('id');

    // update count
    if(!widget.is(":hidden")) {
        closedWidgetCount.text( Number(closedWidgetCount.text()) + 1);
    }

    // hide widget from DOM
    widget.hide(speed);

    // add to hidden list
    closedWidgets.append('
  '+widgetName+'
');

    // add widget to localstorage (and create item if needed)
    var localData = JSON.parse(window.localStorage.getItem('hidden'));
    if(localData == null) {
        hidden = new Array();
        hidden.push(widgetIdentifier);
        localStorage.setItem('hidden', JSON.stringify(hidden));
    }
    else{
        if (!isInArray(localData, widgetIdentifier)) {
            localData.push(widgetIdentifier);
            localStorage.setItem('hidden', JSON.stringify(localData));
        }
    }
}

function keepWidgetHidden(){
    var localData = JSON.parse(window.localStorage.getItem('hidden'));
    if(localData!=null) {
        $.each(localData, function(i,value){
             hideWidget( $("#" + value), 0 );
        });
    }
}

function keepWidgetOrdered(){
    var localData = JSON.parse(window.localStorage.getItem('positions'));
    if(localData!=null) {
        $.each(localData, function(i,value){
            var widgetId ="#" + value;
            $("#widgets").append($(widgetId).parent());
        });
    }
}

function isInArray(array, search)
{
    return (array.indexOf(search) >= 0) ? true : false;
}
<commit_msg>fix #173<commit_after>$(document).ready(function() {
    // keep widgets ordered
    keepWidgetOrdered();

    // hide localstored hidden widgets
    keepWidgetHidden();

    // enable popovers
    $(".pop").popover();

   // activate tooltips on hover
   $("[data-toggle='tooltip']").tooltip({trigger: 'hover', placement:'right'});

    dashboard.getAll();
}).on("click", ".js-smoothscroll", function(event) {
    event.preventDefault();
    var target = $(this.hash).parent();
    pulseElement(target, 8, 400);

    $("html,body").animate({
        scrollTop: target.offset().top - 130
    }, 1000);
}).on("click", ".js-refresh-info", function(event) {
    event.preventDefault();
    var target = event.target;
    var item = target.id.split("-").splice(-1)[0];

    // if the refresh icon is click (where in a ) target will not have an id, so grab its parent instead
    if(target.id == "") {
        var parent = $(target).parent()[0];
        item = parent.id.split("-").splice(-1)[0];
    }

    dashboard.fnMap[item]();
});

// Handle for cancelling active effect.
var pulsing = {
    element: null,
    timeoutIDs: [],
    resetfn: function() {
        pulsing.element = null;
        pulsing.timeoutIDs = [];
    }
};

/**
 * Applies a pulse effect to the specified element. If triggered while already
 * active the ongoing effect is cancelled immediately.
 *
 * @param {HTMLElement} element The element to apply the effect to.
 * @param {Number} times How many pulses.
 * @param {Number} interval Milliseconds between pulses.
 */
function pulseElement(element, times, interval) {
    if (pulsing.element) {
        pulsing.element.removeClass("pulse").
            parent().removeClass("pulse-border");
        pulsing.timeoutIDs.forEach(function(ID) {
            clearTimeout(ID);
        });
        pulsing.timeoutIDs = [];
    }
    pulsing.element = element;
    var parent = element.parent();
    var f = function() {
        element.toggleClass("pulse");
        parent.toggleClass("pulse-border");
    };

    pulsing.timeoutIDs.push(setTimeout(pulsing.resetfn,
                                       (times + 1) * interval));
    for (; times > 0; --times) {
        pulsing.timeoutIDs.push(setTimeout(f, times * interval));
    }
}

/**
 * Adds jQuery UI sortable portlet functionality to widgets
 *
 *
 */

$( "#widgets" ).sortable({
      handle: ".widget-header",
      cancel: "#filter-ps",
      cursor: "move",
      opacity: 0.7,
      scrollSensitivity:10,
      tolerance: 'pointer',
      stop: function(event, ui) {
            // save widget order in localstorage
            var newOrder = new Array();
            $('.widget').each(function() {
                newOrder.push($(this).attr("id"));
            });
            localStorage.setItem('positions', JSON.stringify(newOrder));
        }
 });

/**
 *
 * Widget hide functionality
 *
**/
// general cached DOM objects
closedWidgetCount = $('#closed-widget-count'),
closedWidgets = $('#closed-widget-list');
allWidgets = $('.widget');

// Close all widgets
$('#close-all-widgets').click(function(){
    allWidgets.each(function(index){
        if ($(this).is(":visible")){
	       hideWidget($(this), 400);
        }
    });
});

// Open all widgets
$('#open-all-widgets').click(function(){
    allWidgets.each(function(index){
	openWidget($(this), $(this).attr('id'), 500);
    });
});

// attach a close button to all widget headers
$('.widget-header').append('

');

// hide / close widget function
$('.hide-widget').live('click',function(){
    var widget = $(this).parent().parent();
    hideWidget(widget, 300);
});

// unhide closed widget
$('.open-widget').live('click',function(){
    // cache DOM objects/data used in this function
    var widgetIdentifier = $(this).data('id');
    var widget = $( "#" + widgetIdentifier );
    var navItem = $(this).parent();

    openWidget(widget,widgetIdentifier,500);

    // remove item from closed-widget-list
    navItem.remove();

});

function openWidget(widget, widgetIdentifier, speed){

    // decrement closed-widget-count
    if(widget.is(":hidden")) {
        closedWidgetCount.text( Number(closedWidgetCount.text()) - 1);
    }

    // unhide widget
    widget.show(500);

     // remove widget from localstorage
    var localData = JSON.parse(window.localStorage.getItem('hidden'));
    for(var i = localData.length; i--;){
        if (localData[i] == widgetIdentifier) {
            localData.splice(i, 1);
        }
    }
    localStorage.setItem('hidden', JSON.stringify(localData));
}

function hideWidget(widget, speed){
    // cache DOM objects/data used in this function
    var widgetName = widget.find('.widget-header h3').text();
    var widgetIdentifier = widget.attr('id');

    // update count
    if(!widget.is(":hidden")) {
        closedWidgetCount.text( Number(closedWidgetCount.text()) + 1);
    }

    // hide widget from DOM
    widget.hide(speed);

    // add to hidden list
    closedWidgets.append('
  '+widgetName+'
');

    // add widget to localstorage (and create item if needed)
    var localData = JSON.parse(window.localStorage.getItem('hidden'));
    if(localData == null) {
        hidden = new Array();
        hidden.push(widgetIdentifier);
        localStorage.setItem('hidden', JSON.stringify(hidden));
    }
    else{
        if (!isInArray(localData, widgetIdentifier)) {
            localData.push(widgetIdentifier);
            localStorage.setItem('hidden', JSON.stringify(localData));
        }
    }
}

function keepWidgetHidden(){
    var localData = JSON.parse(window.localStorage.getItem('hidden'));
    if(localData!=null) {
        $.each(localData, function(i,value){
             hideWidget( $("#" + value), 0 );
        });
    }
}

function keepWidgetOrdered(){
    var localData = JSON.parse(window.localStorage.getItem('positions'));
    if(localData!=null) {
        $.each(localData, function(i,value){
            var widgetId ="#" + value;
            $("#widgets").append($(widgetId).parent());
        });
    }
}

function isInArray(array, search)
{
    return (array.indexOf(search) >= 0) ? true : false;
}
<|endoftext|>


<commit_before>'use strict';

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

const Exchange = require ('./base/Exchange');
const { ExchangeError } = require ('./base/errors');

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

module.exports = class ccex extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'ccex',
            'name': 'C-CEX',
            'countries': [ 'DE', 'EU' ],
            'rateLimit': 1500,
            'has': {
                'CORS': false,
                'fetchTickers': true,
                'fetchOrderBooks': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/27766433-16881f90-5ed8-11e7-92f8-3d92cc747a6c.jpg',
                'api': {
                    'tickers': 'https://c-cex.com/t',
                    'public': 'https://c-cex.com/t/api_pub.html',
                    'private': 'https://c-cex.com/t/api.html',
                },
                'www': 'https://c-cex.com',
                'doc': 'https://c-cex.com/?id=api',
            },
            'api': {
                'tickers': {
                    'get': [
                        'coinnames',
                        '{market}',
                        'pairs',
                        'prices',
                        'volume_{coin}',
                    ],
                },
                'public': {
                    'get': [
                        'balancedistribution',
                        'markethistory',
                        'markets',
                        'marketsummaries',
                        'orderbook',
                        'fullorderbook',
                    ],
                },
                'private': {
                    'get': [
                        'buylimit',
                        'cancel',
                        'getbalance',
                        'getbalances',
                        'getopenorders',
                        'getorder',
                        'getorderhistory',
                        'mytrades',
                        'selllimit',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'taker': 0.2 / 100,
                    'maker': 0.2 / 100,
                },
            },
        });
    }

    commonCurrencyCode (currency) {
        if (currency === 'IOT')
            return 'IoTcoin';
        if (currency === 'BLC')
            return 'Cryptobullcoin';
        if (currency === 'XID')
            return 'InternationalDiamond';
        return currency;
    }

    async fetchMarkets () {
        let markets = await this.publicGetMarkets ();
        let result = [];
        for (let p = 0; p < markets['result'].length; p++) {
            let market = markets['result'][p];
            let id = market['MarketName'];
            let base = market['MarketCurrency'];
            let quote = market['BaseCurrency'];
            base = this.commonCurrencyCode (base);
            quote = this.commonCurrencyCode (quote);
            let symbol = base + '/' + quote;
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let response = await this.privateGetGetbalances ();
        let balances = response['result'];
        let result = { 'info': balances };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let code = balance['Currency'];
            let currency = this.commonCurrencyCode (code);
            let account = {
                'free': balance['Available'],
                'used': balance['Pending'],
                'total': balance['Balance'],
            };
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'market': this.marketId (symbol),
            'type': 'both',
        };
        if (typeof limit !== 'undefined')
            request['depth'] = limit; // 100
        let response = await this.publicGetOrderbook (this.extend (request, params));
        let orderbook = response['result'];
        return this.parseOrderBook (orderbook, undefined, 'buy', 'sell', 'Rate', 'Quantity');
    }

    async fetchOrderBooks (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let orderbooks = {};
        let response = await this.publicGetFullorderbook ();
        let types = Object.keys (response['result']);
        for (let i = 0; i < types.length; i++) {
            let type = types[i];
            let bidasks = response['result'][type];
            let bidasksByMarketId = this.groupBy (bidasks, 'Market');
            let marketIds = Object.keys (bidasksByMarketId);
            for (let j = 0; j < marketIds.length; j++) {
                let marketId = marketIds[j];
                let symbol = marketId.toUpperCase ();
                let side = type;
                if (symbol in this.markets_by_id) {
                    let market = this.markets_by_id[symbol];
                    symbol = market['symbol'];
                } else {
                    let [ base, quote ] = symbol.split ('-');
                    let invertedId = quote + '-' + base;
                    if (invertedId in this.markets_by_id) {
                        let market = this.markets_by_id[invertedId];
                        symbol = market['symbol'];
                    }
                }
                if (!(symbol in orderbooks))
                    orderbooks[symbol] = {};
                orderbooks[symbol][side] = bidasksByMarketId[marketId];
            }
        }
        let result = {};
        let keys = Object.keys (orderbooks);
        for (let k = 0; k < keys.length; k++) {
            let key = keys[k];
            result[key] = this.parseOrderBook (orderbooks[key], undefined, 'buy', 'sell', 'Rate', 'Quantity');
        }
        return result;
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = ticker['updated'] * 1000;
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': parseFloat (ticker['high']),
            'low': parseFloat (ticker['low']),
            'bid': parseFloat (ticker['buy']),
            'ask': parseFloat (ticker['sell']),
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'first': undefined,
            'last': parseFloat (ticker['lastprice']),
            'change': undefined,
            'percentage': undefined,
            'average': parseFloat (ticker['avg']),
            'baseVolume': undefined,
            'quoteVolume': this.safeFloat (ticker, 'buysupport'),
            'info': ticker,
        };
    }

    async fetchTickers (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let tickers = await this.tickersGetPrices (params);
        let result = { 'info': tickers };
        let ids = Object.keys (tickers);
        for (let i = 0; i < ids.length; i++) {
            let id = ids[i];
            let ticker = tickers[id];
            let uppercase = id.toUpperCase ();
            let market = undefined;
            let symbol = undefined;
            if (uppercase in this.markets_by_id) {
                market = this.markets_by_id[uppercase];
                symbol = market['symbol'];
            } else {
                let [ base, quote ] = uppercase.split ('-');
                base = this.commonCurrencyCode (base);
                quote = this.commonCurrencyCode (quote);
                symbol = base + '/' + quote;
            }
            result[symbol] = this.parseTicker (ticker, market);
        }
        return result;
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.tickersGetMarket (this.extend ({
            'market': market['id'].toLowerCase (),
        }, params));
        let ticker = response['ticker'];
        return this.parseTicker (ticker, market);
    }

    parseTrade (trade, market) {
        let timestamp = this.parse8601 (trade['TimeStamp']);
        return {
            'id': trade['Id'].toString (),
            'info': trade,
            'order': undefined,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'type': undefined,
            'side': trade['OrderType'].toLowerCase (),
            'price': trade['Price'],
            'amount': trade['Quantity'],
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.publicGetMarkethistory (this.extend ({
            'market': market['id'],
            'type': 'both',
            'depth': 100,
        }, params));
        return this.parseTrades (response['result'], market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let method = 'privateGet' + this.capitalize (side) + type;
        let response = await this[method] (this.extend ({
            'market': this.marketId (symbol),
            'quantity': amount,
            'rate': price,
        }, params));
        return {
            'info': response,
            'id': response['result']['uuid'],
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        return await this.privateGetCancel ({ 'uuid': id });
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'][api];
        if (api === 'private') {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ().toString ();
            let query = this.keysort (this.extend ({
                'a': path,
                'apikey': this.apiKey,
                'nonce': nonce,
            }, params));
            url += '?' + this.urlencode (query);
            headers = { 'apisign': this.hmac (this.encode (url), this.encode (this.secret), 'sha512') };
        } else if (api === 'public') {
            url += '?' + this.urlencode (this.extend ({
                'a': 'get' + path,
            }, params));
        } else {
            url += '/' + this.implodeParams (path, params) + '.json';
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let response = await this.fetch2 (path, api, method, params, headers, body);
        if (api === 'tickers')
            return response;
        if ('success' in response)
            if (response['success'])
                return response;
        throw new ExchangeError (this.id + ' ' + this.json (response));
    }
};
<commit_msg>ccex fetchMarkets → pairs.json fix #2246<commit_after>'use strict';

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

const Exchange = require ('./base/Exchange');
const { ExchangeError } = require ('./base/errors');

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

module.exports = class ccex extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'ccex',
            'name': 'C-CEX',
            'countries': [ 'DE', 'EU' ],
            'rateLimit': 1500,
            'has': {
                'CORS': false,
                'fetchTickers': true,
                'fetchOrderBooks': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/27766433-16881f90-5ed8-11e7-92f8-3d92cc747a6c.jpg',
                'api': {
                    'web': 'https://c-cex.com/t',
                    'public': 'https://c-cex.com/t/api_pub.html',
                    'private': 'https://c-cex.com/t/api.html',
                },
                'www': 'https://c-cex.com',
                'doc': 'https://c-cex.com/?id=api',
            },
            'api': {
                'web': {
                    'get': [
                        'coinnames',
                        '{market}',
                        'pairs',
                        'prices',
                        'volume_{coin}',
                    ],
                },
                'public': {
                    'get': [
                        'balancedistribution',
                        'markethistory',
                        'markets',
                        'marketsummaries',
                        'orderbook',
                        'fullorderbook',
                    ],
                },
                'private': {
                    'get': [
                        'buylimit',
                        'cancel',
                        'getbalance',
                        'getbalances',
                        'getopenorders',
                        'getorder',
                        'getorderhistory',
                        'mytrades',
                        'selllimit',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'taker': 0.2 / 100,
                    'maker': 0.2 / 100,
                },
            },
        });
    }

    commonCurrencyCode (currency) {
        if (currency === 'IOT')
            return 'IoTcoin';
        if (currency === 'BLC')
            return 'Cryptobullcoin';
        if (currency === 'XID')
            return 'InternationalDiamond';
        return currency;
    }

    async fetchMarkets () {
        let result = {};
        let response = await this.webGetPairs ();
        let markets = response['pairs'];
        for (let i = 0; i < markets.length; i++) {
            let id = markets[i];
            let [ baseId, quoteId ] = id.split ('-');
            let base = baseId.toUpperCase ();
            let quote = quoteId.toUpperCase ();
            base = this.commonCurrencyCode (base);
            quote = this.commonCurrencyCode (quote);
            let symbol = base + '/' + quote;
            result[symbol] = {
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'info': id,
            };
        }
        // an alternative documented parser
        //     let markets = await this.publicGetMarkets ();
        //     for (let p = 0; p < markets['result'].length; p++) {
        //         let market = markets['result'][p];
        //         let id = market['MarketName'];
        //         let base = market['MarketCurrency'];
        //         let quote = market['BaseCurrency'];
        //         base = this.commonCurrencyCode (base);
        //         quote = this.commonCurrencyCode (quote);
        //         let symbol = base + '/' + quote;
        //         result.push ({
        //             'id': id,
        //             'symbol': symbol,
        //             'base': base,
        //             'quote': quote,
        //             'info': market,
        //         });
        //     }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let response = await this.privateGetGetbalances ();
        let balances = response['result'];
        let result = { 'info': balances };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let code = balance['Currency'];
            let currency = this.commonCurrencyCode (code);
            let account = {
                'free': balance['Available'],
                'used': balance['Pending'],
                'total': balance['Balance'],
            };
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'market': this.marketId (symbol),
            'type': 'both',
        };
        if (typeof limit !== 'undefined')
            request['depth'] = limit; // 100
        let response = await this.publicGetOrderbook (this.extend (request, params));
        let orderbook = response['result'];
        return this.parseOrderBook (orderbook, undefined, 'buy', 'sell', 'Rate', 'Quantity');
    }

    async fetchOrderBooks (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let orderbooks = {};
        let response = await this.publicGetFullorderbook ();
        let types = Object.keys (response['result']);
        for (let i = 0; i < types.length; i++) {
            let type = types[i];
            let bidasks = response['result'][type];
            let bidasksByMarketId = this.groupBy (bidasks, 'Market');
            let marketIds = Object.keys (bidasksByMarketId);
            for (let j = 0; j < marketIds.length; j++) {
                let marketId = marketIds[j];
                let symbol = marketId.toUpperCase ();
                let side = type;
                if (symbol in this.markets_by_id) {
                    let market = this.markets_by_id[symbol];
                    symbol = market['symbol'];
                } else {
                    let [ base, quote ] = symbol.split ('-');
                    let invertedId = quote + '-' + base;
                    if (invertedId in this.markets_by_id) {
                        let market = this.markets_by_id[invertedId];
                        symbol = market['symbol'];
                    }
                }
                if (!(symbol in orderbooks))
                    orderbooks[symbol] = {};
                orderbooks[symbol][side] = bidasksByMarketId[marketId];
            }
        }
        let result = {};
        let keys = Object.keys (orderbooks);
        for (let k = 0; k < keys.length; k++) {
            let key = keys[k];
            result[key] = this.parseOrderBook (orderbooks[key], undefined, 'buy', 'sell', 'Rate', 'Quantity');
        }
        return result;
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = ticker['updated'] * 1000;
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': parseFloat (ticker['high']),
            'low': parseFloat (ticker['low']),
            'bid': parseFloat (ticker['buy']),
            'ask': parseFloat (ticker['sell']),
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'first': undefined,
            'last': parseFloat (ticker['lastprice']),
            'change': undefined,
            'percentage': undefined,
            'average': parseFloat (ticker['avg']),
            'baseVolume': undefined,
            'quoteVolume': this.safeFloat (ticker, 'buysupport'),
            'info': ticker,
        };
    }

    async fetchTickers (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let tickers = await this.webGetPrices (params);
        let result = { 'info': tickers };
        let ids = Object.keys (tickers);
        for (let i = 0; i < ids.length; i++) {
            let id = ids[i];
            let ticker = tickers[id];
            let uppercase = id.toUpperCase ();
            let market = undefined;
            let symbol = undefined;
            if (uppercase in this.markets_by_id) {
                market = this.markets_by_id[uppercase];
                symbol = market['symbol'];
            } else {
                let [ base, quote ] = uppercase.split ('-');
                base = this.commonCurrencyCode (base);
                quote = this.commonCurrencyCode (quote);
                symbol = base + '/' + quote;
            }
            result[symbol] = this.parseTicker (ticker, market);
        }
        return result;
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.webGetMarket (this.extend ({
            'market': market['id'].toLowerCase (),
        }, params));
        let ticker = response['ticker'];
        return this.parseTicker (ticker, market);
    }

    parseTrade (trade, market) {
        let timestamp = this.parse8601 (trade['TimeStamp']);
        return {
            'id': trade['Id'].toString (),
            'info': trade,
            'order': undefined,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'type': undefined,
            'side': trade['OrderType'].toLowerCase (),
            'price': trade['Price'],
            'amount': trade['Quantity'],
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.publicGetMarkethistory (this.extend ({
            'market': market['id'],
            'type': 'both',
            'depth': 100,
        }, params));
        return this.parseTrades (response['result'], market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let method = 'privateGet' + this.capitalize (side) + type;
        let response = await this[method] (this.extend ({
            'market': this.marketId (symbol),
            'quantity': amount,
            'rate': price,
        }, params));
        return {
            'info': response,
            'id': response['result']['uuid'],
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        return await this.privateGetCancel ({ 'uuid': id });
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'][api];
        if (api === 'private') {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ().toString ();
            let query = this.keysort (this.extend ({
                'a': path,
                'apikey': this.apiKey,
                'nonce': nonce,
            }, params));
            url += '?' + this.urlencode (query);
            headers = { 'apisign': this.hmac (this.encode (url), this.encode (this.secret), 'sha512') };
        } else if (api === 'public') {
            url += '?' + this.urlencode (this.extend ({
                'a': 'get' + path,
            }, params));
        } else {
            url += '/' + this.implodeParams (path, params) + '.json';
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let response = await this.fetch2 (path, api, method, params, headers, body);
        if (api === 'web')
            return response;
        if ('success' in response)
            if (response['success'])
                return response;
        throw new ExchangeError (this.id + ' ' + this.json (response));
    }
};
<|endoftext|>


<commit_before>/**
 * Created by Administrator on 2016/11/8 0008.
 */
;(function(){
    'use strict'

    var $content = $("#task_content"),
        $addTaskBtn = $("#add_task_btn"),
        $task_detail = $(".task_detail"),
        $task_detail_mask = $(".task_detail_mask"),
        task_list = [],
        $delete_task_btn,
        $detail_task_btn;

    init();

    $addTaskBtn.on("click", function(e){
        var new_task = {};
        /* 获取新Task的值 */
        new_task.content = $content.val();
        /* 如果新Task的值为空则直接返回，否则继续执行 */
        if(!new_task.content) return;
        /* 存入新Task */
        if(addTask(new_task)){
            $content.val(null);
        }
    });

    /**
     * 添加Task
     * @param {String} 任务内容
     */
    function addTask(new_task){
        /* 将新Task推入TaskList */
        task_list.push(new_task);
        /* 更新LocalStorege */
        refreshTaskList();
        return true;
    }

    /**
     * 渲染全部的Task
     */
    function renderTaskList(){
        var $task_list = $(".task_list");
        $task_list.html("");
        for(var i=0; i<task_list.length; i++){
            var $task = renderTaskItem(task_list[i],i);
            $task_list.append($task);
        }

        $delete_task_btn = $(".task_list").find(".del");
        $detail_task_btn = $(".task_list").find(".detail");
        listenTaskDelete();
        listenTaskDetail()

        //console.log("$delete_task_btn",$delete_task_btn);
    }

    /**
     * 渲染单条Task模版
     * @param  {Object} data  task
     * @param  {Int} index 序号
     * @return {jQuery}    task对象
     */
    function renderTaskItem(data,index){
        if(!data || (!index && index != 0)) return;
        var task_item_tpl = `

                <input type="checkbox"/>
                ${data.content}

                删除
                详细

`;

        return $(task_item_tpl);
    }

    /**
     * 刷新localStorage数据并渲染模版
     */
    function refreshTaskList(){
        store.set("task_list",task_list);
        renderTaskList();
    }

    /**
     * 查找并监听所有删除按钮的点击事件
     */
    function listenTaskDelete(){
        $delete_task_btn.on("click", function(){
            var $this = $(this);
            var $item = $this.parent().parent();
            var index = $item.data("index");
            var temp = confirm("确认删除？");
            temp ? deleteTask(index) : null;
        });
    }

    /**
     * 删除Task
     * @param  {int} index TaskId
     */
    function deleteTask(index){
        if((!index && index != 0) || !task_list[index]) return;
        delete task_list[index];
        /*更新localStorage*/
        refreshTaskList();
    }

    /**
     * 查找并监听所有详细按钮的点击事件
     */
    function listenTaskDetail(){
        $detail_task_btn.on("click", function(){
            var $this = $(this);
            var $item = $this.parent().parent();
            var index = $item.data("index");
            showTaskDetail(index);
        });
    }

    /**
     * 显示Task详细信息
     * @param  {int} index
     */
    function showTaskDetail(index){
        if(!index && index != 0) return;
        $task_detail_mask.show();
        $task_detail.show();
    }

    function init(){
        task_list = store.get("task_list") || [];
        if(task_list.length) renderTaskList();
    }

    /**
     * 相应Enter键
     */
    $content.keyup(function(e){
        if(e.key === "Enter"){
            $addTaskBtn.trigger("click");
        }
    });

})();
<commit_msg>显示Task完结<commit_after>/**
 * Created by Administrator on 2016/11/8 0008.
 */
;(function(){
    'use strict'

    var $content = $("#task_content"),
        $addTaskBtn = $("#add_task_btn"),
        $task_detail = $(".task_detail"),
        $task_detail_mask = $(".task_detail_mask"),
        task_list = [],
        $delete_task_btn,
        $detail_task_btn;

    init();

    $addTaskBtn.on("click", function(e){
        var new_task = {};
        /* 获取新Task的值 */
        new_task.content = $content.val();
        /* 如果新Task的值为空则直接返回，否则继续执行 */
        if(!new_task.content) return;
        /* 存入新Task */
        if(addTask(new_task)){
            $content.val(null);
        }
    });

    $task_detail_mask.on("click" ,hideTaskDetail);

    /**
     * 添加Task
     * @param {String} 任务内容
     */
    function addTask(new_task){
        /* 将新Task推入TaskList */
        task_list.push(new_task);
        /* 更新LocalStorege */
        refreshTaskList();
        return true;
    }

    /**
     * 渲染全部的Task
     */
    function renderTaskList(){
        var $task_list = $(".task_list");
        $task_list.html("");
        for(var i=0; i<task_list.length; i++){
            var $task = renderTaskItem(task_list[i],i);
            $task_list.append($task);
        }

        $delete_task_btn = $(".task_list").find(".del");
        $detail_task_btn = $(".task_list").find(".detail");
        listenTaskDelete();
        listenTaskDetail()

        //console.log("$delete_task_btn",$delete_task_btn);
    }

    /**
     * 渲染单条Task模版
     * @param  {Object} data  task
     * @param  {Int} index 序号
     * @return {jQuery}    task对象
     */
    function renderTaskItem(data,index){
        if(!data || (!index && index != 0)) return;
        var task_item_tpl = `

                <input type="checkbox"/>
                ${data.content}

                删除
                详细

`;

        return $(task_item_tpl);
    }

    /**
     * 刷新localStorage数据并渲染模版
     */
    function refreshTaskList(){
        store.set("task_list",task_list);
        renderTaskList();
    }

    /**
     * 查找并监听所有删除按钮的点击事件
     */
    function listenTaskDelete(){
        $delete_task_btn.on("click", function(){
            var $this = $(this);
            var $item = $this.parent().parent();
            var index = $item.data("index");
            var temp = confirm("确认删除？");
            temp ? deleteTask(index) : null;
        });
    }

    /**
     * 删除Task
     * @param  {int} index TaskId
     */
    function deleteTask(index){
        if((!index && index != 0) || !task_list[index]) return;
        delete task_list[index];
        /*更新localStorage*/
        refreshTaskList();
    }

    /**
     * 查找并监听所有详细按钮的点击事件
     */
    function listenTaskDetail(){
        $detail_task_btn.on("click", function(){
            var $this = $(this);
            var $item = $this.parent().parent();
            var index = $item.data("index");
            showTaskDetail(index);
        });
    }

    /**
     * 显示Task详细信息
     * @param  {int} index
     */
    function showTaskDetail(index){
        if(!index && index != 0) return;
        renderTaskDetai(index);
        $task_detail_mask.show();
        $task_detail.show();
    }

    /**
     * 渲染指定Task的详细信息
     */
    function renderTaskDetai(index){
        var item = task_list[index];
        if(!item) return;
        var tpl = `

            ${item.content}

                <textarea></textarea>

                <input type="date"/>

`;

        $task_detail.html(null);
        $task_detail.html(tpl);
    }

    /**
     * 隐藏Task详细信息
     */
    function hideTaskDetail(){
        $task_detail_mask.hide();
        $task_detail.hide();
    }

    function init(){
        task_list = store.get("task_list") || [];
        if(task_list.length) renderTaskList();
    }

    /**
     * 相应Enter键
     */
    $content.keyup(function(e){
        if(e.key === "Enter"){
            $addTaskBtn.trigger("click");
        }
    });

})();
<|endoftext|>