UNPKG

bot18

Version:

A high-frequency cryptocurrency trading bot by Zenbot creator @carlos8f

942 lines (800 loc) 23.9 kB
const assert = require('assert'); const nock = require('nock'); const Gdax = require('../index.js'); const key = 'key'; const secret = 'secret'; const passphrase = 'passphrase'; const EXCHANGE_API_URL = 'https://api.gdax.com'; const authClient = new Gdax.AuthenticatedClient(key, secret, passphrase); suite('AuthenticatedClient', () => { afterEach(() => nock.cleanAll()); test('._getSignature()', () => { const method = 'PUT'; const relativeURI = '/orders'; const opts = { method: 'PUT', uri: 'https://api.gdax.com/orders', }; const sig = authClient._getSignature(method, relativeURI, opts); assert.equal(sig['CB-ACCESS-KEY'], key); assert.equal(sig['CB-ACCESS-PASSPHRASE'], passphrase); assert(sig['CB-ACCESS-TIMESTAMP']); assert(sig['CB-ACCESS-SIGN']); }); test('.getCoinbaseAccounts()', done => { const expectedResponse = [ { id: 'fc3a8a57-7142-542d-8436-95a3d82e1622', name: 'ETH Wallet', balance: '0.00000000', currency: 'ETH', type: 'wallet', primary: false, active: true, }, ]; nock(EXCHANGE_API_URL) .get('/coinbase-accounts') .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => authClient.getCoinbaseAccounts((err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }) ); let promisetest = authClient .getCoinbaseAccounts() .then(data => assert.deepEqual(data, expectedResponse)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.getAccount()', done => { const expectedResponse = { id: 'a1b2c3d4', balance: '1.100', holds: '0.100', available: '1.00', currency: 'USD', }; nock(EXCHANGE_API_URL) .get('/accounts/test-id') .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => authClient.getAccount('test-id', (err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }) ); let promisetest = authClient .getAccount('test-id') .then(data => assert.deepEqual(data, expectedResponse)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.getAccounts()', done => { const expectedResponse = [ { id: 'a1b2c3d4', balance: '1.100', holds: '0.100', available: '1.00', currency: 'USD', }, ]; nock(EXCHANGE_API_URL) .get('/accounts') .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => authClient.getAccounts((err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }) ); let promisetest = authClient .getAccounts() .then(data => assert.deepEqual(data, expectedResponse)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.getAccountHistory()', done => { const expectedResponse = [ { id: '100', created_at: '2014-11-07T08:19:27.028459Z', amount: '0.001', balance: '239.669', type: 'fee', details: { order_id: 'd50ec984-77a8-460a-b958-66f114b0de9b', trade_id: '74', product_id: 'BTC-USD', }, }, ]; nock(EXCHANGE_API_URL) .get('/accounts/test-id/ledger') .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => authClient.getAccountHistory('test-id', (err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }) ); let promisetest = authClient .getAccountHistory('test-id') .then(data => assert.deepEqual(data, expectedResponse)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.getAccountTransfers()', done => { const expectedResponse = [ { id: '100', created_at: '2014-11-07T08:19:27.028459Z', amount: '0.001', balance: '239.669', type: 'fee', details: { order_id: 'd50ec984-77a8-460a-b958-66f114b0de9b', trade_id: '74', product_id: 'BTC-USD', }, }, ]; nock(EXCHANGE_API_URL) .get('/accounts/test-id/transfers') .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => authClient.getAccountTransfers('test-id', (err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }) ); let promisetest = authClient .getAccountTransfers('test-id') .then(data => assert.deepEqual(data, expectedResponse)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.getAccountHolds()', done => { const expectedResponse = [ { id: '82dcd140-c3c7-4507-8de4-2c529cd1a28f', account_id: 'e0b3f39a-183d-453e-b754-0c13e5bab0b3', created_at: '2014-11-06T10:34:47.123456Z', updated_at: '2014-11-06T10:40:47.123456Z', amount: '4.23', type: 'order', ref: '0a205de4-dd35-4370-a285-fe8fc375a273', }, ]; nock(EXCHANGE_API_URL) .get('/accounts/test-id/holds') .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => { authClient.getAccountHolds('test-id', (err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }); }); let promisetest = authClient .getAccountHolds('test-id') .then(data => assert.deepEqual(data, expectedResponse)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.placeOrder()', done => { const order = { side: 'buy', funds: '20.00', product_id: 'ETH-USD', type: 'market', }; const expectedOrder = order; const expectedResponse = { id: '0428b97b-bec1-429e-a94c-59992926778d', }; nock(EXCHANGE_API_URL) .post('/orders', expectedOrder) .reply(200, expectedResponse); authClient.placeOrder(order, (err, resp, data) => { assert.ifError(err); assert.deepEqual(data, expectedResponse); nock.cleanAll(); done(); }); }); test('.buy()', done => { const order = { size: '10', product_id: 'BTC-USD', price: '100', }; const expectedOrder = order; expectedOrder.side = 'buy'; const expectedResponse = { id: '0428b97b-bec1-429e-a94c-59992926778d', }; nock(EXCHANGE_API_URL) .post('/orders', expectedOrder) .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => { authClient.buy(order, (err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }); }); let promisetest = authClient .buy(order) .then(data => assert.deepEqual(data, expectedResponse)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.buy() market order', done => { const order = { funds: '20.00', product_id: 'BTC-USD', type: 'market', }; const expectedOrder = order; expectedOrder.side = 'buy'; const expectedResponse = { id: '0428b97b-bec1-429e-a94c-59992926778d', }; nock(EXCHANGE_API_URL) .post('/orders', expectedOrder) .reply(200, expectedResponse); authClient.buy(order, (err, resp, data) => { assert.ifError(err); assert.deepEqual(data, expectedResponse); nock.cleanAll(); done(); }); }); test('.sell()', done => { const order = { size: '10', product_id: 'BTC-USD', price: '100', }; const expectedOrder = order; expectedOrder.side = 'sell'; const expectedResponse = { id: '0428b97b-bec1-429e-a94c-59992926778d', }; nock(EXCHANGE_API_URL) .post('/orders', expectedOrder) .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => { authClient.sell(order, (err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }); }); let promisetest = authClient .sell(order) .then(data => assert.deepEqual(data, expectedResponse)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); suite('.cancelAllOrders()', () => { test('cancels all orders', () => { const cancelledOrdersOne = [ 'deleted-id-1', 'deleted-id-2', 'deleted-id-3', 'deleted-id-4', ]; const cancelledOrdersTwo = [ 'deleted-id-5', 'deleted-id-6', 'deleted-id-7', 'deleted-id-8', ]; const totalExpectedDeleted = cancelledOrdersOne.concat( cancelledOrdersTwo ); const nockSetup = () => { // first list of Id's that just got cancelled nock(EXCHANGE_API_URL) .delete('/orders') .reply(200, cancelledOrdersOne) // second list of Id's that just got cancelled .delete('/orders') .reply(200, cancelledOrdersTwo) // return empty array signalling the completion of all // orders having been cancelled .delete('/orders') .reply(200, []); }; nockSetup(); let cbtest = new Promise((resolve, reject) => { const p = authClient.cancelAllOrders((err, resp, data) => { if (err) { reject(err); } else { assert.deepEqual(data, totalExpectedDeleted); } resolve(); }); if (p !== undefined) { reject(); } }); return cbtest .then(() => { nockSetup(); return authClient.cancelAllOrders(); }) .then(data => assert.deepEqual(data, totalExpectedDeleted)); }); test('handles errors', () => { nock(EXCHANGE_API_URL) .delete('/orders') .times(2) .reply(400, { message: 'some error' }); const cbtest = new Promise((resolve, reject) => { authClient.cancelAllOrders(err => { if (err) { assert.equal(err.response.statusCode, 400); assert.equal(err.data.message, 'some error'); resolve(); } else { reject(); } }); }); const promisetest = authClient .cancelAllOrders() .then(() => assert.fail('should have thrown an error')) .catch(err => { assert.equal(err.response.statusCode, 400); assert.equal(err.data.message, 'some error'); }); return Promise.all([cbtest, promisetest]); }); }); suite('.cancelOrder()', () => { test('requires orderID', done => { let cbtest = new Promise(resolve => { authClient .cancelOrder(err => { assert(err); resolve(); }) .catch(() => {}); }); let promisetest = authClient .cancelOrder() .catch(err => !assert(err) && true) .then(val => assert.strictEqual(val, true)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('cancels order', done => { const expectedResponse = [ { id: 'd50ec984-77a8-460a-b958-66f114b0de9b', size: '3.0', price: '100.23', product_id: 'BTC-USD', status: 'open', filled_size: '1.23', fill_fees: '0.001', settled: false, side: 'buy', created_at: '2014-11-14T06:39:55.189376Z', }, ]; nock(EXCHANGE_API_URL) .get('/orders') .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => { authClient.getOrders((err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }); }); let promisetest = authClient .getOrders() .then(data => assert.deepEqual(data, expectedResponse)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); }); test('.getFills()', done => { const expectedResponse = [ { trade_id: 74, product_id: 'BTC-USD', price: '10.00', size: '0.01', order_id: 'd50ec984-77a8-460a-b958-66f114b0de9b', created_at: '2014-11-07T22:19:28.578544Z', liquidity: 'T', fee: '0.00025', settled: true, side: 'buy', }, ]; nock(EXCHANGE_API_URL) .get('/fills') .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => { authClient.getFills((err, response, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }); }); let promisetest = authClient .getFills() .then(data => assert.deepEqual(data, expectedResponse)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.getFundings()', done => { const expectedResponse = [ { id: '280c0a56-f2fa-4d3b-a199-92df76fff5cd', order_id: '280c0a56-f2fa-4d3b-a199-92df76fff5cd', profile_id: 'd881e5a6-58eb-47cd-b8e2-8d9f2e3ec6f6', amount: '545.2400000000000000', status: 'outstanding', created_at: '2017-03-18T00:34:34.270484Z', currency: 'USD', repaid_amount: '532.7580047716682500', }, ]; nock(EXCHANGE_API_URL) .get('/funding') .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => { authClient.getFundings((err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }); }); let promisetest = authClient.getFundings(); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.repay()', done => { const params = { amount: 10000, currency: 'USD', }; nock(EXCHANGE_API_URL) .post('/funding/repay', params) .reply(200, {}); nock(EXCHANGE_API_URL) .post('/funding/repay', params) .reply(200, {}); let cbtest = new Promise((resolve, reject) => { authClient.repay(params, err => { if (err) { reject(err); } resolve(); }); }); let promisetest = authClient.repay(params); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.marginTransfer()', done => { const params = { margin_profile_id: '45fa9e3b-00ba-4631-b907-8a98cbdf21be', type: 'deposit', currency: 'USD', amount: 2, }; const expectedResponse = { created_at: '2017-01-25T19:06:23.415126Z', id: '80bc6b74-8b1f-4c60-a089-c61f9810d4ab', user_id: '521c20b3d4ab09621f000011', profile_id: 'cda95996-ac59-45a3-a42e-30daeb061867', margin_profile_id: '45fa9e3b-00ba-4631-b907-8a98cbdf21be', type: 'deposit', amount: '2', currency: 'USD', account_id: '23035fc7-0707-4b59-b0d2-95d0c035f8f5', margin_account_id: 'e1d9862c-a259-4e83-96cd-376352a9d24d', margin_product_id: 'BTC-USD', status: 'completed', nonce: 25, }; nock(EXCHANGE_API_URL) .post('/profiles/margin-transfer', params) .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => { authClient.marginTransfer(params, (err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }); }); let promisetest = authClient.marginTransfer(params); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.closePosition()', done => { const params = { repay_only: false, }; nock(EXCHANGE_API_URL) .post('/position/close', params) .times(2) .reply(200, {}); let cbtest = new Promise((resolve, reject) => { authClient.closePosition(params, err => { if (err) { reject(err); } resolve(); }); }); let promisetest = authClient.closePosition(params); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.deposit()', done => { const transfer = { amount: 10480, currency: 'USD', coinbase_account_id: 'test-id', }; const expectedTransfer = transfer; nock(EXCHANGE_API_URL) .post('/deposits/coinbase-account', expectedTransfer) .times(2) .reply(200, {}); let cbtest = new Promise((resolve, reject) => { authClient.deposit(transfer, err => { if (err) { reject(err); } resolve(); }); }); let promisetest = authClient.deposit(transfer); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail); }); test('.depositCrypto()', done => { const params = { currency: 'BTC', }; const expectedAccountsRespons = [ { id: 'test-id', name: 'BTC Wallet', balance: '0.00000000', currency: 'BTC', type: 'wallet', primary: true, active: true, }, ]; const expectedAddressResponse = { id: 'test-id', address: 'test-address', name: 'New exchange deposit address', created_at: '2018-02-18T06:26:10Z', updated_at: '2018-02-18T06:26:10Z', network: 'bitcoin', uri_scheme: 'bitcoin', resource: 'address', resource_path: '/v2/accounts/test-account-id/addresses/test-id', warning_title: 'Only send Bitcoin (BTC) to this address', warning_details: 'Sending any other digital asset, including Bitcoin Cash (BCH), will result in permanent loss.', callback_url: null, exchange_deposit_address: true, }; nock(EXCHANGE_API_URL) .get('/coinbase-accounts') .times(2) .reply(200, expectedAccountsRespons); nock(EXCHANGE_API_URL) .post('/coinbase-accounts/test-id/addresses') .times(2) .reply(200, expectedAddressResponse); let cbtest = new Promise((resolve, reject) => { authClient.depositCrypto(params, err => { if (err) { reject(err); } resolve(); }); }); let promisetest = authClient.depositCrypto(params); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail); }); test('.withdraw()', done => { const transfer = { amount: 10480, currency: 'USD', coinbase_account_id: 'test-id', }; const expectedTransfer = transfer; nock(EXCHANGE_API_URL) .post('/withdrawals/coinbase-account', expectedTransfer) .times(2) .reply(200, {}); let cbtest = new Promise((resolve, reject) => { authClient.withdraw(transfer, err => { if (err) { reject(err); } resolve(); }); }); let promisetest = authClient.withdraw(transfer); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.createReport()', done => { const params = { type: 'fills', start_date: '2014-11-01T00:00:00.000Z', end_date: '2014-11-30T23:59:59.000Z', product_id: 'BTC-USD', format: 'pdf', }; const expectedResponse = { id: 'test-id', type: 'fills', status: 'pending', created_at: '2015-01-06T10:34:47.000Z', completed_at: 'undefined', expires_at: '2015-01-13T10:35:47.000Z', file_url: 'undefined', params: { start_date: '2014-11-01T00:00:00.000Z', end_date: '2014-11-30T23:59:59.000Z', }, }; nock(EXCHANGE_API_URL) .post('/reports', params) .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => authClient.createReport(params, (err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }) ); let promisetest = authClient .createReport(params) .then(data => assert.deepEqual(data, expectedResponse)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.getReportStatus()', done => { const expectedResponse = { id: 'test-id', type: 'fills', status: 'ready', created_at: '2015-01-06T10:34:47.000Z', completed_at: '2015-01-06T10:35:47.000Z', expires_at: '2015-01-13T10:35:47.000Z', file_url: 'https://example.com/0428b97b.../fills.pdf', params: { start_date: '2014-11-01T00:00:00.000Z', end_date: '2014-11-30T23:59:59.000Z', }, }; nock(EXCHANGE_API_URL) .get('/reports/test-id') .times(2) .reply(200, expectedResponse); let cbtest = new Promise((resolve, reject) => authClient.getReportStatus('test-id', (err, resp, data) => { if (err) { reject(err); } assert.deepEqual(data, expectedResponse); resolve(); }) ); let promisetest = authClient .getReportStatus('test-id') .then(data => assert.deepEqual(data, expectedResponse)); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); test('.withdrawCrypto()', done => { const withdrawParams = { amount: 10480, currency: 'BTC', crypto_address: 'test-address', }; nock(EXCHANGE_API_URL) .post('/withdrawals/crypto', withdrawParams) .times(2) .reply(200, {}); let cbtest = new Promise((resolve, reject) => { authClient.withdrawCrypto(withdrawParams, err => { if (err) { reject(err); } resolve(); }); }); let promisetest = authClient.withdrawCrypto(withdrawParams); Promise.all([cbtest, promisetest]) .then(() => done()) .catch(err => assert.ifError(err) || assert.fail()); }); });