astro-perp-ccxt-dev
Version:
1,984 lines • 89.6 kB
JavaScript
'use strict';
var zonda$1 = require('./abstract/zonda.js');
var errors = require('./base/errors.js');
var number = require('./base/functions/number.js');
var Precise = require('./base/Precise.js');
var sha512 = require('./static_dependencies/noble-hashes/sha512.js');
// ----------------------------------------------------------------------------
// ---------------------------------------------------------------------------
/**
* @class zonda
* @augments Exchange
*/
class zonda extends zonda$1 {
describe() {
return this.deepExtend(super.describe(), {
'id': 'zonda',
'name': 'Zonda',
'countries': ['EE'],
'rateLimit': 1000,
'has': {
'CORS': true,
'spot': true,
'margin': false,
'swap': false,
'future': false,
'option': false,
'addMargin': false,
'cancelAllOrders': false,
'cancelOrder': true,
'cancelOrders': false,
'closeAllPositions': false,
'closePosition': false,
'createDepositAddress': false,
'createOrder': true,
'createReduceOnlyOrder': false,
'fetchBalance': true,
'fetchBorrowInterest': false,
'fetchBorrowRate': false,
'fetchBorrowRateHistories': false,
'fetchBorrowRateHistory': false,
'fetchBorrowRates': false,
'fetchBorrowRatesPerSymbol': false,
'fetchCrossBorrowRate': false,
'fetchCrossBorrowRates': false,
'fetchDeposit': false,
'fetchDepositAddress': true,
'fetchDepositAddresses': true,
'fetchDepositAddressesByNetwork': false,
'fetchDeposits': undefined,
'fetchFundingHistory': false,
'fetchFundingInterval': false,
'fetchFundingIntervals': false,
'fetchFundingRate': false,
'fetchFundingRateHistory': false,
'fetchFundingRates': false,
'fetchGreeks': false,
'fetchIndexOHLCV': false,
'fetchIsolatedBorrowRate': false,
'fetchIsolatedBorrowRates': false,
'fetchIsolatedPositions': false,
'fetchLedger': true,
'fetchLeverage': false,
'fetchLeverages': false,
'fetchLeverageTiers': false,
'fetchLiquidations': false,
'fetchMarginAdjustmentHistory': false,
'fetchMarginMode': false,
'fetchMarginModes': false,
'fetchMarketLeverageTiers': false,
'fetchMarkets': true,
'fetchMarkOHLCV': false,
'fetchMarkPrices': false,
'fetchMyLiquidations': false,
'fetchMySettlementHistory': false,
'fetchMyTrades': true,
'fetchOHLCV': true,
'fetchOpenInterest': false,
'fetchOpenInterestHistory': false,
'fetchOpenOrder': false,
'fetchOpenOrders': true,
'fetchOption': false,
'fetchOptionChain': false,
'fetchOrderBook': true,
'fetchOrderBooks': false,
'fetchPosition': false,
'fetchPositionMode': false,
'fetchPositions': false,
'fetchPositionsRisk': false,
'fetchPremiumIndexOHLCV': false,
'fetchSettlementHistory': false,
'fetchTicker': true,
'fetchTickers': true,
'fetchTime': false,
'fetchTrades': true,
'fetchTradingFee': false,
'fetchTradingFees': false,
'fetchTransactionFee': false,
'fetchTransactionFees': false,
'fetchTransactions': undefined,
'fetchTransfer': false,
'fetchUnderlyingAssets': false,
'fetchVolatilityHistory': false,
'fetchWithdrawal': false,
'fetchWithdrawals': undefined,
'reduceMargin': false,
'repayCrossMargin': false,
'repayIsolatedMargin': false,
'setLeverage': false,
'setMargin': false,
'setMarginMode': false,
'setPositionMode': false,
'transfer': true,
'withdraw': true,
},
'timeframes': {
'1m': '60',
'3m': '180',
'5m': '300',
'15m': '900',
'30m': '1800',
'1h': '3600',
'2h': '7200',
'4h': '14400',
'6h': '21600',
'12h': '43200',
'1d': '86400',
'3d': '259200',
'1w': '604800',
},
'hostname': 'zondacrypto.exchange',
'urls': {
'referral': 'https://auth.zondaglobal.com/ref/jHlbB4mIkdS1',
'logo': 'https://user-images.githubusercontent.com/1294454/159202310-a0e38007-5e7c-4ba9-a32f-c8263a0291fe.jpg',
'www': 'https://zondaglobal.com',
'api': {
'public': 'https://{hostname}/API/Public',
'private': 'https://{hostname}/API/Trading/tradingApi.php',
'v1_01Public': 'https://api.{hostname}/rest',
'v1_01Private': 'https://api.{hostname}/rest',
},
'doc': [
'https://docs.zondacrypto.exchange/',
'https://github.com/BitBayNet/API',
],
'support': 'https://zondaglobal.com/en/helpdesk/zonda-exchange',
'fees': 'https://zondaglobal.com/legal/zonda-exchange/fees',
},
'api': {
'public': {
'get': [
'{id}/all',
'{id}/market',
'{id}/orderbook',
'{id}/ticker',
'{id}/trades',
],
},
'private': {
'post': [
'info',
'trade',
'cancel',
'orderbook',
'orders',
'transfer',
'withdraw',
'history',
'transactions',
],
},
'v1_01Public': {
'get': [
'trading/ticker',
'trading/ticker/{symbol}',
'trading/stats',
'trading/stats/{symbol}',
'trading/orderbook/{symbol}',
'trading/transactions/{symbol}',
'trading/candle/history/{symbol}/{resolution}',
],
},
'v1_01Private': {
'get': [
'api_payments/deposits/crypto/addresses',
'payments/withdrawal/{detailId}',
'payments/deposit/{detailId}',
'trading/offer',
'trading/stop/offer',
'trading/config/{symbol}',
'trading/history/transactions',
'balances/BITBAY/history',
'balances/BITBAY/balance',
'fiat_cantor/rate/{baseId}/{quoteId}',
'fiat_cantor/history',
'client_payments/v2/customer/crypto/{currency}/channels/deposit',
'client_payments/v2/customer/crypto/{currency}/channels/withdrawal',
'client_payments/v2/customer/crypto/deposit/fee',
'client_payments/v2/customer/crypto/withdrawal/fee',
],
'post': [
'trading/offer/{symbol}',
'trading/stop/offer/{symbol}',
'trading/config/{symbol}',
'balances/BITBAY/balance',
'balances/BITBAY/balance/transfer/{source}/{destination}',
'fiat_cantor/exchange',
'api_payments/withdrawals/crypto',
'api_payments/withdrawals/fiat',
'client_payments/v2/customer/crypto/deposit',
'client_payments/v2/customer/crypto/withdrawal',
],
'delete': [
'trading/offer/{symbol}/{id}/{side}/{price}',
'trading/stop/offer/{symbol}/{id}/{side}/{price}',
],
'put': [
'balances/BITBAY/balance/{id}',
],
},
},
'fees': {
'trading': {
'maker': this.parseNumber('0.0'),
'taker': this.parseNumber('0.001'),
'percentage': true,
'tierBased': false,
},
'fiat': {
'maker': this.parseNumber('0.0030'),
'taker': this.parseNumber('0.0043'),
'percentage': true,
'tierBased': true,
'tiers': {
'taker': [
[this.parseNumber('0.0043'), this.parseNumber('0')],
[this.parseNumber('0.0042'), this.parseNumber('1250')],
[this.parseNumber('0.0041'), this.parseNumber('3750')],
[this.parseNumber('0.0040'), this.parseNumber('7500')],
[this.parseNumber('0.0039'), this.parseNumber('10000')],
[this.parseNumber('0.0038'), this.parseNumber('15000')],
[this.parseNumber('0.0037'), this.parseNumber('20000')],
[this.parseNumber('0.0036'), this.parseNumber('25000')],
[this.parseNumber('0.0035'), this.parseNumber('37500')],
[this.parseNumber('0.0034'), this.parseNumber('50000')],
[this.parseNumber('0.0033'), this.parseNumber('75000')],
[this.parseNumber('0.0032'), this.parseNumber('100000')],
[this.parseNumber('0.0031'), this.parseNumber('150000')],
[this.parseNumber('0.0030'), this.parseNumber('200000')],
[this.parseNumber('0.0029'), this.parseNumber('250000')],
[this.parseNumber('0.0028'), this.parseNumber('375000')],
[this.parseNumber('0.0027'), this.parseNumber('500000')],
[this.parseNumber('0.0026'), this.parseNumber('625000')],
[this.parseNumber('0.0025'), this.parseNumber('875000')],
],
'maker': [
[this.parseNumber('0.0030'), this.parseNumber('0')],
[this.parseNumber('0.0029'), this.parseNumber('1250')],
[this.parseNumber('0.0028'), this.parseNumber('3750')],
[this.parseNumber('0.0028'), this.parseNumber('7500')],
[this.parseNumber('0.0027'), this.parseNumber('10000')],
[this.parseNumber('0.0026'), this.parseNumber('15000')],
[this.parseNumber('0.0025'), this.parseNumber('20000')],
[this.parseNumber('0.0025'), this.parseNumber('25000')],
[this.parseNumber('0.0024'), this.parseNumber('37500')],
[this.parseNumber('0.0023'), this.parseNumber('50000')],
[this.parseNumber('0.0023'), this.parseNumber('75000')],
[this.parseNumber('0.0022'), this.parseNumber('100000')],
[this.parseNumber('0.0021'), this.parseNumber('150000')],
[this.parseNumber('0.0021'), this.parseNumber('200000')],
[this.parseNumber('0.0020'), this.parseNumber('250000')],
[this.parseNumber('0.0019'), this.parseNumber('375000')],
[this.parseNumber('0.0018'), this.parseNumber('500000')],
[this.parseNumber('0.0018'), this.parseNumber('625000')],
[this.parseNumber('0.0017'), this.parseNumber('875000')],
],
},
},
'funding': {
'withdraw': {},
},
},
'options': {
'fetchTickerMethod': 'v1_01PublicGetTradingTickerSymbol',
'fetchTickersMethod': 'v1_01PublicGetTradingTicker',
'fiatCurrencies': ['EUR', 'USD', 'GBP', 'PLN'],
'transfer': {
'fillResponseFromRequest': true,
},
},
'features': {
'spot': {
'sandbox': false,
'createOrder': {
'marginMode': false,
'triggerPrice': true,
'triggerDirection': false,
'triggerPriceType': undefined,
'stopLossPrice': false,
'takeProfitPrice': false,
'attachedStopLossTakeProfit': undefined,
'timeInForce': {
'IOC': true,
'FOK': true,
'PO': true,
'GTD': false,
},
'hedged': false,
'trailing': false,
'leverage': false,
'marketBuyByCost': true,
'marketBuyRequiresPrice': false,
'selfTradePrevention': false,
'iceberg': false,
},
'createOrders': undefined,
'fetchMyTrades': {
'marginMode': false,
'limit': undefined,
'daysBack': 100000,
'untilDays': 100000,
'symbolRequired': false,
},
'fetchOrder': undefined,
'fetchOpenOrders': {
'marginMode': false,
'limit': 100,
'trigger': false,
'trailing': false,
'symbolRequired': false,
},
'fetchOrders': undefined,
'fetchClosedOrders': undefined,
'fetchOHLCV': {
'limit': undefined,
},
},
'swap': {
'linear': undefined,
'inverse': undefined,
},
'future': {
'linear': undefined,
'inverse': undefined,
},
},
'precisionMode': number.TICK_SIZE,
'exceptions': {
'400': errors.ExchangeError,
'401': errors.InvalidOrder,
'402': errors.InvalidOrder,
'403': errors.InvalidOrder,
'404': errors.InvalidOrder,
'405': errors.InvalidOrder,
'406': errors.InsufficientFunds,
// code 407 not specified are not specified in their docs
'408': errors.InvalidOrder,
'501': errors.AuthenticationError,
'502': errors.AuthenticationError,
'503': errors.InvalidNonce,
'504': errors.ExchangeError,
'505': errors.AuthenticationError,
'506': errors.AccountSuspended,
// codes 507 and 508 are not specified in their docs
'509': errors.ExchangeError,
'510': errors.BadSymbol,
'FUNDS_NOT_SUFFICIENT': errors.InsufficientFunds,
'OFFER_FUNDS_NOT_EXCEEDING_MINIMUMS': errors.InvalidOrder,
'OFFER_NOT_FOUND': errors.OrderNotFound,
'OFFER_WOULD_HAVE_BEEN_PARTIALLY_FILLED': errors.OrderImmediatelyFillable,
'ACTION_LIMIT_EXCEEDED': errors.RateLimitExceeded,
'UNDER_MAINTENANCE': errors.OnMaintenance,
'REQUEST_TIMESTAMP_TOO_OLD': errors.InvalidNonce,
'PERMISSIONS_NOT_SUFFICIENT': errors.PermissionDenied,
'INVALID_STOP_RATE': errors.InvalidOrder,
'TIMEOUT': errors.ExchangeError,
'RESPONSE_TIMEOUT': errors.ExchangeError,
'ACTION_BLOCKED': errors.PermissionDenied,
'INVALID_HASH_SIGNATURE': errors.AuthenticationError,
},
'commonCurrencies': {
'GGC': 'Global Game Coin',
},
});
}
/**
* @method
* @name zonda#fetchMarkets
* @see https://docs.zondacrypto.exchange/reference/ticker-1
* @description retrieves data on all markets for zonda
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} an array of objects representing market data
*/
async fetchMarkets(params = {}) {
const response = await this.v1_01PublicGetTradingTicker(params);
//
// {
// "status": "Ok",
// "items": {
// "BSV-USD": {
// "market": {
// "code": "BSV-USD",
// "first": { currency: "BSV", minOffer: "0.00035", scale: 8 },
// "second": { currency: "USD", minOffer: "5", scale: 2 }
// },
// "time": "1557569762154",
// "highestBid": "52.31",
// "lowestAsk": "62.99",
// "rate": "63",
// "previousRate": "51.21",
// },
// },
// }
//
const items = this.safeValue(response, 'items', {});
const markets = Object.values(items);
return this.parseMarkets(markets);
}
parseMarket(item) {
const market = this.safeValue(item, 'market', {});
const id = this.safeString(market, 'code');
const first = this.safeValue(market, 'first', {});
const second = this.safeValue(market, 'second', {});
const baseId = this.safeString(first, 'currency');
const quoteId = this.safeString(second, 'currency');
const base = this.safeCurrencyCode(baseId);
const quote = this.safeCurrencyCode(quoteId);
let fees = this.safeValue(this.fees, 'trading', {});
const fiatCurrencies = this.safeValue(this.options, 'fiatCurrencies', []);
if (this.inArray(base, fiatCurrencies) || this.inArray(quote, fiatCurrencies)) {
fees = this.safeValue(this.fees, 'fiat', {});
}
// todo: check that the limits have ben interpreted correctly
return {
'id': id,
'symbol': base + '/' + quote,
'base': base,
'quote': quote,
'settle': undefined,
'baseId': baseId,
'quoteId': quoteId,
'settleId': undefined,
'type': 'spot',
'spot': true,
'margin': false,
'swap': false,
'future': false,
'option': false,
'active': undefined,
'contract': false,
'linear': undefined,
'inverse': undefined,
'taker': this.safeNumber(fees, 'taker'),
'maker': this.safeNumber(fees, 'maker'),
'contractSize': undefined,
'expiry': undefined,
'expiryDatetime': undefined,
'optionType': undefined,
'strike': undefined,
'precision': {
'amount': this.parseNumber(this.parsePrecision(this.safeString(first, 'scale'))),
'price': this.parseNumber(this.parsePrecision(this.safeString(second, 'scale'))),
},
'limits': {
'leverage': {
'min': undefined,
'max': undefined,
},
'amount': {
'min': this.safeNumber(first, 'minOffer'),
'max': undefined,
},
'price': {
'min': undefined,
'max': undefined,
},
'cost': {
'min': undefined,
'max': undefined,
},
},
'created': undefined,
'info': item,
};
}
/**
* @method
* @name zonda#fetchOpenOrders
* @see https://docs.zondacrypto.exchange/reference/active-orders
* @description fetch all unfilled currently open orders
* @param {string} symbol not used by zonda fetchOpenOrders
* @param {int} [since] the earliest time in ms to fetch open orders for
* @param {int} [limit] the maximum number of open orders structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const request = {};
// todo pair
const response = await this.v1_01PrivateGetTradingOffer(this.extend(request, params));
const items = this.safeList(response, 'items', []);
return this.parseOrders(items, undefined, since, limit, { 'status': 'open' });
}
parseOrder(order, market = undefined) {
//
// {
// "market": "ETH-EUR",
// "offerType": "Sell",
// "id": "93d3657b-d616-11e9-9248-0242ac110005",
// "currentAmount": "0.04",
// "lockedAmount": "0.04",
// "rate": "280",
// "startAmount": "0.04",
// "time": "1568372806924",
// "postOnly": false,
// "hidden": false,
// "mode": "limit",
// "receivedAmount": "0.0",
// "firstBalanceId": "5b816c3e-437c-4e43-9bef-47814ae7ebfc",
// "secondBalanceId": "ab43023b-4079-414c-b340-056e3430a3af"
// }
//
// cancelOrder
//
// {
// status: "Ok",
// errors: []
// }
//
const marketId = this.safeString(order, 'market');
const symbol = this.safeSymbol(marketId, market, '-');
const timestamp = this.safeInteger(order, 'time');
const amount = this.safeString(order, 'startAmount');
const remaining = this.safeString(order, 'currentAmount');
const postOnly = this.safeValue(order, 'postOnly');
return this.safeOrder({
'id': this.safeString(order, 'id'),
'clientOrderId': undefined,
'info': order,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'lastTradeTimestamp': undefined,
'status': undefined,
'symbol': symbol,
'type': this.safeString(order, 'mode'),
'timeInForce': undefined,
'postOnly': postOnly,
'side': this.safeStringLower(order, 'offerType'),
'price': this.safeString(order, 'rate'),
'triggerPrice': undefined,
'amount': amount,
'cost': undefined,
'filled': undefined,
'remaining': remaining,
'average': undefined,
'fee': undefined,
'trades': undefined,
}, market);
}
/**
* @method
* @name zonda#fetchMyTrades
* @see https://docs.zondacrypto.exchange/reference/transactions-history
* @description fetch all trades made by the user
* @param {string} symbol unified market symbol
* @param {int} [since] the earliest time in ms to fetch trades for
* @param {int} [limit] the maximum number of trades structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
*/
async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const request = {};
if (symbol) {
const markets = [this.marketId(symbol)];
symbol = this.symbol(symbol);
request['markets'] = markets;
}
const query = { 'query': this.json(this.extend(request, params)) };
const response = await this.v1_01PrivateGetTradingHistoryTransactions(query);
//
// {
// "status": "Ok",
// "totalRows": "67",
// "items": [
// {
// "id": "b54659a0-51b5-42a0-80eb-2ac5357ccee2",
// "market": "BTC-EUR",
// "time": "1541697096247",
// "amount": "0.00003",
// "rate": "4341.44",
// "initializedBy": "Sell",
// "wasTaker": false,
// "userAction": "Buy",
// "offerId": "bd19804a-6f89-4a69-adb8-eb078900d006",
// "commissionValue": null
// },
// ]
// }
//
const items = this.safeValue(response, 'items');
const result = this.parseTrades(items, undefined, since, limit);
if (symbol === undefined) {
return result;
}
return this.filterBySymbol(result, symbol);
}
parseBalance(response) {
const balances = this.safeValue(response, 'balances');
if (balances === undefined) {
throw new errors.ExchangeError(this.id + ' empty balance response ' + this.json(response));
}
const result = { 'info': response };
for (let i = 0; i < balances.length; i++) {
const balance = balances[i];
const currencyId = this.safeString(balance, 'currency');
const code = this.safeCurrencyCode(currencyId);
const account = this.account();
account['used'] = this.safeString(balance, 'lockedFunds');
account['free'] = this.safeString(balance, 'availableFunds');
result[code] = account;
}
return this.safeBalance(result);
}
/**
* @method
* @name zonda#fetchBalance
* @see https://docs.zondacrypto.exchange/reference/list-of-wallets
* @description query for balance and get the amount of funds available for trading or funds locked in orders
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
*/
async fetchBalance(params = {}) {
await this.loadMarkets();
const response = await this.v1_01PrivateGetBalancesBITBAYBalance(params);
return this.parseBalance(response);
}
/**
* @method
* @name zonda#fetchOrderBook
* @see https://docs.zondacrypto.exchange/reference/orderbook-2
* @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
* @param {string} symbol unified symbol of the market to fetch the order book for
* @param {int} [limit] the maximum amount of order book entries to return
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
*/
async fetchOrderBook(symbol, limit = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
const response = await this.v1_01PublicGetTradingOrderbookSymbol(this.extend(request, params));
//
// {
// "status":"Ok",
// "sell":[
// {"ra":"43988.93","ca":"0.00100525","sa":"0.00100525","pa":"0.00100525","co":1},
// {"ra":"43988.94","ca":"0.00114136","sa":"0.00114136","pa":"0.00114136","co":1},
// {"ra":"43989","ca":"0.010578","sa":"0.010578","pa":"0.010578","co":1},
// ],
// "buy":[
// {"ra":"42157.33","ca":"2.83147881","sa":"2.83147881","pa":"2.83147881","co":2},
// {"ra":"42096.0","ca":"0.00011878","sa":"0.00011878","pa":"0.00011878","co":1},
// {"ra":"42022.0","ca":"0.00011899","sa":"0.00011899","pa":"0.00011899","co":1},
// ],
// "timestamp":"1642299886122",
// "seqNo":"27641254"
// }
//
const rawBids = this.safeValue(response, 'buy', []);
const rawAsks = this.safeValue(response, 'sell', []);
const timestamp = this.safeInteger(response, 'timestamp');
return {
'symbol': market['symbol'],
'bids': this.parseBidsAsks(rawBids, 'ra', 'ca'),
'asks': this.parseBidsAsks(rawAsks, 'ra', 'ca'),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'nonce': this.safeInteger(response, 'seqNo'),
};
}
parseTicker(ticker, market = undefined) {
//
// version 1
//
// {
// "m": "ETH-PLN",
// "h": "13485.13",
// "l": "13100.01",
// "v": "126.10710939",
// "r24h": "13332.72"
// }
//
// version 2
//
// {
// "market": {
// "code": "ADA-USDT",
// "first": {
// "currency": "ADA",
// "minOffer": "0.2",
// "scale": "6"
// },
// "second": {
// "currency": "USDT",
// "minOffer": "0.099",
// "scale": "6"
// },
// "amountPrecision": "6",
// "pricePrecision": "6",
// "ratePrecision": "6"
// },
// "time": "1655812661202",
// "highestBid": "0.492",
// "lowestAsk": "0.499389",
// "rate": "0.50588",
// "previousRate": "0.504981"
// }
//
const tickerMarket = this.safeValue(ticker, 'market');
const marketId = this.safeString2(tickerMarket, 'code', 'm');
market = this.safeMarket(marketId, market);
const timestamp = this.safeInteger(ticker, 'time');
const rate = this.safeValue(ticker, 'rate');
return this.safeTicker({
'symbol': this.safeSymbol(marketId, market),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'high': this.safeString(ticker, 'h'),
'low': this.safeString(ticker, 'l'),
'bid': this.safeNumber(ticker, 'highestBid'),
'bidVolume': undefined,
'ask': this.safeNumber(ticker, 'lowestAsk'),
'askVolume': undefined,
'vwap': undefined,
'open': this.safeString(ticker, 'r24h'),
'close': rate,
'last': rate,
'previousClose': this.safeValue(ticker, 'previousRate'),
'change': undefined,
'percentage': undefined,
'average': undefined,
'baseVolume': this.safeString(ticker, 'v'),
'quoteVolume': undefined,
'info': ticker,
}, market);
}
/**
* @method
* @name zonda#fetchTicker
* @description v1_01PublicGetTradingTickerSymbol retrieves timestamp, datetime, bid, ask, close, last, previousClose, v1_01PublicGetTradingStatsSymbol retrieves high, low, volume and opening price of an asset
* @see https://docs.zondacrypto.exchange/reference/market-statistics
* @param {string} symbol unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.method] v1_01PublicGetTradingTickerSymbol (default) or v1_01PublicGetTradingStatsSymbol
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
async fetchTicker(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
const method = 'v1_01PublicGetTradingTickerSymbol';
const defaultMethod = this.safeString(this.options, 'fetchTickerMethod', method);
const fetchTickerMethod = this.safeString2(params, 'method', 'fetchTickerMethod', defaultMethod);
let response = undefined;
if (fetchTickerMethod === method) {
response = await this.v1_01PublicGetTradingTickerSymbol(this.extend(request, params));
//
// {
// "status": "Ok",
// "ticker": {
// "market": {
// "code": "ADA-USDT",
// "first": {
// "currency": "ADA",
// "minOffer": "0.21",
// "scale": 6
// },
// "second": {
// "currency": "USDT",
// "minOffer": "0.099",
// "scale": 6
// },
// "amountPrecision": 6,
// "pricePrecision": 6,
// "ratePrecision": 6
// },
// "time": "1655810976780",
// "highestBid": "0.498543",
// "lowestAsk": "0.50684",
// "rate": "0.50588",
// "previousRate": "0.504981"
// }
// }
//
}
else if (fetchTickerMethod === 'v1_01PublicGetTradingStatsSymbol') {
response = await this.v1_01PublicGetTradingStatsSymbol(this.extend(request, params));
//
// {
// "status": "Ok",
// "stats": {
// "m": "BTC-USDT",
// "h": "28800",
// "l": "26703.950101",
// "v": "6.72932396",
// "r24h": "27122.2"
// }
// }
//
}
else {
throw new errors.BadRequest(this.id + ' fetchTicker params["method"] must be "v1_01PublicGetTradingTickerSymbol" or "v1_01PublicGetTradingStatsSymbol"');
}
const stats = this.safeValue2(response, 'ticker', 'stats');
return this.parseTicker(stats, market);
}
/**
* @ignore
* @method
* @name zonda#fetchTickersV2
* @description v1_01PublicGetTradingTicker retrieves timestamp, datetime, bid, ask, close, last, previousClose for each market, v1_01PublicGetTradingStats retrieves high, low, volume and opening price of each market
* @see https://docs.zondacrypto.exchange/reference/market-statistics
* @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.method] v1_01PublicGetTradingTicker (default) or v1_01PublicGetTradingStats
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
async fetchTickers(symbols = undefined, params = {}) {
await this.loadMarkets();
const method = 'v1_01PublicGetTradingTicker';
const defaultMethod = this.safeString(this.options, 'fetchTickersMethod', method);
const fetchTickersMethod = this.safeString2(params, 'method', 'fetchTickersMethod', defaultMethod);
let response = undefined;
if (fetchTickersMethod === method) {
response = await this.v1_01PublicGetTradingTicker(params);
//
// {
// "status": "Ok",
// "items": {
// "DAI-PLN": {
// "market": {
// "code": "DAI-PLN",
// "first": {
// "currency": "DAI",
// "minOffer": "0.99",
// "scale": 8
// },
// "second": {
// "currency": "PLN",
// "minOffer": "5",
// "scale": 2
// },
// "amountPrecision": 8,
// "pricePrecision": 2,
// "ratePrecision": 2
// },
// "time": "1655810825137",
// "highestBid": "4.42",
// "lowestAsk": "4.44",
// "rate": "4.44",
// "previousRate": "4.43"
// },
// ...
// }
// }
//
}
else if (fetchTickersMethod === 'v1_01PublicGetTradingStats') {
response = await this.v1_01PublicGetTradingStats(params);
//
// {
// "status": "Ok",
// "items": {
// "DAI-PLN": {
// "m": "DAI-PLN",
// "h": "4.41",
// "l": "4.37",
// "v": "8.71068087",
// "r24h": "4.36"
// },
// ...
// }
// }
//
}
else {
throw new errors.BadRequest(this.id + ' fetchTickers params["method"] must be "v1_01PublicGetTradingTicker" or "v1_01PublicGetTradingStats"');
}
const items = this.safeDict(response, 'items');
return this.parseTickers(items, symbols);
}
/**
* @method
* @name zonda#fetchLedger
* @description fetch the history of changes, actions done by the user or operations that altered the balance of the user
* @see https://docs.zondacrypto.exchange/reference/operations-history
* @param {string} [code] unified currency code, default is undefined
* @param {int} [since] timestamp in ms of the earliest ledger entry, default is undefined
* @param {int} [limit] max number of ledger entries to return, default is undefined
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger}
*/
async fetchLedger(code = undefined, since = undefined, limit = undefined, params = {}) {
const balanceCurrencies = [];
if (code !== undefined) {
const currency = this.currency(code);
balanceCurrencies.push(currency['id']);
}
let request = {
'balanceCurrencies': balanceCurrencies,
};
if (since !== undefined) {
request['fromTime'] = since;
}
if (limit !== undefined) {
request['limit'] = limit;
}
request = this.extend(request, params);
const response = await this.v1_01PrivateGetBalancesBITBAYHistory({ 'query': this.json(request) });
const items = response['items'];
return this.parseLedger(items, undefined, since, limit);
}
parseLedgerEntry(item, currency = undefined) {
//
// FUNDS_MIGRATION
// {
// "historyId": "84ea7a29-7da5-4de5-b0c0-871e83cad765",
// "balance": {
// "id": "821ec166-cb88-4521-916c-f4eb44db98df",
// "currency": "LTC",
// "type": "CRYPTO",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "LTC"
// },
// "detailId": null,
// "time": 1506128252968,
// "type": "FUNDS_MIGRATION",
// "value": 0.0009957,
// "fundsBefore": { "total": 0, "available": 0, "locked": 0 },
// "fundsAfter": { "total": 0.0009957, "available": 0.0009957, "locked": 0 },
// "change": { "total": 0.0009957, "available": 0.0009957, "locked": 0 }
// }
//
// CREATE_BALANCE
// {
// "historyId": "d0fabd8d-9107-4b5e-b9a6-3cab8af70d49",
// "balance": {
// "id": "653ffcf2-3037-4ebe-8e13-d5ea1a01d60d",
// "currency": "BTG",
// "type": "CRYPTO",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "BTG"
// },
// "detailId": null,
// "time": 1508895244751,
// "type": "CREATE_BALANCE",
// "value": 0,
// "fundsBefore": { "total": null, "available": null, "locked": null },
// "fundsAfter": { "total": 0, "available": 0, "locked": 0 },
// "change": { "total": 0, "available": 0, "locked": 0 }
// }
//
// BITCOIN_GOLD_FORK
// {
// "historyId": "2b4d52d3-611c-473d-b92c-8a8d87a24e41",
// "balance": {
// "id": "653ffcf2-3037-4ebe-8e13-d5ea1a01d60d",
// "currency": "BTG",
// "type": "CRYPTO",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "BTG"
// },
// "detailId": null,
// "time": 1508895244778,
// "type": "BITCOIN_GOLD_FORK",
// "value": 0.00453512,
// "fundsBefore": { "total": 0, "available": 0, "locked": 0 },
// "fundsAfter": { "total": 0.00453512, "available": 0.00453512, "locked": 0 },
// "change": { "total": 0.00453512, "available": 0.00453512, "locked": 0 }
// }
//
// ADD_FUNDS
// {
// "historyId": "3158236d-dae5-4a5d-81af-c1fa4af340fb",
// "balance": {
// "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
// "currency": "BTC",
// "type": "CRYPTO",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "BTC"
// },
// "detailId": "8e83a960-e737-4380-b8bb-259d6e236faa",
// "time": 1520631178816,
// "type": "ADD_FUNDS",
// "value": 0.628405,
// "fundsBefore": { "total": 0.00453512, "available": 0.00453512, "locked": 0 },
// "fundsAfter": { "total": 0.63294012, "available": 0.63294012, "locked": 0 },
// "change": { "total": 0.628405, "available": 0.628405, "locked": 0 }
// }
//
// TRANSACTION_PRE_LOCKING
// {
// "historyId": "e7d19e0f-03b3-46a8-bc72-dde72cc24ead",
// "balance": {
// "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
// "currency": "BTC",
// "type": "CRYPTO",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "BTC"
// },
// "detailId": null,
// "time": 1520706403868,
// "type": "TRANSACTION_PRE_LOCKING",
// "value": -0.1,
// "fundsBefore": { "total": 0.63294012, "available": 0.63294012, "locked": 0 },
// "fundsAfter": { "total": 0.63294012, "available": 0.53294012, "locked": 0.1 },
// "change": { "total": 0, "available": -0.1, "locked": 0.1 }
// }
//
// TRANSACTION_POST_OUTCOME
// {
// "historyId": "c4010825-231d-4a9c-8e46-37cde1f7b63c",
// "balance": {
// "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
// "currency": "BTC",
// "type": "CRYPTO",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "BTC"
// },
// "detailId": "bf2876bc-b545-4503-96c8-ef4de8233876",
// "time": 1520706404032,
// "type": "TRANSACTION_POST_OUTCOME",
// "value": -0.01771415,
// "fundsBefore": { "total": 0.63294012, "available": 0.53294012, "locked": 0.1 },
// "fundsAfter": { "total": 0.61522597, "available": 0.53294012, "locked": 0.08228585 },
// "change": { "total": -0.01771415, "available": 0, "locked": -0.01771415 }
// }
//
// TRANSACTION_POST_INCOME
// {
// "historyId": "7f18b7af-b676-4125-84fd-042e683046f6",
// "balance": {
// "id": "ab43023b-4079-414c-b340-056e3430a3af",
// "currency": "EUR",
// "type": "FIAT",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "EUR"
// },
// "detailId": "f5fcb274-0cc7-4385-b2d3-bae2756e701f",
// "time": 1520706404035,
// "type": "TRANSACTION_POST_INCOME",
// "value": 628.78,
// "fundsBefore": { "total": 0, "available": 0, "locked": 0 },
// "fundsAfter": { "total": 628.78, "available": 628.78, "locked": 0 },
// "change": { "total": 628.78, "available": 628.78, "locked": 0 }
// }
//
// TRANSACTION_COMMISSION_OUTCOME
// {
// "historyId": "843177fa-61bc-4cbf-8be5-b029d856c93b",
// "balance": {
// "id": "ab43023b-4079-414c-b340-056e3430a3af",
// "currency": "EUR",
// "type": "FIAT",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "EUR"
// },
// "detailId": "f5fcb274-0cc7-4385-b2d3-bae2756e701f",
// "time": 1520706404050,
// "type": "TRANSACTION_COMMISSION_OUTCOME",
// "value": -2.71,
// "fundsBefore": { "total": 766.06, "available": 766.06, "locked": 0 },
// "fundsAfter": { "total": 763.35,"available": 763.35, "locked": 0 },
// "change": { "total": -2.71, "available": -2.71, "locked": 0 }
// }
//
// TRANSACTION_OFFER_COMPLETED_RETURN
// {
// "historyId": "cac69b04-c518-4dc5-9d86-e76e91f2e1d2",
// "balance": {
// "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
// "currency": "BTC",
// "type": "CRYPTO",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "BTC"
// },
// "detailId": null,
// "time": 1520714886425,
// "type": "TRANSACTION_OFFER_COMPLETED_RETURN",
// "value": 0.00000196,
// "fundsBefore": { "total": 0.00941208, "available": 0.00941012, "locked": 0.00000196 },
// "fundsAfter": { "total": 0.00941208, "available": 0.00941208, "locked": 0 },
// "change": { "total": 0, "available": 0.00000196, "locked": -0.00000196 }
// }
//
// WITHDRAWAL_LOCK_FUNDS
// {
// "historyId": "03de2271-66ab-4960-a786-87ab9551fc14",
// "balance": {
// "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
// "currency": "BTC",
// "type": "CRYPTO",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "BTC"
// },
// "detailId": "6ad3dc72-1d6d-4ec2-8436-ca43f85a38a6",
// "time": 1522245654481,
// "type": "WITHDRAWAL_LOCK_FUNDS",
// "value": -0.8,
// "fundsBefore": { "total": 0.8, "available": 0.8, "locked": 0 },
// "fundsAfter": { "total": 0.8, "available": 0, "locked": 0.8 },
// "change": { "total": 0, "available": -0.8, "locked": 0.8 }
// }
//
// WITHDRAWAL_SUBTRACT_FUNDS
// {
// "historyId": "b0308c89-5288-438d-a306-c6448b1a266d",
// "balance": {
// "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
// "currency": "BTC",
// "type": "CRYPTO",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "BTC"
// },
// "detailId": "6ad3dc72-1d6d-4ec2-8436-ca43f85a38a6",
// "time": 1522246526186,
// "type": "WITHDRAWAL_SUBTRACT_FUNDS",
// "value": -0.8,
// "fundsBefore": { "total": 0.8, "available": 0, "locked": 0.8 },
// "fundsAfter": { "total": 0, "available": 0, "locked": 0 },
// "change": { "total": -0.8, "available": 0, "locked": -0.8 }
// }
//
// TRANSACTION_OFFER_ABORTED_RETURN
// {
// "historyId": "b1a3c075-d403-4e05-8f32-40512cdd88c0",
// "balance": {
// "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
// "currency": "BTC",
// "type": "CRYPTO",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "BTC"
// },
// "detailId": null,
// "time": 1522512298662,
// "type": "TRANSACTION_OFFER_ABORTED_RETURN",
// "value": 0.0564931,
// "fundsBefore": { "total": 0.44951311, "available": 0.39302001, "locked": 0.0564931 },
// "fundsAfter": { "total": 0.44951311, "available": 0.44951311, "locked": 0 },
// "change": { "total": 0, "available": 0.0564931, "locked": -0.0564931 }
// }
//
// WITHDRAWAL_UNLOCK_FUNDS
// {
// "historyId": "0ed569a2-c330-482e-bb89-4cb553fb5b11",
// "balance": {
// "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
// "currency": "BTC",
// "type": "CRYPTO",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "BTC"
// },
// "detailId": "0c7be256-c336-4111-bee7-4eb22e339700",
// "time": 1527866360785,
// "type": "WITHDRAWAL_UNLOCK_FUNDS",
// "value": 0.05045,
// "fundsBefore": { "total": 0.86001578, "available": 0.80956578, "locked": 0.05045 },
// "fundsAfter": { "total": 0.86001578, "available": 0.86001578, "locked": 0 },
// "change": { "total": 0, "available": 0.05045, "locked": -0.05045 }
// }
//
// TRANSACTION_COMMISSION_RETURN
// {
// "historyId": "07c89c27-46f1-4d7a-8518-b73798bf168a",
// "balance": {
// "id": "ab43023b-4079-414c-b340-056e3430a3af",
// "currency": "EUR",
// "type": "FIAT",
// "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
// "name": "EUR"
// },
// "detailId": null,
// "time": 1528304043063,
// "type": "TRANSACTION_COMMISSION_RETURN",
// "value": 0.6,
// "fundsBefore": { "total": 0, "available": 0, "locked": 0 },
// "fundsAfter": { "total": 0.6, "available": 0.6, "locked": 0 },
// "change": { "total": 0.6, "available": 0.6, "locked": 0 }
// }
//
const timestamp = this.safeInteger(item, 'time');
const balance = this.safeValue(item, 'balance', {});
const currencyId = this.safeString(balance, 'currency');
currency = this.safeCurrency(currencyId, currency);
const change = this.safeValue(item, 'change', {});
let amount = this.safeString(change, 'total');
let direction = 'in';
if (Precise["default"].stringLt(amount, '0')) {
direction = 'out';
amount = Precise["default"].stringNeg(amount);
}
// there are 2 undocumented api calls: (v1_01PrivateGetPaymentsDepositDetailId and v1_01PrivateGetPaymentsWithdrawalDetailId)
// that can be used to enrich the transfers with txid, address etc (you need to use info.detailId as a parameter)
const fundsBefore = this.safeValue(item, 'fundsBefore', {});
const fundsAfter = this.safeValue(item, 'fundsAfter', {});
return this.safeLedgerEntry({
'info': item,
'id': this.safeString(item, 'historyId'),
'direction': direction,
'account': undefined,
'referenceId': this.safeString(item, 'detailId'),
'referenceAccount': undefined,
'type': this.parseLedgerEntryType(this.safeString(item, 'type')),
'currency': this.safeCurrencyCode(currencyId),
'amount': this.parseNumber(amount),
'before': this.safeNumber(fundsBefore, 'total'),
'after': this.safeNumber(fundsAfter, 'total'),
'status': 'ok',
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'fee': undefined,
}, currency);
}
parseLedgerEntryType(type) {
const types = {
'ADD_FUNDS': 'transaction',
'BITCOIN_GOLD_FORK': 'transaction',
'CREATE_BALANCE': 'transaction',
'FUNDS_MIGRATION': 'transaction',
'WITHDRAWAL_LOCK_FUNDS': 'transaction',
'WITHDRAWAL_SUBTRACT_FUNDS': 'transaction',
'WITHDRAWAL_UNLOCK_FUNDS': 'transaction',
'TRANSACTION_COMMISSION_OUTCOME': 'fee',
'TRANSACTION_COMMISSION_RETURN': 'fee',
'TRANSACTION_OFFER_ABORTED_RETURN': 'trade',
'TRANSACTION_OFFER_COMPLETED_RETURN': 'trade',
'TRANSACTION_POST_INCOME': 'trade',
'TRANSACTION_POST_OUTCOME': 'trade',
'TRANSACTION_PRE_LOCKING': 'trade',
};
return this.safeString(types, type, type);
}
parseOHLCV(ohlcv, market = undefined) {
//
// [
// "1582399800000",
// {
// "o": "0.0001428",
// "c": "0.0001428",
// "h": "0.0001428",
// "l": "0.0001428",
// "v": "4",
// "co": "1"
// }
// ]
//
const first = this.safeValue(ohlcv, 1, {});
return [
this.safeInteger(ohlcv, 0),
this.safeNumber(first, 'o'),
this.safeNumber(first, 'h'),
this.safeNumber(first, 'l'),
this.safeNumber(first, 'c'),
this.safeNumber(first, 'v'),
];
}
/**
* @method
* @name zonda#fetchOHLCV
* @see https://docs.zondacrypto.exchange/reference/candles-chart
* @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
* @param {string} timeframe the length of time each candle represents
* @param {int} [since] timestamp in ms of the earliest candle to fetch
* @param {int} [limit] the maximum amount of candles to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const tradingSymbol = market['baseId'] + '-' + market['quoteId'];
const request = {
'symbol': tradingSymbol,
'resolution': this.safeString(this.timeframes, timeframe, timeframe),
// 'from': 1574709092000, // unix timestamp in milliseconds, required
// 'to': 1574709092000, // unix timestamp in milliseconds, required
};
if (limit === undefined) {
limit = 100;
}
else {
limit = Math.min(limit, 11000); // supports up to 11k candles diapason
}
const duration = this.parseTimeframe(timeframe);
const timerange = limit * duration * 1000;
if (since === undefined) {
request['to'] = this.milliseconds();
request['from'] = request['to'] - timerange;
}
else {
request['from'] = since;
request['to'] = this.sum(request['from'], timerange);
}
const response = await this.v1_01PublicGetTradingCandleHistorySymbolResolution(this.extend(request, params));
//
// {
// "status":"Ok",
// "items":[
// ["1591503060000",{"o":"0.02509572","c":"0.02509438","h":"0.02509664","l":"0.02509438","v":"0.02082165","co":"17"}],
// ["1591503120000",{"o":"0.02509606","c":"0.02509515","h":"0.02509606","l":"0.02509487","v":"0.04971703","co":"13"}],
// ["1591503180000",{"o":"0.02509532","c":"0.02509589","h":"0.02509589","l":"0.02509454","v":"0.01332236","co":"7"}],
// ]
// }
//
const items = this.safeList(response, 'items', []);
return this.parseOHLCVs(items, market, timeframe, since, limit);
}
parseTrade(trade, market = undefined) {
//
// createOrder trades
//
// {
// "rate": "0.02195928",
// "amount": "0.00167952"
// }
//
// fetchMyTrades (private)
//
// {
// "amount": "0.29285199",
// "commissionValue": "0.00125927",
// "id": "11c8203a-a267-11e9-b698-0242ac110007",
// "initializedBy": "Buy",
// "market": "ETH-EUR",
// "offerId": "11c82038-a267-11e9-b698-0242ac110007",
// "rate": "277",
// "time": "1562689917517",
// "userAction": "Buy",
// "wasTaker": true,
// }
//
// fetchTrades (public)
//
// {
// "id": "df00b0da-e5e0-11e9-8c19-0242ac11000a",
// "t": "1570108958831",
// "a": "0.04776653",
// "r": "0.02145854",
// "ty": "Sell"
// }
//
const timestamp = this.safeInteger2(trade, 'time', 't');
const side = this.safeStringLower2(trade, 'userAction', 'ty');
const wasTaker = this.safeValue(trade, 'wasTaker');
let takerOrMaker = undefined;
if (wasTaker !== undefined) {
takerOrMaker = wasTaker ? 'taker' : 'maker';
}
const priceString = this.safeString2(trade, 'rate', 'r');
const amountString = this.safeString2(trade, 'amount', 'a');
const feeCostString = this.safeString(trade, 'commissionValue');
const marketId = this.safeString(trade, 'market');
market = this.safeMarket(marketId, market, '-');
const symbol = market['symbol'];
let fee = undefined;
if (feeCostString !== undefined) {
const feeCurrency = (side === 'buy') ? market['base'] : market['quote'];
fee = {
'currency': feeCurrency,
'cost': feeCostString,
};
}
const order = this.safeString(trade, 'offerId');
// todo: check this logic
let type = undefined;
if (order !== undefined) {
type = order ? 'limit' : 'market';
}
return this.safeTrade({
'id': this.safeString(trade, 'id'),
'order': order,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'symbol': symbol,
'type': type,
'side': side,
'price': priceString,
'amount': amountString,
'cost': undefined,
'takerOrMaker': takerOrMaker,
'fee': fee,
'info': trade,
}, market);
}
/**
* @method
* @name zonda#fetchTrades
* @see https://docs.zondacrypto.exchange/reference/last-transactions
* @description get the list of most recent trades for a particular symbol
* @param {string} symbol unified symbol of the market to fetch trades for
* @param {int} [since] timestamp in ms of the earliest trade to fetch
* @param {int} [limit] the maximum amount of trades to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
*/
async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const tradingSymbol = market['baseId'] + '-' + market['quoteId'];
const request = {
'symbol': tradingSymbol,
};
if (since !== undefined) {
request['fromTime'] = since - 1; // result does not include exactly `since` time therefore decrease by 1
}
if (limit !== undefined) {
request['limit'] = limit; // default - 10, max - 300
}
const response = await this.v1_01PublicGetTradingTransactionsSymbol(this.extend(request, params));
const items = this.safeList(response, 'items');
return this.parseTrades(items, market, since, limit);
}
/**
* @method
* @name zonda#createOrder
* @description create a trade order
* @see https://docs.zondacrypto.exchange/reference/new-order
* @param {string} symbol unified symbol of the market to create an order in
* @param {string} type 'market' or 'limit'
* @param {string} side 'buy' or 'sell'
* @param {float} amount how much of currency you want to trade in units of base currency
* @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const tradingSymbol = market['baseId'] + '-' + market['quoteId'];
amount = parseFloat(this.amountToPrecision(symbol, amount));
const request = {
'symbol': tradingSymbol,
'offerType': side.toUpperCase(),
'amount': amount,
};
const stopLossPrice = this.safeValue2(params, 'stopPrice', 'stopLossPrice');
const isStopLossPrice = stopLossPrice !== undefined;
const isLimitOrder = type === 'limit';
const isMarketOrder = type === 'market';
const isStopLimit = (type === 'stop-limit') || (isLimitOrder && isStopLossPrice);
const isStopMarket = type === 'stop-market' || (isMarketOrder && isStopLossPrice);
const isStopOrder = isStopLimit || isStopMarket;
if (isLimitOrder || isStopLimit) {
request['rate'] = this.priceToPrecision(symbol, price);
request['mode'] = isStopLimit ? 'stop-limit' : 'limit';
}
else if (isMarketOrder || isStopMarket) {
request['mode'] = isStopMarket ? 'stop-market' : 'market';
}
else {
throw new errors.ExchangeError(this.id + ' createOrder() invalid type');
}
params = this.omit(params, ['stopPrice', 'stopLossPrice']);
let response = undefined;
if (isStopOrder) {
if (!isStopLossPrice) {
throw new errors.ExchangeError(this.id + ' createOrder() zonda requires `triggerPrice` parameter for stop-limit or stop-market orders');
}
request['stopRate'] = this.priceToPrecision(symbol, stopLossPrice);
response = await this.v1_01PrivatePostTradingStopOfferSymbol(this.extend(request, params));
}
else {
response = await this.v1_01PrivatePostTradingOfferSymbol(this.extend(request, params));
}
//
// unfilled (open order)
//
// {
// "status": "Ok",
// "completed": false, // can deduce status from here
// "offerId": "ce9cc72e-d61c-11e9-9248-0242ac110005",
// "transactions": [], // can deduce order info from here
// }
//
// filled (closed order)
//
// {
// "status": "Ok",
// "offerId": "942a4a3e-e922-11e9-8c19-0242ac11000a",
// "completed": true,
// "transactions": [
// {
// "rate": "0.02195928",
// "amount": "0.00167952"
// },
// {
// "rate": "0.02195928",
// "amount": "0.00167952"
// },
// {
// "rate": "0.02196207",
// "amount": "0.27704177"
// }
// ]
// }
//
// partially-filled (open order)
//
// {
// "status": "Ok",
// "offerId": "d0ebefab-f4d7-11e9-8c19-0242ac11000a",
// "completed": false,
// "transactions": [
// {
// "rate": "0.02106404",
// "amount": "0.0019625"
// },
// {
// "rate": "0.02106404",
// "amount": "0.0019625"
// },
// {
// "rate": "0.02105901",
// "amount": "0.00975256"
// }
// ]
// }
//
const id = this.safeString2(response, 'offerId', 'stopOfferId');
const completed = this.safeBool(response, 'completed', false);
const status = completed ? 'closed' : 'open';
const transactions = this.safeValue(response, 'transactions');
return this.safeOrder({
'id': id,
'info': response,
'timestamp': undefined,
'datetime': undefined,
'lastTradeTimestamp': undefined,
'status': status,
'symbol': symbol,
'type': type,
'side': side,
'price': price,
'amount': amount,
'cost': undefined,
'filled': undefined,
'remaining': undefined,
'average': undefined,
'fee': undefined,
'trades': transactions,
'clientOrderId': undefined,
});
}
/**
* @method
* @name zonda#cancelOrder
* @see https://docs.zondacrypto.exchange/reference/cancel-order
* @description cancels an open order
* @param {string} id order id
* @param {string} symbol unified symbol of the market the order was made in
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
async cancelOrder(id, symbol = undefined, params = {}) {
const side = this.safeString(params, 'side');
if (side === undefined) {
throw new errors.ExchangeError(this.id + ' cancelOrder() requires a `side` parameter ("buy" or "sell")');
}
const price = this.safeValue(params, 'price');
if (price === undefined) {
throw new errors.ExchangeError(this.id + ' cancelOrder() requires a `price` parameter (float or string)');
}
await this.loadMarkets();
const market = this.market(symbol);
const tradingSymbol = market['baseId'] + '-' + market['quoteId'];
const request = {
'symbol': tradingSymbol,
'id': id,
'side': side,
'price': price,
};
const response = await this.v1_01PrivateDeleteTradingOfferSymbolIdSidePrice(this.extend(request, params));
// { status: "Fail", errors: [ "NOT_RECOGNIZED_OFFER_TYPE" ] } -- if required params are missing
// { status: "Ok", errors: [] }
return this.parseOrder(response);
}
isFiat(currency) {
const fiatCurrencies = {
'USD': true,
'EUR': true,
'PLN': true,
};
return this.safeBool(fiatCurrencies, currency, false);
}
parseDepositAddress(depositAddress, currency = undefined) {
//
// {
// "address": "33u5YAEhQbYfjHHPsfMfCoSdEjfwYjVcBE",
// "currency": "BTC",
// "balanceId": "5d5d19e7-2265-49c7-af9a-047bcf384f21",
// "balanceEngine": "BITBAY",
// "tag": null
// }
//
const currencyId = this.safeString(depositAddress, 'currency');
const address = this.safeString(depositAddress, 'address');
this.checkAddress(address);
return {
'info': depositAddress,
'currency': this.safeCurrencyCode(currencyId, currency),
'network': undefined,
'address': address,
'tag': this.safeString(depositAddress, 'tag'),
};
}
/**
* @method
* @name zonda#fetchDepositAddress
* @see https://docs.zondacrypto.exchange/reference/deposit-addresses-for-crypto
* @description fetch the deposit address for a currency associated with this account
* @param {string} code unified currency code
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.walletId] Wallet id to filter deposit adresses.
* @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
*/
async fetchDepositAddress(code, params = {}) {
await this.loadMarkets();
const currency = this.currency(code);
const request = {
'currency': currency['id'],
};
const response = await this.v1_01PrivateGetApiPaymentsDepositsCryptoAddresses(this.extend(request, params));
//
// {
// "status": "Ok",
// "data": [{
// "address": "33u5YAEhQbYfjHHPsfMfCoSdEjfwYjVcBE",
// "currency": "BTC",
// "balanceId": "5d5d19e7-2265-49c7-af9a-047bcf384f21",
// "balanceEngine": "BITBAY",
// "tag": null
// }
// ]
// }
//
const data = this.safeValue(response, 'data');
const first = this.safeDict(data, 0);
return this.parseDepositAddress(first, currency);
}
/**
* @method
* @name zonda#fetchDepositAddresses
* @see https://docs.zondacrypto.exchange/reference/deposit-addresses-for-crypto
* @description fetch deposit addresses for multiple currencies and chain types
* @param {string[]|undefined} codes zonda does not support filtering filtering by multiple codes and will ignore this parameter.
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a list of [address structures]{@link https://docs.ccxt.com/#/?id=address-structure}
*/
async fetchDepositAddresses(codes = undefined, params = {}) {
await this.loadMarkets();
const response = await this.v1_01PrivateGetApiPaymentsDepositsCryptoAddresses(params);
//
// {
// "status": "Ok",
// "data": [{
// "address": "33u5YAEhQbYfjHHPsfMfCoSdEjfwYjVcBE",
// "currency": "BTC",
// "balanceId": "5d5d19e7-2265-49c7-af9a-047bcf384f21",
// "balanceEngine": "BITBAY",
// "tag": null
// }
// ]
// }
//
const data = this.safeList(response, 'data');
return this.parseDepositAddresses(data, codes);
}
/**
* @method
* @name zonda#transfer
* @see https://docs.zondacrypto.exchange/reference/internal-transfer
* @description transfer currency internally between wallets on the same account
* @param {string} code unified currency code
* @param {float} amount amount to transfer
* @param {string} fromAccount account to transfer from
* @param {string} toAccount account to transfer to
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
*/
async transfer(code, amount, fromAccount, toAccount, params = {}) {
await this.loadMarkets();
const currency = this.currency(code);
const request = {
'source': fromAccount,
'destination': toAccount,
'currency': code,
'funds': this.currencyToPrecision(code, amount),
};
const response = await this.v1_01PrivatePostBalancesBITBAYBalanceTransferSourceDestination(this.extend(request, params));
//
// {
// "status": "Ok",
// "from": {
// "id": "ad9397c5-3bd9-4372-82ba-22da6a90cb56",
// "userId": "4bc43956-423f-47fd-9faa-acd37c58ed9f",
// "availableFunds": 0.01803472,
// "totalFunds": 0.01804161,
// "lockedFunds": 0.00000689,
// "currency": "BTC",
// "type": "CRYPTO",
// "name": "BTC",
// "balanceEngine": "BITBAY"
// },
// "to": {
// "id": "01931d52-536b-4ca5-a9f4-be28c86d0cc3",
// "userId": "4bc43956-423f-47fd-9faa-acd37c58ed9f",
// "availableFunds": 0.0001,
// "totalFunds": 0.0001,
// "lockedFunds": 0,
// "currency": "BTC",
// "type": "CRYPTO",
// "name": "Prowizja",
// "balanceEngine": "BITBAY"
// },
// "errors": null
// }
//
const transfer = this.parseTransfer(response, currency);
const transferOptions = this.safeValue(this.options, 'transfer', {});
const fillResponseFromRequest = this.safeBool(transferOptions, 'fillResponseFromRequest', true);
if (fillResponseFromRequest) {
transfer['amount'] = amount;
}
return transfer;
}
parseTransfer(transfer, currency = undefined) {
//
// {
// "status": "Ok",
// "from": {
// "id": "ad9397c5-3bd9-4372-82ba-22da6a90cb56",
// "userId": "4bc43956-423f-47fd-9faa-acd37c58ed9f",
// "availableFunds": 0.01803472,
// "totalFunds": 0.01804161,
// "lockedFunds": 0.00000689,
// "currency": "BTC",
// "type": "CRYPTO",
// "name": "BTC",
// "balanceEngine": "BITBAY"
// },
// "to": {
// "id": "01931d52-536b-4ca5-a9f4-be28c86d0cc3",
// "userId": "4bc43956-423f-47fd-9faa-acd37c58ed9f",
// "availableFunds": 0.0001,
// "totalFunds": 0.0001,
// "lockedFunds": 0,
// "currency": "BTC",
// "type": "CRYPTO",
// "name": "Prowizja",
// "balanceEngine": "BITBAY"
// },
// "errors": null
// }
//
const status = this.safeString(transfer, 'status');
const fromAccount = this.safeValue(transfer, 'from', {});
const fromId = this.safeString(fromAccount, 'id');
const to = this.safeValue(transfer, 'to', {});
const toId = this.safeString(to, 'id');
const currencyId = this.safeString(fromAccount, 'currency');
return {
'info': transfer,
'id': undefined,
'timestamp': undefined,
'datetime': undefined,
'currency': this.safeCurrencyCode(currencyId, currency),
'amount': undefined,
'fromAccount': fromId,
'toAccount': toId,
'status': this.parseTransferStatus(status),
};
}
parseTransferStatus(status) {
const statuses = {
'Ok': 'ok',
'Fail': 'failed',
};
return this.safeString(statuses, status, status);
}
/**
* @method
* @name zonda#withdraw
* @see https://docs.zondacrypto.exchange/reference/crypto-withdrawal-1
* @description make a withdrawal
* @param {string} code unified currency code
* @param {float} amount the amount to withdraw
* @param {string} address the address to withdraw to
* @param {string} tag
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
*/
async withdraw(code, amount, address, tag = undefined, params = {}) {
[tag, params] = this.handleWithdrawTagAndParams(tag, params);
this.checkAddress(address);
await this.loadMarkets();
let response = undefined;
const currency = this.currency(code);
const request = {
'currency': currency['id'],
'amount': amount,
'address': address,
// request['balanceId'] = params['balanceId']; // Wallet id used for withdrawal. If not provided, any BITBAY wallet with sufficient funds is used. If BITBAYPAY wallet should be used parameter must be explicitly specified.
};
if (this.isFiat(code)) {
// request['swift'] = params['swift']; // Bank identifier, if required.
response = await this.v1_01PrivatePostApiPaymentsWithdrawalsFiat(this.extend(request, params));
}
else {
if (tag !== undefined) {
request['tag'] = tag;
}
response = await this.v1_01PrivatePostApiPaymentsWithdrawalsCrypto(this.extend(request, params));
}
//
// {
// "status": "Ok",
// "data": {
// "id": "65e01087-afb0-4ab2-afdb-cc925e360296"
// }
// }
//
const data = this.safeDict(response, 'data');
return this.parseTransaction(data, currency);
}
parseTransaction(transaction, currency = undefined) {
//
// withdraw
//
// {
// "id": "65e01087-afb0-4ab2-afdb-cc925e360296"
// }
//
currency = this.safeCurrency(undefined, currency);
return {
'id': this.safeString(transaction, 'id'),
'txid': undefined,
'timestamp': undefined,
'datetime': undefined,
'network': undefined,
'addressFrom': undefined,
'address': undefined,
'addressTo': undefined,
'amount': undefined,
'type': undefined,
'currency': currency['code'],
'status': undefined,
'updated': undefined,
'tagFrom': undefined,
'tag': undefined,
'tagTo': undefined,
'comment': undefined,
'internal': undefined,
'fee': undefined,
'info': transaction,
};
}
sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
let url = this.implodeHostname(this.urls['api'][api]);
if (api === 'public') {
const query = this.omit(params, this.extractParams(path));
url += '/' + this.implodeParams(path, params) + '.json';
if (Object.keys(query).length) {
url += '?' + this.urlencode(query);
}
}
else if (api === 'v1_01Public') {
const query = this.omit(params, this.extractParams(path));
url += '/' + this.implodeParams(path, params);
if (Object.keys(query).length) {
url += '?' + this.urlencode(query);
}
}
else if (api === 'v1_01Private') {
this.checkRequiredCredentials();
const query = this.omit(params, this.extractParams(path));
url += '/' + this.implodeParams(path, params);
const nonce = this.milliseconds().toString();
let payload = undefined;
if (method !== 'POST') {
if (Object.keys(query).length) {
url += '?' + this.urlencode(query);
}
payload = this.apiKey + nonce;
}
else if (body === undefined) {
body = this.json(query);
payload = this.apiKey + nonce + body;
}
headers = {
'Request-Timestamp': nonce,
'Operation-Id': this.uuid(),
'API-Key': this.apiKey,
'API-Hash': this.hmac(this.encode(payload), this.encode(this.secret), sha512.sha512),
'Content-Type': 'application/json',
};
}
else {
this.checkRequiredCredentials();
body = this.urlencode(this.extend({
'method': path,
'moment': this.nonce(),
}, params));
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'API-Key': this.apiKey,
'API-Hash': this.hmac(this.encode(body), this.encode(this.secret), sha512.sha512),
};
}
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
}
handleErrors(httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
if (response === undefined) {
return undefined; // fallback to default error handler
}
if ('code' in response) {
//
// bitbay returns the integer "success": 1 key from their private API
// or an integer "code" value from 0 to 510 and an error message
//
// { "success": 1, ... }
// { 'code': 502, "message": "Invalid sign" }
// { 'code': 0, "message": "offer funds not exceeding minimums" }
//
// 400 At least one parameter wasn't set
// 401 Invalid order type
// 402 No orders with specified currencies
// 403 Invalid payment currency name
// 404 Error. Wrong transaction type
// 405 Order with this id doesn't exist
// 406 No enough money or crypto
// 408 Invalid currency name
// 501 Invalid public key
// 502 Invalid sign
// 503 Invalid moment parameter. Request time doesn't match current server time
// 504 Invalid method
// 505 Key has no permission for this action
// 506 Account locked. Please contact with customer service
// 509 The BIC/SWIFT is required for this currency
// 510 Invalid market name
//
const code = this.safeString(response, 'code'); // always an integer
const feedback = this.id + ' ' + body;
this.throwExactlyMatchedException(this.exceptions, code, feedback);
throw new errors.ExchangeError(feedback);
}
else if ('status' in response) {
//
// {"status":"Fail","errors":["OFFER_FUNDS_NOT_EXCEEDING_MINIMUMS"]}
//
const status = this.safeString(response, 'status');
if (status === 'Fail') {
const errors$1 = this.safeValue(response, 'errors');
const feedback = this.id + ' ' + body;
for (let i = 0; i < errors$1.length; i++) {
const error = errors$1[i];
this.throwExactlyMatchedException(this.exceptions, error, feedback);
}
throw new errors.ExchangeError(feedback);
}
}
return undefined;
}
}
module.exports = zonda;