Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

cryptox

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cryptox - npm Package Compare versions

Comparing version 0.2.0 to 0.2.1

.idea/codeStyleSettings.xml

37

CHANGELOG.md

@@ -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.

"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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc