* Initial itBit implementation * Add tests for calculatePrice in exchange/itbit.js * Add etherium to supported crypto codes in common/itbit.js * Apply standardjs to itbit files * itbit trade test. not important * test getCurrencyRates in ticker/itbit.js
92 lines
2.6 KiB
JavaScript
92 lines
2.6 KiB
JavaScript
'use strict'
|
|
|
|
const querystring = require('querystring')
|
|
const axios = require('axios')
|
|
const crypto = require('crypto')
|
|
const _ = require('lodash/fp')
|
|
|
|
const API_ENDPOINT = 'https://api.itbit.com/v1'
|
|
|
|
let counter = -1
|
|
let lastTimestamp = Date.now()
|
|
|
|
function generateNonce () {
|
|
const timestamp = Date.now()
|
|
if (timestamp !== lastTimestamp) counter = -1
|
|
lastTimestamp = timestamp
|
|
counter = (counter + 1) % 1000
|
|
return timestamp.toString() + counter.toString()
|
|
}
|
|
|
|
function authRequest (account, method, path, data) {
|
|
if (!account.userId || !account.walletId || !account.clientKey || !account.clientSecret) {
|
|
const err = new Error('Must provide user ID, wallet ID, client key, and client secret')
|
|
return Promise.reject(err)
|
|
}
|
|
|
|
const url = buildURL(method, path, data)
|
|
const dataString = method !== 'GET' && !_.isEmpty(data) ? JSON.stringify(data) : ''
|
|
const nonce = generateNonce()
|
|
const timestamp = Date.now()
|
|
const message = nonce + JSON.stringify([method, url, dataString, nonce.toString(), timestamp.toString()])
|
|
|
|
const hashBuffer = crypto
|
|
.createHash('sha256')
|
|
.update(message).digest()
|
|
|
|
const bufferToHash = Buffer.concat([Buffer.from(url), hashBuffer])
|
|
|
|
const signature = crypto
|
|
.createHmac('sha512', Buffer.from(account.clientSecret))
|
|
.update(bufferToHash)
|
|
.digest('base64')
|
|
|
|
return request(method, path, data, {
|
|
'Authorization': account.clientKey + ':' + signature,
|
|
'X-Auth-Timestamp': timestamp,
|
|
'X-Auth-Nonce': nonce
|
|
})
|
|
}
|
|
|
|
function request (method, path, data, auth) {
|
|
const options = {
|
|
method: method,
|
|
url: buildURL(method, path, data),
|
|
headers: {
|
|
'User-Agent': 'Lamassu itBit node.js client',
|
|
...(auth)
|
|
},
|
|
...(method !== 'GET' && { data: data })
|
|
}
|
|
|
|
return axios(options)
|
|
.then(r => r.data)
|
|
.catch(e => {
|
|
var description = _.get(e, 'response.data.description')
|
|
throw new Error(description || e.message)
|
|
})
|
|
}
|
|
|
|
const cryptoCodeTranslations = { 'BTC': 'XBT', 'ETH': 'ETH' }
|
|
function buildMarket (fiatCode, cryptoCode) {
|
|
const translatedCryptoCode = cryptoCodeTranslations[cryptoCode]
|
|
if (!translatedCryptoCode) {
|
|
throw new Error('Unsupported crypto: ' + cryptoCode)
|
|
}
|
|
|
|
if (!_.includes(fiatCode, ['USD', 'EUR', 'SGD'])) {
|
|
throw new Error('Unsupported fiat: ' + fiatCode)
|
|
}
|
|
|
|
return translatedCryptoCode + fiatCode
|
|
}
|
|
|
|
function buildURL (method, path, data) {
|
|
let url = API_ENDPOINT + path
|
|
if (method === 'GET' && !_.isEmpty(data)) {
|
|
url += '?' + querystring.stringify(data)
|
|
}
|
|
return url
|
|
}
|
|
|
|
module.exports = { authRequest, request, buildMarket }
|