UNPKG

crypto-client

Version:

An unified client for all cryptocurrency exchanges.

222 lines (221 loc) 8.02 kB
"use strict"; 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;