crypto-client
Version:
An unified client for all cryptocurrency exchanges.
222 lines (221 loc) • 8.02 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.withdraw = exports.getWithdrawalFees = exports.getDepositAddresses = exports.queryAllBalances = exports.cancelOrder = exports.queryOrder = exports.placeOrder = void 0;
const assert_1 = require("assert");
const axios_1 = __importDefault(require("axios"));
const crypto_1 = __importDefault(require("crypto"));
const qs_1 = __importDefault(require("qs"));
const uuid_1 = require("uuid");
const config_1 = require("../config");
const util_1 = require("../util");
const DOMAIN = 'www.bitstamp.net';
function sign(apiKey, apiSecret, verb, path, data) {
assert_1.strict.ok(apiKey);
assert_1.strict.ok(apiSecret);
assert_1.strict.ok(path);
assert_1.strict.ok(data);
const CONTENT_TYPE = 'application/x-www-form-urlencoded';
const nonce = uuid_1.v1();
const timestamp = Date.now();
const stringToSign = `BITSTAMP ${apiKey}${verb}${DOMAIN}${path}${CONTENT_TYPE}${nonce}${timestamp}v2${data}`;
const signature = crypto_1.default.createHmac('sha256', apiSecret).update(stringToSign).digest('hex');
const headers = {
'X-Auth': `BITSTAMP ${apiKey}`,
'X-Auth-Signature': signature,
'X-Auth-Nonce': nonce,
'X-Auth-Timestamp': timestamp,
'X-Auth-Version': 'v2',
'Content-Type': CONTENT_TYPE,
};
return headers;
}
function sign_v1(apiKey, apiSecret, customerId, nonce) {
assert_1.strict.ok(apiKey);
assert_1.strict.ok(apiSecret);
assert_1.strict.ok(customerId);
assert_1.strict.ok(nonce);
const message = `${nonce}${customerId}${apiKey}`;
const signature = crypto_1.default
.createHmac('sha256', apiSecret)
.update(message)
.digest('hex')
.toUpperCase();
return signature;
}
async function privateRequestV1(path, params) {
try {
assert_1.strict.ok(!path.includes('/v2/'));
const nonce = Date.now();
const signature = sign_v1(config_1.USER_CONFIG.BITSTAMP_API_KEY, config_1.USER_CONFIG.BITSTAMP_API_SECRET, config_1.USER_CONFIG.BITSTAMP_USER_ID, nonce);
Object.assign(params, { key: config_1.USER_CONFIG.BITSTAMP_API_KEY, signature, nonce });
const payload = qs_1.default.stringify(params);
const response = await axios_1.default.post(`https://${DOMAIN}${path}`, payload).catch((e) => {
return e;
});
if (response instanceof Error)
return response;
assert_1.strict.equal(response.status, 200);
if (response.data.error)
return new Error(JSON.stringify(response.data.error));
return response.data;
}
catch (e) {
return e;
}
}
async function privateRequestV2(path, params) {
try {
assert_1.strict.ok(config_1.USER_CONFIG.BITSTAMP_API_KEY);
assert_1.strict.ok(config_1.USER_CONFIG.BITSTAMP_API_SECRET);
assert_1.strict.ok(path.includes('/v2/'));
const payload = qs_1.default.stringify(params) || '{}';
const headers = sign(config_1.USER_CONFIG.BITSTAMP_API_KEY, config_1.USER_CONFIG.BITSTAMP_API_SECRET, 'POST', path, payload);
const response = await axios_1.default.post(`https://${DOMAIN}${path}`, payload, {
headers,
}).catch((e) => {
return e;
});
if (response instanceof Error)
return response;
assert_1.strict.equal(response.status, 200);
if (response.data.status === 'error') {
return new Error(JSON.stringify(response.data.reason)); // eslint-disable-line no-underscore-dangle
}
return response.data;
}
catch (e) {
return e;
}
}
async function privateRequest(path, params = {}) {
return path.includes('/v2/') ? privateRequestV2(path, params) : privateRequestV1(path, params);
}
async function placeOrder(market, price, quantity, sell) {
assert_1.strict.ok(market);
const [priceStr, quantityStr] = util_1.convertPriceAndQuantityToStrings(market, price, quantity, sell);
const path = `/api/v2/${sell ? 'sell' : 'buy'}/${market.id}/`;
const data = await privateRequest(path, { price: priceStr, amount: quantityStr });
if (data instanceof Error)
return data;
return data.id;
}
exports.placeOrder = placeOrder;
async function queryOrder(orderId) {
const data = await privateRequest('/api/order_status/', { id: orderId });
if (data instanceof Error)
return undefined;
return data;
}
exports.queryOrder = queryOrder;
async function cancelOrder(orderId) {
assert_1.strict.ok(orderId);
const data = await privateRequest('/api/v2/cancel_order/', { id: orderId });
if (data instanceof Error)
return false;
return data.id === parseInt(orderId, 10);
}
exports.cancelOrder = cancelOrder;
async function queryAllBalances(all = false) {
const result = {};
const data = await privateRequest('/api/v2/balance/');
if (data instanceof Error)
return data;
const dataTyped = data;
Object.keys(dataTyped)
.filter((x) => (all ? x.endsWith('_balance') : x.endsWith('_available')))
.forEach((key) => {
const symbol = key.substring(0, key.indexOf('_')).toUpperCase();
result[symbol] = parseFloat(dataTyped[key]);
});
return result;
}
exports.queryAllBalances = queryAllBalances;
async function fetchDepositAddress(symbol) {
const pathMap = {
BCH: '/api/v2/bch_address/',
BTC: '/api/bitcoin_deposit_address/',
ETH: '/api/v2/eth_address/',
LTC: '/api/v2/ltc_address/',
XRP: '/api/v2/xrp_address/',
};
if (!(symbol in pathMap))
return undefined;
const path = pathMap[symbol];
const data = await privateRequest(path);
if (data instanceof Error)
return undefined;
if (path.includes('/v2/')) {
const dataTyped = data;
return Object.assign({ symbol, platform: symbol }, dataTyped);
}
const address = data;
return { symbol, platform: symbol, address };
}
async function getDepositAddresses(symbols) {
assert_1.strict.ok(symbols.length);
const requests = symbols.map((symbol) => fetchDepositAddress(symbol));
const arr = await Promise.all(requests);
const result = {};
arr.forEach((address) => {
if (address) {
if (!(address.symbol in result))
result[address.symbol] = {};
result[address.symbol][address.symbol] = address;
}
});
return result;
}
exports.getDepositAddresses = getDepositAddresses;
function getWithdrawalFees() {
const data = {
BTC: 0.0005,
BCH: 0.0001,
LTC: 0.001,
ETH: 0.001,
XRP: 0.02,
USD: 25,
EUR: 0.9,
};
const result = {};
Object.keys(data).forEach((symbol) => {
result[symbol] = {};
result[symbol][symbol] = {
symbol,
platform: symbol,
fee: data[symbol],
min: 0,
};
});
return result;
}
exports.getWithdrawalFees = getWithdrawalFees;
async function withdraw(symbol, address, amount, memo) {
const pathMap = {
BCH: '/api/v2/bch_withdrawal/',
BTC: '/api/bitcoin_withdrawal/',
ETH: '/api/v2/eth_withdrawal/',
LTC: '/api/v2/ltc_withdrawal/',
XRP: '/api/ripple_withdrawal/',
};
if (!(symbol in pathMap))
return new Error(`Invalid symbol ${symbol} at Bitstamp`);
const path = pathMap[symbol];
const params = {
address,
amount: amount.toString(),
};
if (symbol === 'XRP') {
if (memo !== undefined) {
params.destination_tag = memo;
}
}
const data = await privateRequest(path, params);
if (data instanceof Error)
return data;
const dataTyped = data;
return dataTyped.id.toString();
}
exports.withdraw = withdraw;