Time synchronization with server
- wrapper for /v2/public/time rest endpoint - synchronize time before trying to authenticate a request in order to avoid invalid authentication because prevented replay attacks. Resolves #1
This commit is contained in:
@@ -3,7 +3,7 @@ const assert = require('assert');
|
||||
|
||||
const request = require('request');
|
||||
|
||||
const {signMessage} = require('./utility.js');
|
||||
const {signMessage, getServerTimeOffset} = require('./utility.js');
|
||||
|
||||
const baseUrls = {
|
||||
livenet: 'https://api.bybit.com',
|
||||
@@ -14,9 +14,13 @@ module.exports = class Request {
|
||||
|
||||
constructor(key, secret, livenet=false) {
|
||||
this.baseUrl = baseUrls[livenet === true ? 'livenet' : 'testnet'];
|
||||
this._timeOffset = null;
|
||||
|
||||
if(key) assert(secret, 'Secret is required for private enpoints');
|
||||
|
||||
this._syncTime();
|
||||
setInterval(this._syncTime.bind(this), 3600000);
|
||||
|
||||
this.key = key;
|
||||
this.secret = secret;
|
||||
}
|
||||
@@ -34,12 +38,22 @@ module.exports = class Request {
|
||||
return result;
|
||||
}
|
||||
|
||||
async getTimeOffset() {
|
||||
const start = Date.now();
|
||||
const result = await this.get('/v2/public/time');
|
||||
const end = Date.now();
|
||||
|
||||
return Math.ceil((result.time_now * 1000) - start + ((end - start) / 2));
|
||||
}
|
||||
|
||||
async _call(method, endpoint, params) {
|
||||
const publicEndpoint = endpoint.startsWith('/v2/public');
|
||||
|
||||
if(!publicEndpoint) {
|
||||
if(!this.key || !this.secret) throw new Error('Private endpoints require api and private keys set');
|
||||
|
||||
if(this._timeOffset === null) await this._syncTime();
|
||||
|
||||
params = this._signRequest(params);
|
||||
}
|
||||
|
||||
@@ -73,7 +87,7 @@ module.exports = class Request {
|
||||
const params = {
|
||||
...data,
|
||||
api_key: this.key,
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now() + this._timeOffset
|
||||
};
|
||||
|
||||
if(this.key && this.secret) {
|
||||
@@ -89,4 +103,8 @@ module.exports = class Request {
|
||||
.map(key => `${key}=${params[key]}`)
|
||||
.join('&');
|
||||
}
|
||||
|
||||
async _syncTime() {
|
||||
this._timeOffset = await this.getTimeOffset();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user