diff --git a/__tests__/krakenClient/init.js b/__tests__/krakenClient/init.js new file mode 100644 index 0000000..f70e3d7 --- /dev/null +++ b/__tests__/krakenClient/init.js @@ -0,0 +1,24 @@ +const KrakenClient = require('../../kraken.js') + +describe('KrakenClient', async ()=>{ + it('[Constructor] null param', ()=>{ + try{ new KrakenClient() } + catch (e) { + expect(e.message).toBe('[Error] null key or secret') + } + }) + + it('[Constructor]', ()=>{ + const key = 'mockKey' + const secret = 'mockSecret' + const kc = new KrakenClient(key, secret) + const reqConfig = require('../../config/request.json') + + expect(kc.config).toEqual({ + ...reqConfig, + key, + secret + }) + }) + +}) \ No newline at end of file diff --git a/__tests__/lib/signature.js b/__tests__/lib/signature.js new file mode 100644 index 0000000..8f312b7 --- /dev/null +++ b/__tests__/lib/signature.js @@ -0,0 +1,13 @@ +const {getMessageSignature} = require('../../lib/signature') + +describe('KrakenClient', async ()=>{ + it('[Constructor] null param', ()=>{ + const path = '/mock/path' + const request = {mock:'foo'} + const secret = 'mockSecret' + const nonce = 'mockNonce' + const result = getMessageSignature(path, request, secret, nonce) + + expect(result).toBe('VP8viIhM4IDc0gOPRN4oyDqyBr5/f/rSWMMt/NGjwlq9NcmcSnZESpQ1aT4lETVzmyfzUbR6cIi8+2V1wTWtlQ==') + }) +}) \ No newline at end of file diff --git a/config/methods.json b/config/methods.json new file mode 100644 index 0000000..5430270 --- /dev/null +++ b/config/methods.json @@ -0,0 +1,4 @@ +{ + "public" : [ "Time", "Assets", "AssetPairs", "Ticker", "Depth", "Trades", "Spread", "OHLC" ], + "private" : [ "Balance", "TradeBalance", "OpenOrders", "ClosedOrders", "QueryOrders", "TradesHistory", "QueryTrades", "OpenPositions", "Ledgers", "QueryLedgers", "TradeVolume", "AddOrder", "CancelOrder", "DepositMethods", "DepositAddresses", "DepositStatus", "WithdrawInfo", "Withdraw", "WithdrawStatus", "WithdrawCancel" ] +} \ No newline at end of file diff --git a/config/request.json b/config/request.json new file mode 100644 index 0000000..cad1051 --- /dev/null +++ b/config/request.json @@ -0,0 +1,5 @@ +{ + "url" : "https://api.kraken.com", + "version" : 0, + "timeout" : 5000 +} \ No newline at end of file diff --git a/example/basic.js b/example/basic.js new file mode 100644 index 0000000..e4274d8 --- /dev/null +++ b/example/basic.js @@ -0,0 +1,11 @@ +const key = process.env.KRAKEN_API_KEY // replace your key here +const secret = process.env.KRAKEN_API_SECRET // replace your secret here +const KrakenClient = require('../kraken.js') + +(async () => { + // Display user's balance + console.log(await kraken.api('Balance')); + + // Get Ticker Info + console.log(await kraken.api('Ticker', { pair : 'XXBTZUSD' })); +})(); \ No newline at end of file diff --git a/kraken.js b/kraken.js index 4cedb7f..f839702 100644 --- a/kraken.js +++ b/kraken.js @@ -1,31 +1,12 @@ const got = require('got'); -const crypto = require('crypto'); const qs = require('qs'); +const {getMessageSignature} = require('./lib/signature') // Public/Private method names -const methods = { - public : [ 'Time', 'Assets', 'AssetPairs', 'Ticker', 'Depth', 'Trades', 'Spread', 'OHLC' ], - private : [ 'Balance', 'TradeBalance', 'OpenOrders', 'ClosedOrders', 'QueryOrders', 'TradesHistory', 'QueryTrades', 'OpenPositions', 'Ledgers', 'QueryLedgers', 'TradeVolume', 'AddOrder', 'CancelOrder', 'DepositMethods', 'DepositAddresses', 'DepositStatus', 'WithdrawInfo', 'Withdraw', 'WithdrawStatus', 'WithdrawCancel' ], -}; +const methods = require('./config/methods.json'); // Default options -const defaults = { - url : 'https://api.kraken.com', - version : 0, - timeout : 5000, -}; - -// Create a signature for a request -const getMessageSignature = (path, request, secret, nonce) => { - const message = qs.stringify(request); - const secret_buffer = new Buffer(secret, 'base64'); - const hash = new crypto.createHash('sha256'); - const hmac = new crypto.createHmac('sha512', secret_buffer); - const hash_digest = hash.update(nonce + message).digest('binary'); - const hmac_digest = hmac.update(path + hash_digest, 'binary').digest('base64'); - - return hmac_digest; -}; +const defaults = require('./config/request.json'); // Send an API request const rawRequest = async (url, headers, data, timeout) => { @@ -67,12 +48,12 @@ const rawRequest = async (url, headers, data, timeout) => { */ class KrakenClient { constructor(key, secret, options) { + if(!key || !secret) throw new Error('[Error] null key or secret') + // Allow passing the OTP as the third argument for backwards compatibility - if(typeof options === 'string') { - options = { otp : options }; - } + if(typeof options === 'string') options = { otp : options }; - this.config = Object.assign({ key, secret }, defaults, options); + this.config = { ...defaults, key, secret, options}; } /** @@ -107,9 +88,7 @@ class KrakenClient { * @param {Function} callback A callback function to be executed when the request is complete * @return {Object} The request object */ - publicMethod(method, params, callback) { - params = params || {}; - + publicMethod(method, params = {}, callback) { // Default params to empty object if(typeof params === 'function') { callback = params; @@ -136,9 +115,7 @@ class KrakenClient { * @param {Function} callback A callback function to be executed when the request is complete * @return {Object} The request object */ - privateMethod(method, params, callback) { - params = params || {}; - + privateMethod(method, params = {}, callback) { // Default params to empty object if(typeof params === 'function') { callback = params; diff --git a/lib/signature.js b/lib/signature.js new file mode 100644 index 0000000..dcb213e --- /dev/null +++ b/lib/signature.js @@ -0,0 +1,15 @@ +const crypto = require('crypto'); +const qs = require('qs'); + +// Create a signature for a request +const getMessageSignature = (path='', request={}, secret='', nonce='') => { + const message = qs.stringify(request); + const secret_buffer = new Buffer(secret, 'base64'); + const hash = new crypto.createHash('sha256'); + const hmac = new crypto.createHmac('sha512', secret_buffer); + const hash_digest = hash.update(nonce + message).digest('binary'); + const hmac_digest = hmac.update(path + hash_digest, 'binary').digest('base64'); + return hmac_digest; +}; + +module.exports = {getMessageSignature}; \ No newline at end of file diff --git a/package.json b/package.json index 5ec4452..0f879d6 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,9 @@ "name": "kraken-api", "version": "1.0.0", "description": "kraken.com API client library for NodeJS", + "scripts": { + "test": "jest" + }, "keywords": [ "kraken", "api", @@ -27,5 +30,8 @@ "url": "https://github.com/nothingisdead/npm-kraken-api/issues", "email": "rbmyr8@gmail.com" }, - "readmeFilename": "README.md" + "readmeFilename": "README.md", + "devDependencies": { + "jest": "^22.4.3" + } }