Comparing version 0.2.0 to 0.2.1
@@ -6,15 +6,28 @@ # cryptox ChangeLog | ||
## [0.2.1] - 2014-03-10 | ||
### Fixed | ||
- Fix: `bitfinex.getTicker()` returns the result with invalid JSON schema | ||
- Fix: `btce.getFee()` requires `pair` as parameter | ||
- Fix: bitfinex methods return BTC instead of XBT | ||
### Added | ||
- Implement `bitstamp.getTransactions()` | ||
- Implement `bitfinex.getTransactions()` | ||
## [0.2.0] - 2014-02-15 | ||
### Fixed | ||
- Fix bitstamp.getFee() was not returning error when API keys invalid | ||
- | ||
- Fix: `bitstamp.getFee()` does not return error when invalid API keys | ||
### Added | ||
- Add parameter `account_id` to `getBalance()` response | ||
- Implement `getBalance()` method for Bitstamp | ||
- Implement `getFee()` method for Bitstamp | ||
- Implement `getBalance()` method for BitX | ||
- Implement `getFee()` method for BitX | ||
- Implement `getTicker()` method for Bitfinex | ||
- Implement `getOrderBook()` method for Bitfinex | ||
- Implement `getBalance()` method for Bitfinex | ||
- Implement `bitstamp.getBalance()` method | ||
- Implement `bitstamp.getFee()` method | ||
- Implement `bitx.getBalance()` method | ||
- Implement `bitx.getFee()` method | ||
- Implement `bitfinex.getTicker()` method | ||
- Implement `bitfinex.getOrderBook()` method | ||
- Implement `bitfinex.getBalance()` method | ||
- Add the CHANGELOG file | ||
@@ -24,6 +37,6 @@ | ||
- Change API response for `getOrderbook()`. `asks` and `bids` are now arrays of JSON | ||
- Change API response for `getFee()`. Parameter `fee` is replaced with `maker_fee` and `taker_fee` | ||
- Change Bitcoin symbol from "BTC" to "XBT" | ||
- Change: API response for `getOrderbook()`. `asks` and `bids` are now arrays of JSON | ||
- Change: API response for `getFee()`. Parameter `fee` is replaced with `maker_fee` and `taker_fee` | ||
- Change: Bitcoin symbol from "BTC" to "XBT" | ||
- Update documentation | ||
@@ -32,5 +32,5 @@ cryptox API Documentation | ||
Depending on the parameters used, two types of objects can be created | ||
1. **public** (without authentication) - can be used for calling public API methods | ||
2. **private** (with authentication) - can be used for calling public and private API methods | ||
Depending on the parameters used, two types of objects can be created | ||
1. **public** (without authentication) - can be used for calling public API methods | ||
2. **private** (with authentication) - can be used for calling public and private API methods | ||
@@ -369,4 +369,94 @@ #### Examples | ||
### getTransactions | ||
```js | ||
getTransactions(options, callback); | ||
``` | ||
Returns user transaction history. Transactions are returned in descending order (newer transactions first). | ||
> Note: Depending on the exchange used and parameter combination this method can require up to 10 API calls | ||
#### Example | ||
```js | ||
account.getTransactions({limit: 2, sort: "desc"}, function (err, transactions) { | ||
if (!err) | ||
console.log(transactions); | ||
}); | ||
``` | ||
Example result: | ||
```js | ||
{ | ||
{ | ||
"timestamp": "2015-02-25T22:37:19+00:00", | ||
"error": "", | ||
"data": [ | ||
{ | ||
"tx_id": "7624780", | ||
"datetime": "2015-02-24T12:02:27+00:00", | ||
"type": "sell", | ||
"symbol": "XBTUSD", | ||
"amount_base": -0.30183411, | ||
"amount_counter": 72.62, | ||
"rate": 240.6, | ||
"fee_base": 0, | ||
"fee_counter": 0.15, | ||
"order_id": "58025817", | ||
"add_info": "" | ||
}, | ||
{ | ||
"tx_id": "7624695", | ||
"datetime": "2015-02-24T11:45:26+00:00", | ||
"type": "deposit", | ||
"symbol": "XBT", | ||
"amount_base": 49.04253049, | ||
"amount_counter": 0, | ||
"rate": 0, | ||
"fee_base": 0, | ||
"fee_counter": 0, | ||
"order_id": "", | ||
"add_info": "" | ||
} | ||
] | ||
} | ||
``` | ||
#### Arguments | ||
* `options` | ||
Parameter | Type | Required | Description | | ||
--- | --- | :-: | --- | | ||
`limit` | Number | no | limit result to that many transactions. Default: `50`| | ||
`skip` | Number | no | skip that many transactions before beginning to return results| | ||
`after` | String | no | return only transactions after or at the time specified here (ISO 8601 string)| | ||
`before` | String | no | return only transactions before or at the time specified here (ISO 8601 string)| | ||
`type` | String | no | return only transactions of this type <sup>[1]</sup>. Default return all transactions| | ||
`symbol` | String | no | return only transactions related to this curency symbol or curency pair | | ||
><sup>[1]</sup> valid values are `"trades"` (for buys or sells) or `"movements"` (for deposits and withdrawals) | ||
><sup>[2]</sup> valid values are currecny symbols (3 characters) or trading pair symbols (6 characters). | ||
* `callback` see [Callbacks](#callbacks) | ||
#### Response | ||
Parameter | Type | Description| | ||
--- | --- |--- | | ||
`tx_id` |String| transaction ID | | ||
`datetime` |String| ISO 8601 date & time of the transaction | | ||
`type` |String| transaction type: `"buy"`, `"sell"`, `"deposit"`, `"withdrawal"` | | ||
`symbol` |String| currency symbol <sup>[1]</sup> or currency pair <sup>[2]</sup>| | ||
`amount_base` |Number| currency amount <sup>[1]</sup> or base currency amount <sup>[3]</sup>| | ||
`amount_counter`|Number| counter currency amount <sup>[3]</sup>| | ||
`rate` |Number| zero (`0`) <sup>[1]</sup> or the exchange rate <sup>[2] [3]</sup>| | ||
`fee_base` |Number| amount of the fees debited | | ||
`fee_counter` |Number| amount of the fees debited | | ||
`order_id` |String| the id of the parent order of the trade. Can be `""` | | ||
`add_info` |String| additional info. Can be `""` | | ||
><sup>[1]</sup> for single currency transaction (`"deposit"` or `"withdrawal"`) | ||
><sup>[2]</sup> for trades / pair transaction (`"buy"` or `"sell"`) | ||
><sup>[3]</sup> See [Currency Pairs](#currency-pairs) | ||
### getBalance | ||
@@ -394,9 +484,9 @@ | ||
{ | ||
account_id: "1224342323", | ||
account_id: "8274332321", | ||
total: [ | ||
{currency: "XBT", amount: "4.86509177"}, | ||
{currency: "USD", amount: "100.44"} | ||
{currency: "XBT", amount: 4.86509177}, | ||
{currency: "USD", amount: 100.44} | ||
], | ||
available: [ | ||
{currency: "XBT", amount: "2.86709177"}, | ||
{currency: "XBT", amount: 2.86709177}, | ||
] | ||
@@ -445,3 +535,3 @@ } | ||
{ | ||
"orderId": "563489985", | ||
"order_id": "563489985", | ||
"pair": "LTCUSD", | ||
@@ -456,3 +546,3 @@ "type": "buy", | ||
{ | ||
"orderId": "563612426", | ||
"order_id": "563612426", | ||
"pair": "LTCUSD", | ||
@@ -538,3 +628,3 @@ "type": "buy", | ||
The first currency of a currency pair is called the "base currency", and the second currency is called the "quote currency". The currency pair shows how much of the quote currency is needed to purchase one unit of the base currency. | ||
The first currency of a currency pair is called the "base currency", and the second currency is called the "counter currency". The currency pair shows how much of the counter currency is needed to purchase one unit of the base currency. | ||
@@ -541,0 +631,0 @@ In example below the last price of the XBTUSD currency pair is 272.064. |
77
index.js
"use strict"; | ||
var path = require("path"); | ||
var _ = require("lodash"); | ||
var moment = require("moment"); | ||
@@ -15,4 +16,11 @@ var util = require("./lib/util"); //custom functions | ||
var locales = require("./lib/locales"); | ||
self.properties = Exchange.prototype.properties; | ||
self.properties = { | ||
defaults: { | ||
getTransactions: { | ||
limit: 50, | ||
sort: "desc" | ||
} | ||
} | ||
}; | ||
_.assign(self.properties, Exchange.prototype.properties); | ||
self.options = options || {}; | ||
@@ -32,2 +40,10 @@ if (!self.options.hasOwnProperty("lang")) | ||
var addDefaults = function (method, options) { | ||
_.forIn(self.properties.defaults[method], function (value, key) { | ||
if (!options.hasOwnProperty(key)) { | ||
options[key] = value; | ||
} | ||
}); | ||
}; | ||
self.getRate = function (options, callback){ | ||
@@ -41,3 +57,3 @@ var err; | ||
}); | ||
} | ||
}; | ||
@@ -52,3 +68,3 @@ self.getTicker = function (options, callback){ | ||
}); | ||
} | ||
}; | ||
@@ -63,3 +79,3 @@ self.getOrderBook = function (options, callback){ | ||
}); | ||
} | ||
}; | ||
@@ -74,3 +90,3 @@ self.getTrades = function (options, callback){ | ||
}); | ||
} | ||
}; | ||
@@ -85,13 +101,46 @@ self.getFee = function (options, callback){ | ||
}); | ||
} | ||
}; | ||
self.getTransactions = function (options, callback){ | ||
var method = "getTransactions"; | ||
var err; | ||
if (err = checkMethod("getTransactions")) | ||
err = checkMethod(method); // check is method is supported/implemented | ||
if (!err && options.hasOwnProperty(("type") && options.type !== "trades" && options.type !== "movements")) | ||
err = new Error("Invalid 'trades' argument"); | ||
if (!err && options.hasOwnProperty("before") && !moment(options.before, moment.ISO_8601).isValid()) | ||
err = new Error("Invalid 'before' argument (not ISO_8601 string)"); | ||
if (!err && options.hasOwnProperty("after") && !moment(options.after, moment.ISO_8601).isValid()) | ||
err = new Error("Invalid 'after' argument (not ISO_8601 string)"); | ||
if (!err && options.hasOwnProperty("before") && options.hasOwnProperty("after") && moment(options.before).isBefore(moment(options.after))) | ||
err = new Error("Invalid 'after'/'before' arguments ('before' < 'after')"); | ||
if (!err && options.hasOwnProperty("symbol") && !typeof options.symbol === "String") | ||
err = new Error("Invalid 'symbol' argument"); | ||
if (!err && options.hasOwnProperty("symbol")) { | ||
// check if supported symbol | ||
var supported, pair; | ||
supported = [3, 6].indexOf(options.symbol.length) > -1; | ||
if (supported) { | ||
var validSymbol; | ||
self.properties.instruments.forEach(function (e, index, array) { | ||
validSymbol = validSymbol || e.pair.indexOf(options.symbol) > -1 | ||
}); | ||
supported = validSymbol; | ||
} | ||
if (!supported) | ||
err = new Error("Symbol value not supported by the exchange"); | ||
} | ||
if (err) | ||
return callback(err, {timestamp: util.timestampNow(), error: err.message, data: []}); | ||
addDefaults(method, options); | ||
exchange.getTransactions(options, function (err, transactions){ | ||
callback(err, transactions); | ||
}); | ||
} | ||
}; | ||
@@ -106,3 +155,3 @@ self.getBalance = function (options, callback){ | ||
}); | ||
} | ||
}; | ||
@@ -117,3 +166,3 @@ self.getOpenOrders = function (options, callback){ | ||
}); | ||
} | ||
}; | ||
@@ -128,3 +177,3 @@ self.postSellOrder = function (options, callback){ | ||
}); | ||
} | ||
}; | ||
@@ -139,3 +188,3 @@ self.postBuyOrder = function (options, callback){ | ||
}); | ||
} | ||
}; | ||
@@ -142,0 +191,0 @@ self.cancelOrder = function (options, callback){ |
@@ -5,2 +5,4 @@ "use strict"; | ||
var _ = require("lodash"); | ||
var async = require("async"); | ||
var BigNumber = require("bignumber.js"); | ||
var BITFINEX = require('bitfinex'); | ||
@@ -21,2 +23,16 @@ | ||
var currencies = []; | ||
var pairs = []; | ||
self.properties.instruments.forEach(function (element, index, array) { | ||
var currency1 = element.pair.slice(0,3); | ||
var currency2 = element.pair.slice(3,6); | ||
if (currencies.indexOf(currency1) === -1) | ||
currencies.push(currency1); | ||
if (currencies.indexOf(currency2) === -1) | ||
currencies.push(currency2); | ||
if (pairs.indexOf(element.pair) === -1) | ||
pairs.push(element.pair); | ||
}); | ||
self.properties["currencies"] = currencies; | ||
self.properties["pairs"] = pairs; | ||
@@ -43,3 +59,3 @@ self.getRate = function (options, callback) { | ||
}); | ||
} | ||
}; | ||
@@ -60,3 +76,3 @@ var getOneTicker = function (options, callback) { | ||
data = { | ||
pair: options.pair, | ||
pair: options.pair.replace("BTC", "XBT"), | ||
last: parseFloat(bitfinexTicker.last_price), | ||
@@ -67,3 +83,3 @@ bid: parseFloat(bitfinexTicker.bid), | ||
high: parseFloat(bitfinexTicker.high), | ||
low: parseFloat(bitfinexTicker.low), | ||
low: parseFloat(bitfinexTicker.low) | ||
}; | ||
@@ -89,3 +105,3 @@ ticker.timestamp = util.timestamp(bitfinexTicker.timestamp); | ||
ticker.timestamp = oneTicker.timestamp; | ||
ticker.data.push(oneTicker.data); | ||
ticker.data.push(oneTicker.data[0]); | ||
callback(null, ticker); | ||
@@ -110,3 +126,3 @@ }); | ||
data = { | ||
pair: options.pair, | ||
pair: options.pair.replace("BTC", "XBT"), | ||
asks: [], | ||
@@ -158,11 +174,235 @@ bids: [] | ||
var _movements = function (symbol, options, callback) { // same function as native API wrapper, but it returns result according to JSON schema | ||
bitfinexPrivate.movements(symbol, options, function (err, xMovements) { | ||
var movement; | ||
var result = { | ||
timestamp: util.timestampNow(), | ||
error: err && err.message || "", | ||
data: [] | ||
}; | ||
if (err) | ||
return callback(err, result); | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/bitfinex-getTransactions_MockApiResponse.json", xTransactions); // only used to create MockApiResponse file for the test unit | ||
xMovements.forEach(function (element, index, array) { | ||
var btc, usd, tx; | ||
result.data.push( | ||
{ | ||
tx_id: "", | ||
datetime: "", | ||
type: "", | ||
symbol: "", | ||
amount_base: 0, | ||
amount_counter: 0, | ||
rate: 0, | ||
fee_base: 0, | ||
fee_counter: 0, | ||
order_id: "", | ||
add_info: "" | ||
}); | ||
tx = result.data[result.data.length - 1]; | ||
tx.tx_id = element.id.toString(); | ||
tx.datetime = moment.unix(parseFloat(element.timestamp)).utc().format(); | ||
tx.type = element.type.toLowerCase(); | ||
tx.symbol = symbol.toUpperCase().replace("BTC", "XBT"); | ||
tx.amount_base = parseFloat(element.amount); | ||
tx.add_info = "{'method': '" + element.method + ", 'description': '" + element.description + "'}"; | ||
}); | ||
return callback(null, result); | ||
}); | ||
}; | ||
var _mytrades = function (symbol, options, callback) { // same function as native API wrapper, but it returns result according to JSON schema | ||
bitfinexPrivate.past_trades(symbol, options, function (err, xTransactions) { | ||
var trade; | ||
var result = { | ||
timestamp: util.timestampNow(), | ||
error: err && err.message || "", | ||
data: [] | ||
}; | ||
if (err) | ||
return callback(err, result); | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/bitfinex-getTransactions_MockApiResponse.json", xTransactions); // only used to create MockApiResponse file for the test unit | ||
xTransactions.forEach(function (element, index, array) { | ||
var btc, usd, tx; | ||
result.data.push( | ||
{ | ||
tx_id: "", | ||
datetime: "", | ||
type: "", | ||
symbol: "", | ||
amount_base: 0, | ||
amount_counter: 0, | ||
rate: 0, | ||
fee_base: 0, | ||
fee_counter: 0, | ||
order_id: "", | ||
add_info: "" | ||
}); | ||
tx = result.data[result.data.length - 1]; | ||
tx.tx_id = element.tid.toString(); | ||
tx.datetime = moment.unix(parseFloat(element.timestamp)).utc().format(); | ||
tx.type = element.type.toLowerCase(); | ||
tx.symbol = symbol.toUpperCase().replace("BTC", "XBT"); | ||
switch (tx.type) { | ||
case "sell": | ||
tx.amount_base = -parseFloat(element.amount); | ||
break; | ||
case "buy": | ||
tx.amount_base = parseFloat(element.amount); | ||
break; | ||
default: | ||
err = new Error ("Unexpected type: " + JSON.stringify(element)); | ||
result.data = []; | ||
result.error = err.message; | ||
return callback(err, result); | ||
} | ||
tx.rate = parseFloat(element.price); | ||
var amount_base = new BigNumber(tx.amount_base); | ||
var rate = new BigNumber(tx.rate); | ||
var ROUND_UP = 0, ROUND_DOWN = 1, ROUND_HALF_UP = 4; | ||
var amount_counter = amount_base.times(rate).round(8, ROUND_HALF_UP).negated(); | ||
tx.amount_counter = amount_counter.toNumber(); | ||
tx.order_id = element.order_id ? element.order_id.toString() : ""; | ||
tx.add_info = "{'exchange': '" + element.exchange + "'}"; | ||
var fee, fee_currencyError = true; | ||
if (element.fee_currency.replace("BTC", "XBT") === tx.symbol.slice(0,3)) { | ||
tx.fee_base = parseFloat(element.fee_amount); | ||
fee = new BigNumber(tx.fee_base); | ||
tx.fee_counter = 0; | ||
tx.amount_base = amount_base.plus(fee).toNumber(); | ||
fee_currencyError = false; | ||
} | ||
if (element.fee_currency.replace("BTC", "XBT") === tx.symbol.slice(3,6)) { | ||
tx.fee_base = 0; | ||
tx.fee_counter = parseFloat(element.fee_amount); | ||
fee = new BigNumber(tx.fee_counter); | ||
tx.amount_counter = amount_counter.plus(fee).toNumber(); | ||
fee_currencyError = false; | ||
} | ||
if (fee_currencyError) { | ||
err = new Error ("Unexpected fee_currency: " + JSON.stringify(element)); | ||
result.data = []; | ||
result.error = err.message; | ||
return callback(err, result); | ||
} | ||
var stop = 1; | ||
}); | ||
return callback(null, result); | ||
}); | ||
}; | ||
self.getTransactions = function (options, callback) { | ||
var transactions; | ||
var err = new Error("Method not implemented"); | ||
transactions = { | ||
var xSymbol, xOptions, pOptions = {}, err, skip = 0, limit = 0; | ||
_.assign(pOptions, options); // will use pOption in async | ||
limit = options.hasOwnProperty("limit") ? options.limit : self.properties.dictionary.getTransactions.limit.maximum; | ||
pOptions["limit"] = limit; | ||
var transactions = { | ||
timestamp: util.timestampNow(), | ||
error: err.message, | ||
error: "", | ||
data: [] | ||
}; | ||
callback(err, transactions); | ||
var gotTheMovements = false; | ||
var gotTheTrades = false; | ||
if (options.type === "trades") | ||
gotTheMovements = true; | ||
if (options.type === "movements") | ||
gotTheTrades = true; | ||
if (options.hasOwnProperty("skip")) | ||
skip = options.skip; | ||
async.series({ | ||
getMovements: function(cb){ | ||
var currency1, currency2, currencies = []; | ||
xOptions = {}; | ||
if (gotTheMovements) | ||
return cb(null, 'skipped'); | ||
if (pOptions.hasOwnProperty("after")) | ||
xOptions["since"] = moment(pOptions.after).format("X"); | ||
if (pOptions.hasOwnProperty("before")) | ||
xOptions["until"] = moment(pOptions.before).format("X"); | ||
if (pOptions.hasOwnProperty("limit")) | ||
xOptions["limit"] = limit + skip; | ||
if (pOptions.hasOwnProperty("symbol")) { | ||
currency1 = pOptions.symbol.substr(0,3); | ||
currency2 = pOptions.symbol.substr(3,3); | ||
if (currency1 === currency2) | ||
currency2 = ""; | ||
self.properties.currencies.forEach(function (element, index, array) { | ||
if (element === currency1) | ||
currencies.push(currency1); | ||
if (element === currency2) | ||
currencies.push(currency2); | ||
}); | ||
} else { | ||
currencies = self.properties.currencies; | ||
} | ||
async.eachSeries(currencies, function (currency, callback) { // get movements for all currencies | ||
xSymbol = currency.replace("XBT", "BTC").toLowerCase(); | ||
_movements (xSymbol, xOptions, function (err, result) { | ||
if (err) { | ||
transactions.error = err.message; | ||
} else { | ||
util.extendTransactions(transactions, result); | ||
} | ||
return callback(err); | ||
}); | ||
}, function (err) { | ||
if (err) { | ||
transactions.error = err.message; | ||
return cb(err, "error"); | ||
} | ||
return cb(null, "done"); | ||
}); | ||
}, | ||
getMytrades: function(cb){ | ||
xOptions = {}; | ||
if (gotTheTrades) | ||
return cb(null, 'skipped'); | ||
if (pOptions.hasOwnProperty("after")) | ||
xOptions["timestamp"] = moment(pOptions.after).format("X"); | ||
if (pOptions.hasOwnProperty("before")) | ||
xOptions["until"] = moment(pOptions.before).format("X"); | ||
if (pOptions.hasOwnProperty("limit")) | ||
xOptions["limit_trades"] = limit + skip; | ||
var pairs = []; | ||
if (pOptions.hasOwnProperty("symbol")) { | ||
if (self.properties.pairs.indexOf(pOptions.symbol) > -1) | ||
pairs.push(pOptions.symbol); | ||
} else { | ||
pairs = self.properties.pairs; | ||
} | ||
async.eachSeries(pairs, function (pair, callback) { // get movements for all pairs | ||
xSymbol = pair.replace("XBT", "BTC").toLowerCase(); | ||
_mytrades (xSymbol, xOptions, function (err, result) { | ||
if (err) { | ||
transactions.error = err.message; | ||
} else { | ||
util.extendTransactions(transactions, result); | ||
} | ||
return callback(err); | ||
}); | ||
}, function (err) { | ||
if (err) { | ||
transactions.error = err.message; | ||
return cb(err, "error"); | ||
} | ||
return cb(null, "done"); | ||
}); | ||
} | ||
}, | ||
function(err, results) { | ||
var deleteCount; | ||
if (err) | ||
return callback (err, transactions); | ||
if (skip) { // remove items over the limit | ||
transactions.data.splice(0, skip); | ||
} | ||
if (limit && transactions.data.length > limit) { // remove items over the limit | ||
deleteCount = transactions.data.length - limit; | ||
transactions.data.splice(limit, deleteCount); | ||
} | ||
return callback (null, transactions); | ||
}); | ||
var done = true; | ||
}; | ||
@@ -184,2 +424,3 @@ | ||
} | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/bitstamp-getTransactions_MockApiResponse.json", bitfinexBalance); // only used to create MockApiResponse file for the test unit | ||
bitfinexBalance.forEach(function (oneBitfinexBalance, index, arr) { | ||
@@ -215,3 +456,3 @@ data = { | ||
callback(err, openOrders); | ||
} | ||
}; | ||
@@ -227,3 +468,3 @@ self.postSellOrder = function (options, callback) { | ||
callback(err, orderResult); | ||
} | ||
}; | ||
@@ -239,3 +480,3 @@ self.postBuyOrder = function (options, callback) { | ||
callback(err, orderResult); | ||
} | ||
}; | ||
@@ -258,8 +499,8 @@ self.cancelOrder = function (options, callback) { | ||
methods: { | ||
notImplemented: ["getTrades", "getFee", "getTransactions", "getOpenOrders", "postSellOrder", "postBuyOrder", "cancelOrder"], | ||
notSupported: [], | ||
notImplemented: ["getTrades", "getFee", "getOpenOrders", "postSellOrder", "postBuyOrder", "cancelOrder"], | ||
notSupported: [] | ||
}, | ||
instruments: [ // all allowed currency/asset combinatinos (pairs) that form a market | ||
{ | ||
pair: "BTCUSD", | ||
pair: "XBTUSD" | ||
}, | ||
@@ -270,3 +511,3 @@ { | ||
{ | ||
pair: "LTCBTC" | ||
pair: "LTCXBT" | ||
}, | ||
@@ -277,5 +518,31 @@ { | ||
{ | ||
pair: "DRKBTC" | ||
}, | ||
pair: "DRKXBT" | ||
} | ||
], | ||
dictionary: { | ||
"trades": { | ||
"limit_trades" : { | ||
"default": 500 | ||
}, | ||
"type" :{ | ||
"buy": "buy", | ||
"sell": "sell" | ||
} | ||
}, | ||
"movements": { | ||
"limit": { | ||
"default": 50, | ||
"max": 1000 | ||
}, | ||
"type": { | ||
"buy": "buy", | ||
"sell": "sell" | ||
} | ||
}, | ||
"getTransactions": { | ||
"limit" : { | ||
"maximum": 1000 | ||
} | ||
} | ||
}, | ||
publicAPI: { | ||
@@ -293,5 +560,5 @@ supported: true, // is public API (not requireing user authentication) supported by this exchange? | ||
monitorError: "", //if not able to monitor this exchange, please set it to an URL explaining the problem | ||
tradeError: "", //if not able to trade at this exchange, please set it to an URL explaining the problem | ||
} | ||
tradeError: "" //if not able to trade at this exchange, please set it to an URL explaining the problem | ||
}; | ||
module.exports = Bitfinex; |
"use strict"; | ||
var moment = require("moment"); | ||
var BITSTAMP = require('bitstamp'); | ||
var _ = require("lodash"); | ||
var async = require("async"); | ||
var BITSTAMP = require('./api_wrappers/bitstamp'); // remove dependency on bitstamp NPM module | ||
@@ -20,2 +22,83 @@ var util = require("./util"); //custom functions | ||
var checkErr = function (err, result) { // arguments are the result from BITSTAMP module, | ||
// returns the error (as Error object type) or null id no error | ||
if (err instanceof Error) | ||
return err; | ||
if (typeof err === "string") | ||
return new Error(err); | ||
if (result && typeof result.error === "string") | ||
return new Error(result.error); | ||
}; | ||
var user_transactions = function (options, callback) { // same function as native API wrapper, but it returns result normalized according to JSON schema | ||
bitstampPrivate.user_transactions(options, function (err, xTransactions) { | ||
var transactions, amount; | ||
transactions = { | ||
timestamp: util.timestampNow(), | ||
error: err && err.message || "", | ||
data: [] | ||
}; | ||
if (err) { | ||
return callback(err, transactions); | ||
} | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/bitstamp-getTransactions_MockApiResponse.json", xTransactions); // only used to create MockApiResponse file for the test unit | ||
xTransactions.forEach(function (element, index, array) { | ||
var btc, usd, tx; | ||
transactions.data.push( | ||
{ | ||
tx_id: "", | ||
datetime: "", | ||
type: "", | ||
symbol: "", | ||
amount_base: 0, | ||
amount_counter: 0, | ||
rate: 0, | ||
fee_base: 0, | ||
fee_counter: 0, | ||
order_id: "", | ||
add_info: "" | ||
}); | ||
tx = transactions.data[transactions.data.length - 1]; | ||
tx.tx_id = element.id.toString(); | ||
tx.datetime = moment(element.datetime + " Z").utc().format(); | ||
btc = parseFloat(element.btc); | ||
usd = parseFloat(element.usd); | ||
switch (element.type) { | ||
case 0: // deposit | ||
tx.type = "deposit"; | ||
if (btc > 0) { | ||
tx.symbol = "XBT"; | ||
tx.amount_base = btc; | ||
} | ||
if (usd > 0) { | ||
tx.symbol = "USD"; | ||
tx.amount_base = usd; | ||
} | ||
break; | ||
case 1: // withdrawal | ||
tx.type = "withdrawal"; | ||
if (btc < 0) { | ||
tx.symbol = "XBT"; | ||
tx.amount_base = btc; | ||
} | ||
if (usd < 0) { | ||
tx.symbol = "USD"; | ||
tx.amount_base = usd; | ||
} | ||
break; | ||
case 2: // market trade | ||
tx.type = element.btc < 0 ? "sell" : "buy"; | ||
tx.symbol = "XBTUSD"; | ||
tx.amount_base = btc; | ||
tx.amount_counter = usd; | ||
tx.rate = parseFloat(element.btc_usd); | ||
tx.order_id = element.order_id ? element.order_id.toString() : ""; | ||
break; | ||
} | ||
tx.fee_counter = parseFloat(element.fee); | ||
}); | ||
callback(null, transactions); | ||
}); | ||
}; | ||
self.getRate = function (options, callback) { | ||
@@ -41,3 +124,3 @@ self.getTicker(options, function(err, result) { | ||
}); | ||
} | ||
}; | ||
@@ -47,3 +130,4 @@ self.getTicker = function (options, callback) { | ||
var ticker, data; | ||
bitstampPublic.ticker(function(err, bitstampTicker) { | ||
bitstampPublic.ticker(function(xErr, bitstampTicker) { | ||
var err = checkErr(xErr, bitstampTicker); | ||
ticker = { | ||
@@ -57,3 +141,3 @@ timestamp: util.timestampNow(), | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/MockApiResponse.json", bitstampTicker); // only used to create MockApiResponse file for the test unit | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/bitstamp-getTransactions_MockApiResponse.json", bitstampTicker); // only used to create MockApiResponse file for the test unit | ||
ticker.timestamp = util.timestamp(bitstampTicker.timestamp); | ||
@@ -73,9 +157,10 @@ data = { | ||
}) | ||
} | ||
}; | ||
self.getOrderBook = function (options, callback) { | ||
var orderBook, data; | ||
bitstampPublic.order_book(function (err, bitstampOrderBook) { | ||
bitstampPublic.order_book(function (xErr, bitstampOrderBook) { | ||
// https://www.bitstamp.net/api/order_book/ | ||
var price, volume, order; | ||
var err = checkErr(xErr, bitstampOrderBook); | ||
orderBook = { | ||
@@ -88,3 +173,3 @@ timestamp: util.timestampNow(), | ||
return callback(err, orderBook); | ||
}; | ||
} | ||
orderBook.timestamp = util.timestamp(bitstampOrderBook.timestamp); | ||
@@ -111,5 +196,5 @@ data = { | ||
}); | ||
callback(err, orderBook); | ||
callback(null, orderBook); | ||
}); | ||
} | ||
}; | ||
@@ -125,9 +210,8 @@ self.getTrades = function (options, callback) { | ||
callback(err, trades); | ||
} | ||
}; | ||
self.getFee = function (options, callback) { | ||
bitstampPrivate.balance(function (err, bitstampBalance) { | ||
bitstampPrivate.balance(function (xErr, bitstampBalance) { | ||
var fee, data; | ||
if (!err && bitstampBalance.error) | ||
err = new Error(bitstampBalance.error); | ||
var err = checkErr(xErr, bitstampBalance); | ||
fee = { | ||
@@ -141,3 +225,3 @@ timestamp: util.timestampNow(), | ||
} | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/MockApiResponse.json", bitstampBalance); // only used to create MockApiResponse file for the test unit | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/bitstamp-getTransactions_MockApiResponse.json", bitstampBalance); // only used to create MockApiResponse file for the test unit | ||
data = { | ||
@@ -149,17 +233,90 @@ pair: "", | ||
fee.data.push(data); | ||
callback(err, fee); | ||
callback(null, fee); | ||
}); | ||
} | ||
}; | ||
self.getTransactions = function (options, callback) { | ||
var transactions; | ||
var err = new Error("Method not implemented"); | ||
transactions = { | ||
timestamp: util.timestampNow(), | ||
error: err.message, | ||
data: [] | ||
}; | ||
callback(err, transactions); | ||
} | ||
var limit, skip, skippedCount, beforeMoment, afterMoment, txMoment, fetchMore, manualFilter; | ||
var transactions = { | ||
timestamp: util.timestampNow(), | ||
error: "", | ||
data: [] | ||
}; | ||
util.addDefaults("getTransactions", options); | ||
// store for later manipulation of result data | ||
limit = options.limit; | ||
skip = options.hasOwnProperty("skip") && options.skip || 0; | ||
beforeMoment = options.hasOwnProperty("before") && moment(options.before) || null; | ||
afterMoment = options.hasOwnProperty("after") && moment(options.before) || null; | ||
//set xOptions to call the function | ||
var xOptions = { | ||
offset: skip, | ||
limit: options.limit, | ||
sort: options.sort | ||
}; | ||
if (options.hasOwnProperty("before") || options.hasOwnProperty("after") || options.hasOwnProperty("type")) { | ||
// if we will aplly manual filter, don't skip anything and fetch maximum | ||
xOptions.limit = self.properties.dictionary.getTransactions.limit.maximum; | ||
xOptions.offset = 0; | ||
manualFilter = true; | ||
} | ||
async.doWhilst( | ||
function (cb) { | ||
user_transactions(xOptions, function (err, result) { | ||
if (err) | ||
return cb(err); | ||
fetchMore = !(xOptions.limit < self.properties.dictionary.getTransactions.limit.maximum); // if we fetched less than maximum we don't need to fetchMore for sure | ||
fetchMore = fetchMore && !(result.data.length < xOptions.limit); // if fetched below the xOptions.limit, we can't fetch more (we fetched all) | ||
// drop records before, after and skip | ||
var drop, p = 0; // points to the current record to check; | ||
while (p < result.data.length) { | ||
drop = false; | ||
txMoment = moment(result.data[p].datetime); | ||
drop = beforeMoment && txMoment.isAfter(beforeMoment); | ||
if (!drop && options.hasOwnProperty("type")) { | ||
drop = (options.type === "movements") && (["buy", "sell"].indexOf(result.data[p].type) > -1); | ||
drop = drop || (options.type === "trades") && (["deposit", "withdrawal"].indexOf(result.data[p].type) > -1); | ||
} | ||
if (!drop && afterMoment && txMoment.isBefore(afterMoment)) { | ||
fetchMore = false; | ||
drop = true; | ||
} | ||
if (!drop && options.hasOwnProperty("symbol")) { | ||
var currency, found; | ||
currency = options.symbol.substr(0,3); | ||
found = result.data[p].symbol.indexOf(currency) > -1; | ||
currency = options.symbol.substr(3,3); | ||
found = found || currency !== "" && (result.data[p].symbol.indexOf(currency) > -1); | ||
drop = !found; | ||
} | ||
if (drop) | ||
result.data.splice(p, 1); // drop the record | ||
else | ||
p++; // or move pointer to next one | ||
} | ||
util.extendTransactions(transactions, result); | ||
fetchMore = fetchMore && transactions.data.length < limit + skip; | ||
cb(null); | ||
}); | ||
}, | ||
function () { | ||
if (fetchMore) | ||
xOptions.offset += xOptions.limit; | ||
return fetchMore; | ||
}, | ||
function (err) { | ||
if (err) { | ||
transactions.error = err.message; | ||
return callback(err, transactions); | ||
} | ||
if (manualFilter && skip) | ||
transactions.data.splice(0, skip); | ||
transactions.data.splice(limit, transactions.data.length - limit); | ||
callback(null, transactions); | ||
}); | ||
}; | ||
self.getBalance = function (options, callback) { | ||
@@ -176,3 +333,3 @@ bitstampPrivate.balance(function (err, bitstampBalance) { | ||
} | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/MockApiResponse.json", bitstampBalance); // only used to create MockApiResponse file for the test unit | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/bitstamp-getTransactions_MockApiResponse.json", bitstampBalance); // only used to create MockApiResponse file for the test unit | ||
data = { | ||
@@ -197,3 +354,3 @@ total: [], | ||
}); | ||
} | ||
}; | ||
@@ -209,3 +366,3 @@ self.getOpenOrders = function (options, callback) { | ||
callback(err, openOrders); | ||
} | ||
}; | ||
@@ -221,3 +378,3 @@ self.postSellOrder = function (options, callback) { | ||
callback(err, orderResult); | ||
} | ||
}; | ||
@@ -233,3 +390,3 @@ self.postBuyOrder = function (options, callback) { | ||
callback(err, orderResult); | ||
} | ||
}; | ||
@@ -245,3 +402,3 @@ self.cancelOrder = function (options, callback) { | ||
callback(err, orderResult); | ||
} | ||
}; | ||
} | ||
@@ -253,4 +410,4 @@ | ||
methods: { | ||
notImplemented: ["getTrades", "getTransactions", "getOpenOrders", "postSellOrder", "postBuyOrder", "cancelOrder"], | ||
notSupported: [], | ||
notImplemented: ["getTrades", "getOpenOrders", "postSellOrder", "postBuyOrder", "cancelOrder"], | ||
notSupported: [] | ||
}, | ||
@@ -262,3 +419,61 @@ instruments: [ // all allowed currency/asset combinatinos (pairs) that form a market | ||
], | ||
publicAPI: { | ||
dictionary: { | ||
"withdrawal_requests": { | ||
type: { | ||
"0": "SEPA", | ||
"1": "Bitcoin", | ||
"2": "WIRE transfer" | ||
}, | ||
status: { | ||
"0": "open", | ||
"1": "in process", | ||
"2": "finished", | ||
"3": "canceled", | ||
"4": "failed" | ||
} | ||
}, | ||
"sell": { | ||
"type": { | ||
"0": "buy", | ||
"1": "sell" | ||
} | ||
}, | ||
"buy": { | ||
"type" :{ | ||
"0": "buy", | ||
"1": "sell" | ||
} | ||
}, | ||
"open_orders": { | ||
"type" :{ | ||
"0": "buy", | ||
"1": "sell" | ||
} | ||
}, | ||
"user_transactions": { | ||
"offset" : { | ||
"default": 0 | ||
}, | ||
"limit" : { | ||
"default": 100, | ||
"maximum": 1000 | ||
}, | ||
"sort" : { | ||
"desc": "desc", | ||
"asc": "asc", | ||
"default": "desc" | ||
}, | ||
"type" :{ | ||
"0": "deposit", | ||
"1": "withdrawal", | ||
"2": "trade" | ||
} | ||
}, | ||
"getTransactions": { | ||
"limit" : { | ||
"maximum": 1000 | ||
} | ||
} | ||
}, | ||
publicAPI: { | ||
supported: true, // is public API (not requireing user authentication) supported by this exchange? | ||
@@ -275,5 +490,5 @@ requires: [] // required parameters | ||
monitorError: "", //if not able to monitor this exchange, please set it to an URL explaining the problem | ||
tradeError: "", //if not able to trade at this exchange, please set it to an URL explaining the problem | ||
} | ||
tradeError: "" //if not able to trade at this exchange, please set it to an URL explaining the problem | ||
}; | ||
module.exports = Bitstamp; |
@@ -42,3 +42,3 @@ "use strict"; | ||
}); | ||
} | ||
}; | ||
@@ -70,3 +70,3 @@ self.getTicker = function (options, callback) { | ||
ask: parseFloat(bitxTicker.ask), | ||
volume: parseFloat(bitxTicker.rolling_24_hour_volume), | ||
volume: parseFloat(bitxTicker.rolling_24_hour_volume) | ||
}; | ||
@@ -77,3 +77,3 @@ ticker.data.push(data); | ||
}) | ||
} | ||
}; | ||
@@ -90,7 +90,7 @@ self.getOrderBook = function (options, callback) { | ||
data: [] | ||
} | ||
}; | ||
if (err) { | ||
return callback(err, orderBook); | ||
} | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/MockApiResponse.json", bitxOrderBook); // only used to create MockApiResponse file for the test unit | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/bitstamp-getTransactions_MockApiResponse.json", bitxOrderBook); // only used to create MockApiResponse file for the test unit | ||
orderBook.timestamp = util.timestamp(bitxOrderBook.timestamp); | ||
@@ -119,3 +119,3 @@ data = { | ||
}); | ||
} | ||
}; | ||
@@ -136,3 +136,3 @@ self.getFee = function (options, callback) { | ||
callback(null, fee); | ||
} | ||
}; | ||
@@ -153,2 +153,3 @@ self.getBalance = function (options, callback) { | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/bitstamp-getTransactions_MockApiResponse.json", xBalance); // only used to create MockApiResponse file for the test unit | ||
xBalance.balance.forEach(function (element, index, bal) { | ||
@@ -188,3 +189,3 @@ var accountIndex, newAccount, balanceElement; | ||
notImplemented: ["getTrades", "getTransactions", "getOpenOrders", "postSellOrder", "postBuyOrder", "cancelOrder"], | ||
notSupported: [], | ||
notSupported: [] | ||
}, | ||
@@ -194,6 +195,6 @@ instruments: [ // all allowed currency/asset combinatinos (pairs) that form a market | ||
{ | ||
pair: "XBTKES" | ||
pair: "XBTZAR" | ||
}, | ||
{ | ||
pair: "XBTZAR" | ||
pair: "XBTKES" | ||
}, | ||
@@ -218,5 +219,5 @@ { | ||
maker_fee: 0, // fee is hardcoded and fixed | ||
taker_fee: 0.01, // fee is hardcoded and fixed | ||
} | ||
taker_fee: 0.01 // fee is hardcoded and fixed | ||
}; | ||
module.exports = Bitx; |
@@ -51,7 +51,9 @@ "use strict"; | ||
}); | ||
} | ||
}; | ||
self.getTicker = function (options, callback) { | ||
var ticker, data; | ||
var btcePair = pairMap(options["pair"]); | ||
var ticker, data, btcePair; | ||
if (!options) | ||
options = {}; | ||
btcePair = pairMap(options.pair); | ||
btcePublic.ticker(btcePair, function (err, btceTicker) { | ||
@@ -82,3 +84,3 @@ // https://btc-e.com/api/3/ticker/btc_usd | ||
}); | ||
} | ||
}; | ||
@@ -125,3 +127,3 @@ self.getOrderBook = function (options, callback) { | ||
}); | ||
} | ||
}; | ||
@@ -137,7 +139,7 @@ self.getTrades = function (options, callback) { | ||
callback(err, trades); | ||
} | ||
}; | ||
self.getFee = function (options, callback) { | ||
var fee, data; | ||
var btcePair = pairMap(options.pair); | ||
var btcePair = pairMap(self.properties.instruments[0].pair); | ||
btcePublic.fee(btcePair, function (err, btceFee) { | ||
@@ -173,3 +175,3 @@ // https://btc-e.com/api/2/btc_usd/fee | ||
callback(err, transactions); | ||
} | ||
}; | ||
@@ -186,3 +188,3 @@ self.getBalance = function (options, callback) { | ||
callback(err, balance); | ||
} | ||
}; | ||
@@ -200,7 +202,8 @@ self.getOpenOrders = function (options, callback) { | ||
btcePrivate.activeOrders(pair, function (err, result) { | ||
var record; | ||
openOrders.timestamp = util.timestampNow(); // we update the tiomestamp due to the callback | ||
if (!err) { | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/MockApiResponse.json", result); // only used to create MockApiResponse file for the test unit | ||
// var jf = require("jsonfile"); jf.writeFileSync(__dirname + "/bitstamp-getTransactions_MockApiResponse.json", result); // only used to create MockApiResponse file for the test unit | ||
var activeOrders = result["return"]; | ||
for (var record in activeOrders) { | ||
for (record in activeOrders) { | ||
var newOrder = { | ||
@@ -220,7 +223,7 @@ order_id: record.toString(), | ||
// if we have the error "Error: no orders" we will not return error | ||
err = null | ||
err = null; | ||
openOrders.error = err ? err.message : ""; | ||
callback(err, openOrders); | ||
}); | ||
} | ||
}; | ||
@@ -236,3 +239,3 @@ self.postSellOrder = function (options, callback) { | ||
callback(err, orderResult); | ||
} | ||
}; | ||
@@ -248,3 +251,3 @@ self.postBuyOrder = function (options, callback) { | ||
callback(err, orderResult); | ||
} | ||
}; | ||
@@ -260,3 +263,3 @@ self.cancelOrder = function (options, callback) { | ||
callback(err, orderResult); | ||
} | ||
}; | ||
@@ -268,7 +271,5 @@ var pairMap = function (pair) { // converts pairString to different format | ||
//Example "BTCUSD" to "btc_usd" | ||
var currency1, currency2; | ||
var currency1, currency2, currency; | ||
if (typeof pair !== "string") | ||
return ""; | ||
if(pair.length == 6) { | ||
@@ -280,3 +281,3 @@ currency1 = pair.slice(0,3).replace("XBT", "BTC").toLowerCase(); | ||
//Example "btc_usd" to "BTCUSD" | ||
var currency = pair.split("_"); | ||
currency = pair.split("_"); | ||
if(currency.length != 2) | ||
@@ -294,3 +295,3 @@ return pair; | ||
"getBalance", "postSellOrder", "postBuyOrder", "cancelOrder"], | ||
notSupported: [], | ||
notSupported: [] | ||
}, | ||
@@ -377,7 +378,5 @@ instruments: [ // all allowed currency/asset combinatinos (pairs) that form a market | ||
monitorError: "", //if not able to monitor this exchange, please set it to an URL explaining the problem | ||
tradeError: "", //if not able to trade at this exchange, please set it to an URL explaining the problem | ||
maker_fee: 0.002, // fee is hardcoded and fixed to 0.2% | ||
taker_fee: 0.002, // fee is hardcoded and fixed to 0.2% | ||
} | ||
tradeError: "" //if not able to trade at this exchange, please set it to an URL explaining the problem | ||
}; | ||
module.exports = Btce; |
@@ -0,9 +1,27 @@ | ||
"use strict"; | ||
var moment = require('moment'); | ||
var _ = require('lodash'); | ||
var BigNumber = require('bignumber.js'); | ||
var moment = require("moment"); | ||
var _ = require("lodash"); | ||
var BigNumber = require("bignumber.js"); | ||
// help functions | ||
var util = { | ||
replaceKey: function (object, changeKey, toKey) { | ||
if (object.hasOwnProperty(changeKey)) { | ||
object[toKey] = object[changeKey]; | ||
delete object[changeKey]; | ||
} | ||
return object; | ||
}, | ||
addDefaults: function (method, options) { | ||
var Cryptox = require("../index.js"); | ||
var cryptox = new Cryptox("bitstamp"); | ||
_.forIn(cryptox.properties.defaults[method], function (value, key) { | ||
if (!options.hasOwnProperty(key)) { | ||
options[key] = value; | ||
} | ||
}); | ||
}, | ||
updateBalanceArray: function (balance, newItems) { | ||
@@ -38,4 +56,39 @@ // the function takes two arguments | ||
return newBalance; | ||
}, | ||
tx_isAbove: function (tx, referenceTx) { | ||
//compare 2 transactions returns -1 if tx1 < th 2, zero or 1 if tx1 > tx2 | ||
var refm = moment (referenceTx.datetime); | ||
var m = moment (tx.datetime); | ||
if (m.isAfter(refm)) | ||
return 1; | ||
if (m.isBefore(refm)) | ||
return -1; | ||
if (m.isSame(refm)) | ||
return (tx.tx_id.localeCompare(referenceTx.tx_id)); | ||
}, | ||
extendTransactions: function (target, newTransactions) { | ||
// Merge the content of newTransactions into the target | ||
// target must be initially sorted. the target result will also be sorted | ||
var i, p = 0, stop, newTx; | ||
for (i = 0; i < newTransactions.data.length; i++) { | ||
newTx = newTransactions.data[i]; | ||
// move the pointer up as much as possible | ||
stop = false; | ||
while (!stop && p > 0) { | ||
stop = util.tx_isAbove(newTx, target.data[--p]) < 1; | ||
} | ||
// move the pointer down as much as possible | ||
stop = false; | ||
while (!stop && p < target.data.length) { | ||
stop = util.tx_isAbove(newTx, target.data[p]) >= 0; | ||
if (!stop) | ||
p++; | ||
} | ||
target.data.splice(p, 0, newTransactions.data[i]); // insert at position p; | ||
} | ||
}, | ||
// check if two moments are corresponding | ||
@@ -42,0 +95,0 @@ // to the same time |
{ | ||
"name": "cryptox", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "Common API wrapper for multiple crypto currency exchanges", | ||
@@ -36,3 +36,3 @@ "main": "index.js", | ||
"dependencies": { | ||
"bitstamp": "0.1.9", | ||
"underscore": "1.4.4", | ||
"btc-e": "*", | ||
@@ -46,3 +46,3 @@ "moment": ">=2.9.0", | ||
"open-exchange-rates" : ">=0.3.0", | ||
"bitfinex": ">=0.3.3" | ||
"bitfinex": "0.4.0" | ||
}, | ||
@@ -49,0 +49,0 @@ "devDependencies": { |
@@ -73,15 +73,15 @@ cryptox | ||
| |Bitfinex|Bitstamp |BitX|BTC-e|CEX.io|OXR <sup>[1]</sup>| | ||
| --- | :-: | :-: |:-: | :-: | :-: | :-: | | ||
|[getRate](#getrate) | FI | FI | FI | FI | | FI | | ||
|[getTicker](#getticker) | FI | FI | FI | FI | | — | | ||
|[getOrderBook](#getorderbook) | FI | FI | FI | FI | | — | | ||
|[getTrades](#gettrades) | | | | | | — | | ||
|[getFee](#getfee) | | FI | FI | FI | | — | | ||
|[getTransactions](#gettransactions)| | | | | | — | | ||
|[getBalance](#getbalance) | FI | FI | FI | | | — | | ||
|[getOpenOrders](#getopenorders) | | | | FI | | — | | ||
|[postSellOrder](#postsellorder) | | | | | | — | | ||
|[postBuyOrder](#postbuyorder) | | | | | | — | | ||
|[cancelOrder](#cancelorder) | | | | | | — | | ||
| |Bitfinex|Bitstamp |BitX|BTC-e|CEX.io|OXR <sup>[1]</sup>| | ||
| --- | :-: | :-: |:-: | :-: | :-: | :-: | | ||
|[getRate](docs/api_documentation.md#getrate) | FI | FI | FI | FI | | FI | | ||
|[getTicker](docs/api_documentation.md#getticker) | FI | FI | FI | FI | | — | | ||
|[getOrderBook](docs/api_documentation.md#getorderbook) | FI | FI | FI | FI | | — | | ||
|[getTrades](docs/api_documentation.md#gettrades) | | | | | | — | | ||
|[getFee](docs/api_documentation.md#getfee) | | FI | FI | FI | | — | | ||
|[getTransactions](docs/api_documentation.md#gettransactions)| FI | FI | | | | — | | ||
|[getBalance](docs/api_documentation.md#getbalance) | FI | FI | FI | | | — | | ||
|[getOpenOrders](docs/api_documentation.md#getopenorders) | | | | FI | | — | | ||
|[postSellOrder](docs/api_documentation.md#postsellorder) | | | | | | — | | ||
|[postBuyOrder](docs/api_documentation.md#postbuyorder) | | | | | | — | | ||
|[cancelOrder](docs/api_documentation.md#cancelorder) | | | | | | — | | ||
@@ -94,3 +94,3 @@ | ||
><sup>[1]</sup> OXR ([Open Exchange Rates](https://openexchangerates.org/)) is not a crypto exchange, however it provides exchange rates for world fiat currencies | ||
><sup>[1]</sup> OXR ([Open Exchange Rates](https://openexchangerates.org/)) is not a crypto exchange, however it provides exchange rates for world fiat currencies | ||
@@ -107,4 +107,2 @@ | ||
**IMPORTANT NOTE**: Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable. | ||
See detailed [ChangeLog](CHANGELOG.md) | ||
@@ -111,0 +109,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
181522
36
2463
118
1
+ Addedunderscore@1.4.4
+ Addedbitfinex@0.4.0(transitive)
+ Addedcrypto@0.0.3(transitive)
- Removedbitstamp@0.1.9
- Removedbitfinex@1.0.3(transitive)
- Removedbitstamp@0.1.9(transitive)
Updatedbitfinex@0.4.0