kamiswiss-ccxt
Version:
A JavaScript / Python / PHP cryptocurrency trading library with support for 130+ exchanges
1,163 lines (1,134 loc) • 51 kB
JavaScript
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
const { ExchangeError, AuthenticationError, InsufficientFunds, ExchangeNotAvailable, InvalidOrder, BadRequest, OrderNotFound, NotSupported } = require ('./base/errors');
// ---------------------------------------------------------------------------
module.exports = class anxpro extends Exchange {
describe () {
return this.deepExtend (super.describe (), {
'id': 'anxpro',
'name': 'ANXPro',
'countries': [ 'JP', 'SG', 'HK', 'NZ' ],
'rateLimit': 1500,
'has': {
'CORS': false,
'fetchCurrencies': true,
'fetchOHLCV': false,
'fetchTrades': false,
'fetchOpenOrders': true,
'fetchDepositAddress': true,
'fetchTransactions': true,
'fetchMyTrades': true,
'createDepositAddress': false,
'withdraw': true,
},
'urls': {
'logo': 'https://user-images.githubusercontent.com/1294454/27765983-fd8595da-5ec9-11e7-82e3-adb3ab8c2612.jpg',
'api': {
'public': 'https://anxpro.com/api/2',
'private': 'https://anxpro.com/api/2',
'v3public': 'https://anxpro.com/api/3',
'v3private': 'https://anxpro.com/api/3',
},
'www': 'https://anxpro.com',
'doc': [
'https://anxv2.docs.apiary.io',
'https://anxv3.docs.apiary.io',
'https://anxpro.com/pages/api',
],
},
'api': {
'v3public': {
'get': [
'currencyStatic',
],
},
'v3private': {
'post': [
'register/register',
'register/verifyRegistration',
'register/resendVerification',
'register/autoRegister',
'account',
'subaccount/new',
'transaction/list',
'order/list',
'trade/list',
'send',
'receive',
'receive/create',
'batch/new',
'batch/add',
'batch/list',
'batch/info',
'batch/closeForSend',
'order/new',
'order/info',
'order/cancel',
'retail/quote',
'retail/trade',
'validateAddress',
'address/check',
'alert/create',
'alert/delete',
'alert/list',
'kyc/personal',
'kyc/document',
'kyc/status',
'kyc/verifyCode',
'news/list',
'press/list',
'announcements/list',
'apiDoc/list',
],
},
'public': {
'get': [
'{currency_pair}/money/ticker',
'{currency_pair}/money/depth/full',
'{currency_pair}/money/trade/fetch', // disabled by ANXPro
],
},
'private': {
'post': [
'{currency_pair}/money/order/add',
'{currency_pair}/money/order/cancel',
'{currency_pair}/money/order/quote',
'{currency_pair}/money/order/result',
'{currency_pair}/money/orders',
'money/{currency}/address',
'money/{currency}/send_simple',
'money/info',
'money/trade/list',
'money/wallet/history',
],
},
},
'httpExceptions': {
'403': AuthenticationError,
},
'exceptions': {
'exact': {
// v2
'Insufficient Funds': InsufficientFunds,
'Trade value too small': InvalidOrder,
'The currency pair is not supported': BadRequest,
'Order amount is too low': InvalidOrder,
'Order amount is too high': InvalidOrder,
'order rate is too low': InvalidOrder,
'order rate is too high': InvalidOrder,
'Too many open orders': InvalidOrder,
'Unexpected error': ExchangeError,
'Order Engine is offline': ExchangeNotAvailable,
'No executed order with that identifer found': OrderNotFound,
'Unknown server error, please contact support.': ExchangeError,
},
},
'fees': {
'trading': {
'tierBased': false,
'percentage': true,
'maker': 0.1 / 100,
'taker': 0.2 / 100,
},
},
'options': {
'fetchMyTradesMethod': 'private_post_money_trade_list', // or 'v3private_post_trade_list'
},
});
}
async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets ();
const request = {};
if (since !== undefined) {
request['from'] = since;
}
if (limit !== undefined) {
request['max'] = limit;
}
const currency = (code === undefined) ? undefined : this.currency (code);
if (currency !== undefined) {
request['ccy'] = currency['id'];
}
const response = await this.v3privatePostTransactionList (this.extend (request, params));
//
// {
// transactions: [
// {
// transactionClass: 'COIN',
// uuid: '7896857b-2ed6-4c62-ba4c-619837438d9c',
// userUuid: '82027ee9-cb59-4f29-80d6-f7e793f39ad4',
// amount: -17865.72689976,
// fee: 1,
// balanceBefore: 17865.72689976,
// balanceAfter: 17865.72689976,
// ccy: 'XRP',
// transactionState: 'PROCESSED',
// transactionType: 'WITHDRAWAL',
// received: '1551357946000',
// processed: '1551357946000',
// timestampMillis: '1557441435932',
// displayTitle: 'Coin Withdrawal',
// displayDescription: 'Withdraw to: rw2ciyaNshpHe7bCHo4bRWq6pqqynnWKQg?dt=3750180345',
// coinAddress: 'rw2ciyaNshpHe7bCHo4bRWq6pqqynnWKQg?dt=3750180345',
// coinTransactionId: '68444611753E9D8F5C33DCBBF43F01391070F79CAFCF7625397D1CEFA519064A',
// subAccount: [
// Object
// ]
// },
// {
// transactionClass: 'FILL',
// uuid: 'a5ae54de-c14a-4ef8-842d-56000c9dc7ab',
// userUuid: '82027ee9-cb59-4f29-80d6-f7e793f39ad4',
// amount: 0.09006364,
// fee: 0.00018013,
// balanceBefore: 0.3190001,
// balanceAfter: 0.40888361,
// ccy: 'BTC',
// transactionState: 'PROCESSED',
// transactionType: 'FILL_CREDIT',
// received: '1551357057000',
// processed: '1551357057000',
// timestampMillis: '1557441435956',
// displayTitle: 'Order Fill',
// displayDescription: 'Buy BTC @ 3008.53930 EUR/BTC'
// }
// ],
// count: ...,
// timestamp: '1557441435971',
// resultCode: 'OK'
// }
//
const transactions = this.safeValue (response, 'transactions', []);
const grouped = this.groupBy (transactions, 'transactionType');
const depositsAndWithdrawals = this.arrayConcat (grouped['DEPOSIT'], grouped['WITHDRAWAL']);
return this.parseTransactions (depositsAndWithdrawals, currency, since, limit);
}
parseTransaction (transaction, currency = undefined) {
//
// withdrawal
//
// {
// transactionClass: 'COIN',
// uuid: 'bff91938-4dad-4c48-9db6-468324ce96c1',
// userUuid: '82027ee9-cb59-4f29-80d6-f7e793f39ad4',
// amount: -0.40888361,
// fee: 0.002,
// balanceBefore: 0.40888361,
// balanceAfter: 0.40888361,
// ccy: 'BTC',
// transactionState: 'PROCESSED',
// transactionType: 'WITHDRAWAL',
// received: '1551357156000',
// processed: '1551357156000',
// timestampMillis: '1557441846213',
// displayTitle: 'Coin Withdrawal',
// displayDescription: 'Withdraw to: 1AHnhqbvbYx3rnZx8uC7NbFZaTe4tafFHX',
// coinAddress: '1AHnhqbvbYx3rnZx8uC7NbFZaTe4tafFHX',
// coinTransactionId:
// 'ab80abcb62bf6261ebc827c73dd59a4ce15d740b6ba734af6542f43b6485b923',
// subAccount: {
// uuid: '652e1add-0d0b-462c-a03c-d6197c825c1a',
// name: 'DEFAULT'
// }
// }
//
// deposit
//
// {
// "transactionClass": "COIN",
// "uuid": "eb65576f-c1a8-423c-8e2f-fa50109b2eab",
// "userUuid": "82027ee9-cb59-4f29-80d6-f7e793f39ad4",
// "amount": 3.99287184,
// "fee": 0,
// "balanceBefore": 8.39666034,
// "balanceAfter": 12.38953218,
// "ccy": "ETH",
// "transactionState": "PROCESSED",
// "transactionType": "DEPOSIT",
// "received": "1529420056000",
// "processed": "1529420766000",
// "timestampMillis": "1557442743854",
// "displayTitle": "Coin Deposit",
// "displayDescription": "Deposit to: 0xf123aa44fadea913a7da99cc2ee202db684ce0e3",
// "coinTransactionId": "0x33a3e5ea7c034dc5324a88aa313962df0a5d571ab4bcc3cb00b876b1bdfc54f7",
// "coinConfirmations": 51,
// "coinConfirmationsRequired": 45,
// "subAccount": {"uuid": "aba1de05-c7c6-49d7-84ab-a6aca0e827b6", "name": "DEFAULT"}
// }
//
const timestamp = this.safeInteger (transaction, 'received');
const updated = this.safeInteger (transaction, 'processed');
const transactionType = this.safeString (transaction, 'transactionType');
let type = undefined;
let amount = this.safeFloat (transaction, 'amount');
let address = this.safeString (transaction, 'coinAddress');
let tag = undefined;
if (transactionType === 'WITHDRAWAL') {
type = 'withdrawal';
amount = -amount;
if (address) {
// xrp: "coinAddress": "rw2ciyaNshpHe7bCHo4bRWq6pqqynnWKQg?dt=3750180345",
if (address.indexOf ('?dt=') >= 0) {
const parts = address.split ('?dt=');
address = parts[0];
tag = parts[1];
}
}
} else if (transactionType === 'DEPOSIT') {
if (!address) {
const displayDescription = this.safeString (transaction, 'displayDescription');
const addressText = displayDescription.replace ('Deposit to: ', '');
if (addressText.length > 0) {
// eth: "displayDescription": "Deposit to: 0xf123aa44fadea913a7da99cc2ee202db684ce0e3",
// xrp: "displayDescription": "Deposit to: rUjxty1WWLwX1evhKf3C2XNZDMcXEZ9ToJ?dt=504562345",
if (addressText.indexOf ('?dt=') >= 0) {
const parts = addressText.split ('?dt=');
address = parts[0];
tag = parts[1];
} else {
address = addressText;
}
}
}
type = 'deposit';
}
const currencyId = this.safeString (transaction, 'ccy');
const code = this.commonCurrencyCode (currencyId);
const transactionState = this.safeString (transaction, 'transactionState');
const status = this.parseTransactionStatus (transactionState);
const feeCost = this.safeFloat (transaction, 'fee');
const netAmount = amount - feeCost;
return {
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'id': this.safeString (transaction, 'uuid'),
'currency': code,
'amount': netAmount,
'address': address,
'tag': tag,
'status': status,
'type': type,
'updated': updated,
'txid': this.safeString (transaction, 'coinTransactionId'),
'fee': {
'cost': feeCost,
'currency': code,
},
'info': transaction,
};
}
parseTransactionStatus (status) {
const statuses = {
'PROCESSED': 'ok',
'REVERSED': 'canceled',
'CANCELLED_INSUFFICIENT_FUNDS': 'canceled',
'CANCELLED_LIMIT_BREACH': 'canceled',
};
return this.safeString (statuses, status, status);
}
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets ();
//
// v2
//
// {
// result: 'success',
// data: [
// {
// tradeId: 'c2ed821d-717a-4b7e-beb0-a9ba60e8f5a0',
// orderId: '5a65ae21-c7a8-4009-b3af-306c2ad21a02',
// timestamp: '1551357057000',
// tradedCurrencyFillAmount: '0.09006364',
// settlementCurrencyFillAmount: '270.96',
// settlementCurrencyFillAmountUnrounded: '270.96000000',
// price: '3008.53930',
// ccyPair: 'BTCEUR',
// side: 'BUY' // missing in v3
// },
// {
// tradeId: 'fc0d3a9d-8b0b-4dff-b2e9-edd160785210',
// orderId: '8161ae6e-251a-4eed-a56f-d3d6555730c1',
// timestamp: '1551357033000',
// tradedCurrencyFillAmount: '0.06521746',
// settlementCurrencyFillAmount: '224.09',
// settlementCurrencyFillAmountUnrounded: '224.09000000',
// price: '3436.04305',
// ccyPair: 'BTCUSD',
// side: 'BUY' // missing in v3
// },
// ]
// }
//
// v3
//
// {
// trades: [
// {
// tradeId: 'c2ed821d-717a-4b7e-beb0-a9ba60e8f5a0',
// orderId: '5a65ae21-c7a8-4009-b3af-306c2ad21a02',
// timestamp: '1551357057000',
// tradedCurrencyFillAmount: '0.09006364',
// settlementCurrencyFillAmount: '270.96',
// settlementCurrencyFillAmountUnrounded: '270.96000000',
// price: '3008.53930',
// ccyPair: 'BTCEUR'
// },
// {
// tradeId: 'fc0d3a9d-8b0b-4dff-b2e9-edd160785210',
// orderId: '8161ae6e-251a-4eed-a56f-d3d6555730c1',
// timestamp: '1551357033000',
// tradedCurrencyFillAmount: '0.06521746',
// settlementCurrencyFillAmount: '224.09',
// settlementCurrencyFillAmountUnrounded: '224.09000000',
// price: '3436.04305',
// ccyPair: 'BTCUSD'
// },
// ],
// count: 3,
// timestamp: '1557438456732',
// resultCode: 'OK'
// }
//
const request = {};
if (limit !== undefined) {
request['max'] = limit;
}
const method = this.safeString (this.options, 'fetchMyTradesMethod', 'private_post_money_trade_list');
const response = await this[method] (this.extend (request, params));
const trades = this.safeValue2 (response, 'trades', 'data', []);
const market = (symbol === undefined) ? undefined : this.market (symbol);
return this.parseTrades (trades, market, since, limit);
}
parseTrade (trade, market = undefined) {
//
// v2
//
// {
// tradeId: 'fc0d3a9d-8b0b-4dff-b2e9-edd160785210',
// orderId: '8161ae6e-251a-4eed-a56f-d3d6555730c1',
// timestamp: '1551357033000',
// tradedCurrencyFillAmount: '0.06521746',
// settlementCurrencyFillAmount: '224.09',
// settlementCurrencyFillAmountUnrounded: '224.09000000',
// price: '3436.04305',
// ccyPair: 'BTCUSD',
// side: 'BUY', // missing in v3
// }
//
// v3
//
// {
// tradeId: 'fc0d3a9d-8b0b-4dff-b2e9-edd160785210',
// orderId: '8161ae6e-251a-4eed-a56f-d3d6555730c1',
// timestamp: '1551357033000',
// tradedCurrencyFillAmount: '0.06521746',
// settlementCurrencyFillAmount: '224.09',
// settlementCurrencyFillAmountUnrounded: '224.09000000',
// price: '3436.04305',
// ccyPair: 'BTCUSD'
// }
//
const id = this.safeString (trade, 'tradeId');
const orderId = this.safeString (trade, 'orderId');
const timestamp = this.safeInteger (trade, 'timestamp');
const price = this.safeFloat (trade, 'price');
const amount = this.safeFloat (trade, 'tradedCurrencyFillAmount');
const cost = this.safeFloat (trade, 'settlementCurrencyFillAmount');
let side = this.safeString (trade, 'side');
side = (side === undefined) ? undefined : side.toLowerCase ();
return {
'id': id,
'order': orderId,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'symbol': this.findSymbol (this.safeString (trade, 'ccyPair')),
'type': undefined,
'side': side,
'price': price,
'amount': amount,
'cost': cost,
'fee': undefined,
'info': trade,
};
}
async fetchCurrencies (params = {}) {
const response = await this.v3publicGetCurrencyStatic (params);
const result = {};
const currencies = response['currencyStatic']['currencies'];
// "currencies": {
// "HKD": {
// "decimals": 2,
// "minOrderSize": 1.00000000,
// "maxOrderSize": 10000000000.00000000,
// "displayDenominator": 1,
// "summaryDecimals": 0,
// "displayUnit": "HKD",
// "symbol": "$",
// "type": "FIAT",
// "engineSettings": {
// "depositsEnabled": false,
// "withdrawalsEnabled": true,
// "displayEnabled": true,
// "mobileAccessEnabled": true
// },
// "minOrderValue": 1.00000000,
// "maxOrderValue": 10000000000.00000000,
// "maxMarketOrderValue": 36000.00000000,
// "maxMarketOrderSize": 36000.00000000,
// "assetDivisibility": 0
// },
// "ETH": {
// "decimals": 8,
// "minOrderSize": 0.00010000,
// "maxOrderSize": 1000000000.00000000,
// "type": "CRYPTO",
// "confirmationThresholds": [
// { "confosRequired": 30, "threshold": 0.50000000 },
// { "confosRequired": 45, "threshold": 10.00000000 },
// { "confosRequired": 70 }
// ],
// "networkFee": 0.00500000,
// "engineSettings": {
// "depositsEnabled": true,
// "withdrawalsEnabled": true,
// "displayEnabled": true,
// "mobileAccessEnabled": true
// },
// "minOrderValue": 0.00010000,
// "maxOrderValue": 10000000000.00000000,
// "maxMarketOrderValue": 10000000000.00000000,
// "maxMarketOrderSize": 1000000000.00000000,
// "digitalCurrencyType": "ETHEREUM",
// "assetDivisibility": 0,
// "assetIcon": "/images/currencies/crypto/ETH.svg"
// },
// },
const ids = Object.keys (currencies);
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
const currency = currencies[id];
const code = this.commonCurrencyCode (id);
const engineSettings = this.safeValue (currency, 'engineSettings');
const depositsEnabled = this.safeValue (engineSettings, 'depositsEnabled');
const withdrawalsEnabled = this.safeValue (engineSettings, 'withdrawalsEnabled');
const displayEnabled = this.safeValue (engineSettings, 'displayEnabled');
const active = depositsEnabled && withdrawalsEnabled && displayEnabled;
const precision = this.safeInteger (currency, 'decimals');
const fee = this.safeFloat (currency, 'networkFee');
let type = this.safeString (currency, 'type');
if (type !== 'undefined') {
type = type.toLowerCase ();
}
result[code] = {
'id': id,
'code': code,
'info': currency,
'name': code,
'type': type,
'active': active,
'precision': precision,
'fee': fee,
'limits': {
'amount': {
'min': this.safeFloat (currency, 'minOrderSize'),
'max': this.safeFloat (currency, 'maxOrderSize'),
},
'price': {
'min': undefined,
'max': undefined,
},
'cost': {
'min': this.safeFloat (currency, 'minOrderValue'),
'max': this.safeFloat (currency, 'maxOrderValue'),
},
'withdraw': {
'min': undefined,
'max': undefined,
},
},
};
}
return result;
}
async fetchMarkets (params = {}) {
const response = await this.v3publicGetCurrencyStatic (params);
//
// {
// "currencyStatic": {
// "currencies": {
// "HKD": {
// "decimals": 2,
// "minOrderSize": 1.00000000,
// "maxOrderSize": 10000000000.00000000,
// "displayDenominator": 1,
// "summaryDecimals": 0,
// "displayUnit": "HKD",
// "symbol": "$",
// "type": "FIAT",
// "engineSettings": {
// "depositsEnabled": false,
// "withdrawalsEnabled": true,
// "displayEnabled": true,
// "mobileAccessEnabled": true
// },
// "minOrderValue": 1.00000000,
// "maxOrderValue": 10000000000.00000000,
// "maxMarketOrderValue": 36000.00000000,
// "maxMarketOrderSize": 36000.00000000,
// "assetDivisibility": 0
// },
// "ETH": {
// "decimals": 8,
// "minOrderSize": 0.00010000,
// "maxOrderSize": 1000000000.00000000,
// "type": "CRYPTO",
// "confirmationThresholds": [
// { "confosRequired": 30, "threshold": 0.50000000 },
// { "confosRequired": 45, "threshold": 10.00000000 },
// { "confosRequired": 70 }
// ],
// "networkFee": 0.00500000,
// "engineSettings": {
// "depositsEnabled": true,
// "withdrawalsEnabled": true,
// "displayEnabled": true,
// "mobileAccessEnabled": true
// },
// "minOrderValue": 0.00010000,
// "maxOrderValue": 10000000000.00000000,
// "maxMarketOrderValue": 10000000000.00000000,
// "maxMarketOrderSize": 1000000000.00000000,
// "digitalCurrencyType": "ETHEREUM",
// "assetDivisibility": 0,
// "assetIcon": "/images/currencies/crypto/ETH.svg"
// },
// },
// "currencyPairs": {
// "ETHUSD": {
// "priceDecimals": 5,
// "engineSettings": {
// "tradingEnabled": true,
// "displayEnabled": true,
// "cancelOnly": true,
// "verifyRequired": false,
// "restrictedBuy": false,
// "restrictedSell": false
// },
// "minOrderRate": 10.00000000,
// "maxOrderRate": 10000.00000000,
// "displayPriceDecimals": 5,
// "tradedCcy": "ETH",
// "settlementCcy": "USD",
// "preferredMarket": "ANX",
// "chartEnabled": true,
// "simpleTradeEnabled": false
// },
// },
// },
// "timestamp": "1549840691039",
// "resultCode": "OK"
// }
//
const currencyStatic = this.safeValue (response, 'currencyStatic', {});
const currencies = this.safeValue (currencyStatic, 'currencies', {});
const currencyPairs = this.safeValue (currencyStatic, 'currencyPairs', {});
const result = [];
const ids = Object.keys (currencyPairs);
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
const market = currencyPairs[id];
//
// "ETHUSD": {
// "priceDecimals": 5,
// "engineSettings": {
// "tradingEnabled": true,
// "displayEnabled": true,
// "cancelOnly": true,
// "verifyRequired": false,
// "restrictedBuy": false,
// "restrictedSell": false
// },
// "minOrderRate": 10.00000000,
// "maxOrderRate": 10000.00000000,
// "displayPriceDecimals": 5,
// "tradedCcy": "ETH",
// "settlementCcy": "USD",
// "preferredMarket": "ANX",
// "chartEnabled": true,
// "simpleTradeEnabled": false
// },
//
const baseId = this.safeString (market, 'tradedCcy');
const quoteId = this.safeString (market, 'settlementCcy');
const base = this.commonCurrencyCode (baseId);
const quote = this.commonCurrencyCode (quoteId);
const symbol = base + '/' + quote;
const baseCurrency = this.safeValue (currencies, baseId, {});
const quoteCurrency = this.safeValue (currencies, quoteId, {});
const precision = {
'price': this.safeInteger (market, 'priceDecimals'),
'amount': this.safeInteger (baseCurrency, 'decimals'),
};
const engineSettings = this.safeValue (market, 'engineSettings');
const displayEnabled = this.safeValue (engineSettings, 'displayEnabled');
const tradingEnabled = this.safeValue (engineSettings, 'tradingEnabled');
const active = displayEnabled && tradingEnabled;
result.push ({
'id': id,
'symbol': symbol,
'base': base,
'quote': quote,
'baseId': baseId,
'quoteId': quoteId,
'precision': precision,
'active': active,
'limits': {
'price': {
'min': this.safeFloat (market, 'minOrderRate'),
'max': this.safeFloat (market, 'maxOrderRate'),
},
'amount': {
'min': this.safeFloat (baseCurrency, 'minOrderSize'),
'max': this.safeFloat (baseCurrency, 'maxOrderSize'),
},
'cost': {
'min': this.safeFloat (quoteCurrency, 'minOrderValue'),
'max': this.safeFloat (quoteCurrency, 'maxOrderValue'),
},
},
'info': market,
});
}
return result;
}
async fetchBalance (params = {}) {
await this.loadMarkets ();
const response = await this.privatePostMoneyInfo (params);
const balance = this.safeValue (response, 'data', {});
const wallets = balance['Wallets'];
const currencies = Object.keys (wallets);
const result = { 'info': balance };
for (let c = 0; c < currencies.length; c++) {
const currencyId = currencies[c];
const code = this.commonCurrencyCode (currencyId);
const account = this.account ();
if (currencyId in wallets) {
const wallet = wallets[currencyId];
account['free'] = this.safeFloat (wallet['Available_Balance'], 'value');
account['total'] = this.safeFloat (wallet['Balance'], 'value');
account['used'] = account['total'] - account['free'];
}
result[code] = account;
}
return this.parseBalance (result);
}
async fetchOrderBook (symbol, limit = undefined, params = {}) {
await this.loadMarkets ();
const request = {
'currency_pair': this.marketId (symbol),
};
const response = await this.publicGetCurrencyPairMoneyDepthFull (this.extend (request, params));
const orderbook = this.safeValue (response, 'data', {});
const t = this.safeInteger (orderbook, 'dataUpdateTime');
const timestamp = (t === undefined) ? t : parseInt (t / 1000);
return this.parseOrderBook (orderbook, timestamp, 'bids', 'asks', 'price', 'amount');
}
async fetchTicker (symbol, params = {}) {
await this.loadMarkets ();
const request = {
'currency_pair': this.marketId (symbol),
};
const response = await this.publicGetCurrencyPairMoneyTicker (this.extend (request, params));
const ticker = this.safeValue (response, 'data', {});
const t = this.safeInteger (ticker, 'dataUpdateTime');
const timestamp = (t === undefined) ? t : parseInt (t / 1000);
const bid = this.safeFloat (ticker['buy'], 'value');
const ask = this.safeFloat (ticker['sell'], 'value');
const baseVolume = this.safeFloat (ticker['vol'], 'value');
const last = this.safeFloat (ticker['last'], 'value');
return {
'symbol': symbol,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'high': this.safeFloat (ticker['high'], 'value'),
'low': this.safeFloat (ticker['low'], 'value'),
'bid': bid,
'bidVolume': undefined,
'ask': ask,
'askVolume': undefined,
'vwap': undefined,
'open': undefined,
'close': last,
'last': last,
'previousClose': undefined,
'change': undefined,
'percentage': undefined,
'average': this.safeFloat (ticker['avg'], 'value'),
'baseVolume': baseVolume,
'quoteVolume': undefined,
'info': ticker,
};
}
async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
throw new NotSupported (this.id + ' switched off the trades endpoint, see their docs at https://docs.anxv2.apiary.io');
}
async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets ();
const request = {};
if (limit !== undefined) {
request['max'] = limit;
}
const response = await this.v3privatePostOrderList (this.extend (request, params));
const orders = this.safeValue (response, 'orders', []);
const market = (symbol === undefined) ? undefined : this.market (symbol);
return this.parseOrders (orders, market, since, limit);
}
async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
'currency_pair': market['id'],
};
// ANXPro will return all symbol pairs regardless of what is specified in request
const response = await this.privatePostCurrencyPairMoneyOrders (this.extend (request, params));
//
// {
// "result": "success",
// "data": [
// {
// "oid": "e74305c7-c424-4fbc-a8a2-b41d8329deb0",
// "currency": "HKD",
// "item": "BTC",
// "type": "offer",
// "amount": {
// "currency": "BTC",
// "display": "10.00000000 BTC",
// "display_short": "10.00 BTC",
// "value": "10.00000000",
// "value_int": "1000000000"
// },
// "effective_amount": {
// "currency": "BTC",
// "display": "10.00000000 BTC",
// "display_short": "10.00 BTC",
// "value": "10.00000000",
// "value_int": "1000000000"
// },
// "price": {
// "currency": "HKD",
// "display": "412.34567 HKD",
// "display_short": "412.35 HKD",
// "value": "412.34567",
// "value_int": "41234567"
// },
// "status": "open",
// "date": 1393411075000,
// "priority": 1393411075000000,
// "actions": []
// },
// ...
// ]
// }
//
return this.parseOrders (this.safeValue (response, 'data', {}), market, since, limit);
}
parseOrder (order, market = undefined) {
if ('orderId' in order)
return this.parseOrderV3 (order, market);
else
return this.parseOrderV2 (order, market);
}
parseOrderStatus (status) {
const statuses = {
'ACTIVE': 'open',
'FULL_FILL': 'closed',
'CANCEL': 'canceled',
};
return this.safeString (statuses, status, status);
}
parseOrderV3 (order, market = undefined) {
//
// v3
//
// {
// orderType: 'LIMIT',
// tradedCurrency: 'XRP',
// settlementCurrency: 'BTC',
// tradedCurrencyAmount: '400.00000000',
// buyTradedCurrency: true,
// limitPriceInSettlementCurrency: '0.00007129',
// timestamp: '1522547850000',
// orderId: '62a8be4d-73c6-4469-90cd-28b4726effe0',
// tradedCurrencyAmountOutstanding: '0.00000000',
// orderStatus: 'FULL_FILL',
// executedAverageRate: '0.00007127',
// trades: [
// {
// tradeId: 'fe16b796-df57-41a2-b6d9-3489f189749e',
// orderId: '62a8be4d-73c6-4469-90cd-28b4726effe0',
// timestamp: '1522547850000',
// tradedCurrencyFillAmount: '107.91298639',
// settlementCurrencyFillAmount: '0.00768772',
// settlementCurrencyFillAmountUnrounded: '0.00768772',
// price: '0.00007124',
// ccyPair: 'XRPBTC'
// },
// {
// tradeId: 'e2962f67-c094-4243-8b88-0cdc70a1b1c7',
// orderId: '62a8be4d-73c6-4469-90cd-28b4726effe0',
// timestamp: '1522547851000',
// tradedCurrencyFillAmount: '292.08701361',
// settlementCurrencyFillAmount: '0.02082288',
// settlementCurrencyFillAmountUnrounded: '0.02082288',
// price: '0.00007129',
// ccyPair: 'XRPBTC'
// }
// ]
// }
//
const tradedCurrency = this.safeString (order, 'tradedCurrency');
const orderStatus = this.safeString (order, 'orderStatus');
const status = this.parseOrderStatus (orderStatus);
const settlementCurrency = this.safeString (order, 'settlementCurrency');
const symbol = this.findSymbol (tradedCurrency + '/' + settlementCurrency);
const buyTradedCurrency = this.safeString (order, 'buyTradedCurrency');
const side = buyTradedCurrency === 'true' ? 'buy' : 'sell';
const timestamp = this.safeInteger (order, 'timestamp');
let lastTradeTimestamp = undefined;
const trades = [];
let filled = 0;
const type = this.safeString (order, 'orderType').toLowerCase ();
for (let i = 0; i < order['trades'].length; i++) {
const trade = order['trades'][i];
const tradeTimestamp = this.safeInteger (trade, 'timestamp');
if (!lastTradeTimestamp || lastTradeTimestamp < tradeTimestamp)
lastTradeTimestamp = tradeTimestamp;
const parsedTrade = this.extend (this.parseTrade (trade), { 'side': side, 'type': type });
trades.push (parsedTrade);
filled = this.sum (filled, parsedTrade['amount']);
}
let price = this.safeFloat (order, 'limitPriceInSettlementCurrency');
const executedAverageRate = this.safeFloat (order, 'executedAverageRate');
const remaining = type === 'market' ? 0 : this.safeFloat (order, 'tradedCurrencyAmountOutstanding');
let amount = this.safeFloat (order, 'tradedCurrencyAmount');
if (!amount) {
const settlementCurrencyAmount = this.safeFloat (order, 'settlementCurrencyAmount');
amount = settlementCurrencyAmount / executedAverageRate;
}
const cost = executedAverageRate * filled;
return {
'id': this.safeString (order, 'orderId'),
'symbol': symbol,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'lastTradeTimestamp': lastTradeTimestamp,
'type': type,
'side': side,
'price': price,
'cost': cost,
'amount': amount,
'remaining': remaining,
'filled': filled,
'status': status,
'fee': undefined,
'trades': trades,
'info': order,
};
}
parseOrderV2 (order, market = undefined) {
//
// v2
//
// {
// "oid": "e74305c7-c424-4fbc-a8a2-b41d8329deb0",
// "currency": "HKD",
// "item": "BTC",
// "type": "offer", <-- bid/offer
// "amount": {
// "currency": "BTC",
// "display": "10.00000000 BTC",
// "display_short": "10.00 BTC",
// "value": "10.00000000",
// "value_int": "1000000000"
// },
// "effective_amount": {
// "currency": "BTC",
// "display": "10.00000000 BTC",
// "display_short": "10.00 BTC",
// "value": "10.00000000",
// "value_int": "1000000000"
// },
// "price": {
// "currency": "HKD",
// "display": "412.34567 HKD",
// "display_short": "412.35 HKD",
// "value": "412.34567",
// "value_int": "41234567"
// },
// "status": "open",
// "date": 1393411075000,
// "priority": 1393411075000000,
// "actions": []
// }
//
let id = this.safeString (order, 'oid');
let status = this.safeString (order, 'status');
let timestamp = this.safeInteger (order, 'date');
const baseId = this.safeString (order, 'item');
const quoteId = this.safeString (order, 'currency');
const marketId = baseId + '/' + quoteId;
market = this.safeValue (this.markets_by_id, marketId);
let symbol = undefined;
if (typeof market !== 'undefined') {
symbol = market['symbol'];
}
let amount_info = this.safeValue (order, 'amount', {});
let effective_info = this.safeValue (order, 'effective_amount', {});
let price_info = this.safeValue (order, 'price', {});
let remaining = this.safeFloat (effective_info, 'value');
let amount = this.safeFloat (amount_info, 'volume');
let price = this.safeFloat (price_info, 'value');
let filled = undefined;
let cost = undefined;
if (typeof amount !== 'undefined') {
if (typeof remaining !== 'undefined') {
filled = amount - remaining;
cost = price * filled;
}
}
let orderType = 'limit';
let side = this.safeString (order, 'type');
if (side === 'offer') {
side = 'sell';
} else {
side = 'buy';
}
let fee = undefined;
let trades = undefined; // todo parse trades
let lastTradeTimestamp = undefined;
return {
'info': order,
'id': id,
'symbol': symbol,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'lastTradeTimestamp': lastTradeTimestamp,
'type': orderType,
'side': side,
'price': price,
'cost': cost,
'amount': amount,
'remaining': remaining,
'filled': filled,
'status': status,
'fee': fee,
'trades': trades,
};
}
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
await this.loadMarkets ();
const market = this.market (symbol);
const amountMultiplier = Math.pow (10, market['precision']['amount']);
const request = {
'currency_pair': market['id'],
'amount_int': parseInt (amount * amountMultiplier), // 10^8
};
if (type === 'limit') {
const priceMultiplier = Math.pow (10, market['precision']['price']);
request['price_int'] = parseInt (price * priceMultiplier); // 10^5 or 10^8
}
request['type'] = (side === 'buy') ? 'bid' : 'ask';
const response = await this.privatePostCurrencyPairMoneyOrderAdd (this.extend (request, params));
return {
'info': response,
'id': response['data'],
};
}
async cancelOrder (id, symbol = undefined, params = {}) {
return await this.privatePostCurrencyPairMoneyOrderCancel ({ 'oid': id });
}
getAmountMultiplier (code) {
const multipliers = {
'BTC': 100000000,
'LTC': 100000000,
'STR': 100000000,
'XRP': 100000000,
'DOGE': 100000000,
};
const defaultValue = 100;
return this.safeInteger (multipliers, code, defaultValue);
}
async withdraw (code, amount, address, tag = undefined, params = {}) {
this.checkAddress (address);
await this.loadMarkets ();
let currency = this.currency (code);
let multiplier = this.getAmountMultiplier (code);
let request = {
'currency': currency,
'amount_int': parseInt (amount * multiplier),
'address': address,
};
if (tag !== undefined) {
request['destinationTag'] = tag;
}
let response = await this.privatePostMoneyCurrencySendSimple (this.extend (request, params));
return {
'info': response,
'id': response['data']['transactionId'],
};
}
async fetchDepositAddress (code, params = {}) {
await this.loadMarkets ();
let currency = this.currency (code);
let request = {
'currency': currency['id'],
};
let response = await this.privatePostMoneyCurrencyAddress (this.extend (request, params));
let result = response['data'];
let address = this.safeString (result, 'addr');
this.checkAddress (address);
return {
'currency': code,
'address': address,
'info': response,
};
}
nonce () {
return this.milliseconds ();
}
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
let request = this.implodeParams (path, params);
let query = this.omit (params, this.extractParams (path));
let url = this.urls['api'][api] + '/' + request;
if (api === 'public' || api === 'v3public') {
if (Object.keys (query).length)
url += '?' + this.urlencode (query);
} else {
this.checkRequiredCredentials ();
let nonce = this.nonce ();
let auth = undefined;
let contentType = undefined;
if (api === 'v3private') {
body = this.json (this.extend ({ 'tonce': nonce * 1000 }, query));
const path = url.replace ('https://anxpro.com/', '');
auth = path + '\0' + body;
contentType = 'application/json';
} else {
body = this.urlencode (this.extend ({ 'nonce': nonce }, query));
// eslint-disable-next-line quotes
auth = request + "\0" + body;
contentType = 'application/x-www-form-urlencoded';
}
let secret = this.base64ToBinary (this.secret);
let signature = this.hmac (this.encode (auth), secret, 'sha512', 'base64');
headers = {
'Content-Type': contentType,
'Rest-Key': this.apiKey,
'Rest-Sign': this.decode (signature),
};
}
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
}
handleErrors (httpCode, reason, url, method, headers, body, response) {
if (response