Binance TIMESTAMP ERROR (Timestamp for this request is outside of the recvWindow. M 1) - unix-timestamp

I'm using binance broker api, when executing my code.
I got this error :
data: {
code: -1021,enter code here
msg: 'Timestamp for this request is outside of the recvWindow.'
}
Then I have used binance server timestamp and get another error :
data: { code: -1022, msg: 'Signature for this request is not valid.' }
----- My sample code -------
'use strict'
//Modules
const crypto = require('crypto');
const axios = require('axios');
const moment = require('moment');
const keys = require('./config/keys');
//Keys
const apiKey = keys.keys.apiKey;
async function api_call(config){
var response = {}
try {
response = await axios(config);
response = {
error: false,
data : response.data
}
} catch (error) {
response = {
error: true,
data : error
}
}
return response;
}
async function get_binance_server_time(recvWindow=50000){
var timestamp = moment().unix();
var serverTime = 0;
var config = {
method: 'get',
url: `https://api.binance.com/api/v3/time`,
headers: {
'Content-Type': 'application/json',
'X-MBX-APIKEY': apiKey
}
};
var response = await api_call(config);
if(response.error){
response.data = {
serverTime : serverTime
}
}
serverTime = response.data.serverTime
console.log(timestamp);
console.log(response.data.serverTime);
if (timestamp < (serverTime + 1000) && (serverTime - timestamp) <= recvWindow) {
console.log("process");
} else {
console.log("Rejected");
}
return serverTime;
}
async function get_broker_account_information( _signature = null){
// Make the api call here
var serverTime = await get_binance_server_time();
var _timestamp = serverTime;
const query_string = `timestamp=${_timestamp}`;
const recvWindow = 50000
const signature = crypto.createHmac('sha256', apiKey).update(query_string).digest('hex')
var config = {
method: 'get',
url: `https://api.binance.com/sapi/v1/broker/info?timestamp=${_timestamp}&signature=${signature}&recvWindow=${recvWindow}`,
headers: {
'Content-Type': 'application/json',
'X-MBX-APIKEY': apiKey
}
};
var response = await api_call(config)
console.log(response.data);
return response;
}
// create_sub_account()
get_broker_account_information()
// get_binance_server_time()

Binance requires Unix timestamp in Milliseconds.
So you should change
var timestamp = moment().unix();
to
var timestamp = moment().unix()*1000;
Some time sync issues can be resolved by using an offset of about 15 seconds:
const offset = 15000;
var timestamp = moment().unix()*1000 - offset; // works flawlessly in my case
Also try using
const recvWindow = 60000 // maximum allowed
Important:
Your signature has to be generated from secret key, not api key. You need both, api key in header, secret key in signature calculation.
To gerenate a valid signature, all query parameters must be in the queryString, which you use to generate the signature.
Make a parameters object and convert it to a queryString:
var params = {
'timestamp': _timeStamp,
'recvWindow: 60000,
// other query parameters
};
var queryString = Object.keys(params).map(key => key + '=' + params[key]).join('&');
Then generate signature:
const signature = crypto.createHmac('sha256', apiSecret).update(queryString).digest('hex')

Just sync system time with network, is work for me.

Related

Why is Flutter Dart application throwing an XMLHttpRequest error when test programme and POSTMAN do not?

I have an application that was working doing http.get requests on an Ubuntu virtual machine hosting a postgres DB and an API using Hapi/node. The VM disk become corrpupted and following the rebuild, the http.get now throws an XMLHttpRequest error. However, a test programme doing the same request works fine and a test GET using POSTMAN works fine as well. I'm stumped as to why this is the case.
The code that is throwing the error is as follows (the getScores() function):
import 'package:noxo/functions.dart' as func;
import 'dart:convert';
import 'package:http/http.dart' as http;
class DataManager {
Map<dynamic, dynamic> results = {}; // Return values from DB parameter query
double difficulty = 5; // Level of difficulty (1- easiest to 5-hardest)
// Address of API for data requests
final _apiAddress = 'http://192.168.1.201:4044/';
bool _httpAvailable = true; // Assume that http is available
int getHumanScore() {
func.debugPrint('httpAvailable is $_httpAvailable');
if (_httpAvailable && results.isNotEmpty) {
func.debugPrint('Returning HUMAN score');
return results['humanwin'];
} else {
return 0;
}
}
int getDrawScore() {
if (_httpAvailable && results.isNotEmpty) {
return results['draws'];
} else {
return 0;
}
}
int getComputerScore() {
if (_httpAvailable && results.isNotEmpty) {
return results['computerwin'];
} else {
return 0;
}
}
void setDifficulty(double value) {
func.debugPrint('Set difficulty = $value');
difficulty = value;
}
double getDifficulty() {
func.debugPrint('Get difficulty is $difficulty');
return difficulty;
}
void getScores(Function() updateScores) async {
if (_httpAvailable) {
// If we haven't had a previous http error - read the scores
try {
dynamic _parsedAddress = Uri.parse(_apiAddress);
final response = await http.get(_parsedAddress);
func.debugPrint(
'doing getScores. Address = $_apiAddress. statusCode = ${response.statusCode}');
Map decodedResponse = jsonDecode(response.body) as Map;
if (response.statusCode == 200) {
func.debugPrint('getScores response: $decodedResponse');
results = decodedResponse;
updateScores(); // Update scores on main.dart
} else {
throw Exception('Unable to fetch products from the REST API');
}
} catch (e) {
func.debugPrint('getScores. Error is $e.');
_httpAvailable = false; // Disable http checks because we had an error
results =
{}; // Return an empty map if the internet connection is not available
}
}
}
// Put data about scores into the database
Future<void> putScores(String resultPath) async {
// Only try to put the scores if http is available
if (_httpAvailable) {
try {
String address = '$_apiAddress$resultPath';
func.debugPrint('http address: $address');
var response = await http.post(Uri.parse(address));
func.debugPrint('http response: ${response.body.toString()}');
// Check for sucess, throw an error if it didn't work
if (response.statusCode == 200 ||
response.statusCode == 201 ||
response.statusCode == 204) {
return;
} else {
throw Exception(
'Unable to update results from the REST API. Status Code: ' +
response.statusCode.toString());
}
} catch (e) {
_httpAvailable = false; // Disable http requests
}
}
}
}
The output when "getScores()" is called is:
getScores. Error is XMLHttpRequest error..
The Hapi interface code is as follows:
'use strict';
const Hapi = require('#hapi/hapi');
const { options } = require('#hapi/hapi/lib/cors');
const Inert = require('#hapi/inert');
const HapiPostgresConnection = require('hapi-postgres-connection');
const path = require('path');
const debug = true;
const init = async () => {
const server = Hapi.server({
port: 4044,
host: '192.168.1.201',
//host: '0.0.0.0',
routes: {
cors: false
/*
{
origin: ['192.168.*'], // an array of origins or 'ignore'
headers: ['Authorization'], // an array of strings - 'Access-Control-Allow-Headers'
exposedHeaders: ['Accept'], // an array of exposed headers - 'Access-Control-Expose-Headers',
additionalExposedHeaders: ['Accept'], // an array of additional exposed headers
maxAge: 60,
credentials: false // boolean - 'Access-Control-Allow-Credentials'
*/
}
});
await server.register([{
plugin: HapiPostgresConnection
},
{
plugin: Inert
}]);
server.route({
method: 'GET',
path: '/',
handler: async function (request, h) {
let id = '1';
let statement = `SELECT * FROM scores WHERE id = ${id}`;
debugPrint(`Doing GET. Statement = ${statement}`);
try {
const result = await request.pg.client.query(statement);
debugPrint(`After GET. Result = ${result}. Response = ${h.response()}`);
return h.response(result.rows[0]);
} catch (err) {
console.log(err);
}
}
});
server.route({
method: 'GET',
path: '/noxo',
handler: (request, h) => {
return h.file('/home/mike/programming/noxo/index.html');
}
});
server.route({
method: 'GET',
path: '/fwebtest',
handler: (request, h) => {
return h.file('index.html', options [{confine: false}]);
},
options: {
files: {
relativeTo: path.join(__dirname, 'fwebtest')
},
},
});
server.route({
method: 'GET',
path: '/webtest',
handler: (request, h) => {
return h.file('./webtest/index.html', options [{confine: false}])
}
});
server.route({
method: ['PUT', 'POST'],
path: '/',
handler: async function (request, h) {
let statement = 'update scores set';
var jsonData = request.payload;
if (jsonData.hasOwnProperty('id')) {
delete jsonData.id;
}
var first = true
for (var key of Object.keys(jsonData)) {
if (!first) {
statement = statement + ",";
}
statement = statement + ' ' + key + ' = ' + jsonData[key];
first = false;
}
statement = statement + ' where id = 1'
debugPrint(`Doing PUT. Statement = ${statement}`);
try {
const result = await request.pg.client.query(statement);
return h.response(result.rows[0]);
} catch (err) {
console.log(err);
}
}
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
function buildStatement(element, index, array) {
if (index != 'id') {
statement = statement + index + ' = ' + value + ' ';
}
return this;
}
function debugPrint(value){
if (debug == true){
console.log(value);
}
}
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();
The test dart programme, which works, is as follows:
import 'dart:convert';
import 'package:http/http.dart' as http;
// Address of API for data requests
final _apiAddress = 'http://192.168.1.201:4044/';
// Global variables
bool _httpAvailable = true; // Has http conect worked? Assume yes.
const bool debug = true; // Global bebug print variable.
void main() async {
// Get the scores from the API
Map scores = await _getScores();
}
// Function to get the scores using http command
Future<Map> _getScores() async {
debugPrint('Doing GET...');
dynamic response;
Map decodedResponse = {};
try {
dynamic _parsedAddress = Uri.parse(_apiAddress);
response = await http.get(_parsedAddress);
decodedResponse = jsonDecode(response.body) as Map;
} catch (e) {
debugPrint('getScores. Error is $e.');
_httpAvailable = false; // Disable http checks because we had an error
decodedResponse =
{}; // Return an empty map if the internet connection is not available
}
if (response.statusCode == 200) {
debugPrint('response.body:');
debugPrint(response.body);
debugPrint('GET successful... code: ' + response.statusCode.toString());
debugPrint(' ');
return decodedResponse;
} else {
throw Exception('Unable to fetch products from the REST API. Error code: ' +
response.statusCode.toString());
}
}
debugPrint(String message) {
if (debug == true) {
print(message);
}
}
The output from this programme is:
D:\Sync\Programming\Flutter\http_get>dart run
Building package executable...
Built http_test:http_test.
Doing GET...
response.body:
{"id":1,"humanwin":3,"draws":0,"computerwin":0}
GET successful... code: 200
The POSTMAN results are:
I assume that this is a CORS issue from what I have read about XMLHttpRequest errors, but believe I have disabled CORS in the Hapi interface. The application class, test programme and POSTMAN test all pre-date the Ubuntu VM rebuild so the only thing that has changed is the VM. The Hapi code was backed up so that shouldn't have changed either, although I can't quite remember when I took the last backup.
Does anyone have any ideas about why the test programme and POSTMAN work, but my DataManager class in my application doesn't?
In the routes definition for Hapi, cors needs to be set to true as below.
const server = Hapi.server({
port: xxxx,
host: 'xxx.xxx.xxx.xxx',
routes: {
cors: true
}
});

Axios sending url with params as string not object

i need to take url with params example:
https://domain.pl/ptpdf-gen?selected_posts=4871&advisor=magda,wojciech
But axios response is an object like:
{"https://domain.pl/ptpdf-gen?selected_posts":"4871","advisor":"magda,wojciech"}
How to send url as string via axios?
Optionally the request above could also be done as
axios.get('/user', {
params: {
selected_posts: 4871
advisor: ["magda", "Wojciech"]
},
paramsSerializer: params => {
return qs.stringify(params)
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
The qs is an external library,
https://www.npmjs.com/package/qs
var selected = 4871
var advisor = ["magda","wojciech"]
axios.post('https://domain.pl/ptpdf-gen', {selected, advisor })
So i made the url split like this, using URLSearchParams:
const currHref = window.location.search;
const urlParams = new URLSearchParams(window.location.search);
const myParam = urlParams.get('selected_posts');
const myParam2 = urlParams.get('advisor');
Then with axios.post i can send params:
axios.post("http://domain.pl/create", {myParam, myParam2})
On server i did handle params like:
const state = req.body;
const stateValues = Object.values(state);
And then i can concat url with stateValues[0] and stateValues[1];
let linkUrl = "https://domain.pl/ptpdf-gen?selected_posts=" + stateValues[0] + "&advisor=" + stateValues[1];
Works.

How to insert file to a shared drive using REST on Apps Script?

Is there a way that we can upload files to shared drive using POST Method? I don't know how to call the Drive ID of the shared drive and target it to the URL fetch function, is this possible?
This is my code:
var DriveScope = 'https://www.googleapis.com/auth/drive';
var ServiceAccountPrivateKey ="-----BEGIN PRIVATE KEY----"
var ServiceAccountEmail = "drive-uploads#xxxxxxx.com";
function testinRest(){
var service = getDriveService();
var driveID = "XXXXXXXX";
var APIKey = "XXXXXXXXXXXXX";
var resumeBlob = Utilities.newBlob('Hire me!', 'text/plain', 'resume.txt');
var formData = {
'name': 'Bob Smith',
'email': 'bob#example.com',
'resume': resumeBlob
};
var url = 'https://www.googleapis.com/drive/v3/drives';
var output = UrlFetchApp.fetch(url, {
method: 'get',
headers: { 'Authorization': 'Bearer ' + service.getAccessToken() },
contentType: 'application/json'
}).getContentText();
var response= JSON.parse(output);
for(var i=0; i < response.drives.length; i++){
if(driveID == response.drives[i].id){
service.reset()
if (service.hasAccess()) {
var newPresentationName = "RJ POGI";
var url = 'https://www.googleapis.com/upload/drive/v3/files?supportsAllDrives=true&key=' + APIKey;
var body = {
"name": newPresentationName,
"parents": [driveID]
};
var params = {
headers: {
Authorization: 'Bearer ' + service.getAccessToken(),
Referer:'https://explorer.apis.google.com'
},
method: 'post',
payload: formData,//JSON.stringify(body),
contentType: 'application/json',
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(url, params).getContentText();
Logger.log('response: ' + response);
var id = JSON.parse(response).id;
return id;
}
}
}
}
function getDriveService(){
var service = OAuth2.createService('drive').setTokenUrl('https://accounts.google.com/o/oauth2/token').setPrivateKey(ServiceAccountPrivateKey).setClientId(ServiceAccountEmail).setPropertyStore(PropertiesService.getUserProperties()).setScope(DriveScope);
//console.log("Service::" + service);
//console.log('Service Has Access::' + service.hasAccess());
if (!service.hasAccess()) {
Logger.log('Authentication error: %s', service.getLastError());
return;
}else{
return service;
}
}
function reset() {
var service = getDriveService();
service.reset();
}
On this example, I want the resumeBlob to be inserted on the targeted DriveID. Any help will be appreciated. Thanks!
Your problem needs to be divided in three steps:
Create a file on the drive with UrlFetchApp
Pass a content to the file
Insert the file into a shared drive
Now, you original question - 3. is easy to solve, you just need to specify in your requestsupportsTeamDrives=true.
More difficult is the combination of 1. and 2..
The Files: create method offers either an URI for media upload only requests, or for metadata-only.
The workaround would be to perform a resumable Upload, which allows you to post the metadata first, and add the file contents later.
The URI you need to use would be "https://www.googleapis.com/upload/drive/v3/files?supportsTeamDrives=true&uploadType=resumable".
Sample:
function uploadToSharedDrive(){
var url = "https://www.googleapis.com/upload/drive/v3/files?supportsTeamDrives=true&uploadType=resumable";
var resumeBlob = Utilities.newBlob('Hire me!');
var formData = {
'name': 'Bob Smith',
'mimeType': 'text/plain',
'parents': [
"ID of the shared drive"
]
};
params = {
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
},
contentType: 'application/json',
method: 'post',
payload: JSON.stringify(formData),
}
var response = UrlFetchApp.fetch(url, params);
Logger.log(response.getContentText());
data = resumeBlob.getBytes();
var params2 = {
method: "put",
payload: data,
muteHttpExceptions: true,
};
var location = response.getHeaders().Location;
var response = UrlFetchApp.fetch(location, params2);
Logger.log(response.getContentText())
}

Passport-jwt issue : JWT token is working with postman but not working with UI api call

I have integrated passport-jwt for authentication purpose. It's working like charm but whenever Frontend guy use it from frontend angular 2 its giving Unauthorised 401 . I've tried alot but not getting any clue, it must be a silly mistake though.
my passport strategy file is as
let JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
//let fromHeader = require('passport-jwt').fromHeader
// load up the user model
const User = require('../components/user/model');
const database = require('./database'); // get db config file
const config = require('./config'); // get db config file
module.exports = function(passport) {
//var passportStrategy = function(passport){
let opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
//opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme("JWT");
console.log("opts.jwtFromRequest==",opts.jwtFromRequest);
opts.secretOrKey = config.secret;//config.secret;
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
//console.log("opt==",JSON.stringify(opt));
//console.log("jwt_payload===",jwt_payload);
User.findOne({_id: jwt_payload._doc._id}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
done(null, user);
} else {
done(null, false);
}
});
}));
};
my route is as
app.get("/api/user/getAll",
passport.authenticate('jwt',{session:false}),
userController.fetchUsers
);
And frontend header append is as follows :
logoutUser(token) {
//const userData = JSON.stringify(userInfo);
var headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', token); //e.g.token = JWT dasddddasdsda
//headers.append('Authentication', token);
console.log(headers)
return this.http.post('http://localhost:9000/api/user/logout', { headers: headers })
.map((response: Response) =〉 {
return response.json()
})
.catch(this.errorHandler);
}
It would really great if anyone can assist me further to identify the mistake.
Second argument for the post method is payload.
so this code below
this.http.post('http://localhost:9000/api/user/logout', { headers: headers })
has to be
this.http.post('http://localhost:9000/api/user/logout', {}, { headers: headers })

How to translate superagent to axios?

I have some upload working for superagent. It involves posting to an api for cloudinary. My question is how do I do the same thing with axios. I'm not sure what superagent.attach and superagent.field relate to in axios.
Basically when I make the post request I need to attach all these fields to the request or else I get bad request and I want to do this in axios not superagent as I am switching over to axios.
Here are all the params:
const image = files[0];
const cloudName = 'tbaustin';
const url = `https://api.cloudinary.com/v1_1/${cloudName}/image/upload`;
const timestamp = Date.now()/1000;
const uploadPreset = 'cnh7rzwp';
const paramsStr = `timestamp=${timestamp}&upload_preset=${uploadPreset}ORor-6scjYwQGpNBvMW2HGMkc8k`;
const signature = sha1(paramsStr);
const params = {
'api_key': '177287448318217',
'timestamp': timestamp,
'upload_preset': uploadPreset,
'signature': signature
}
Here is the superagent post request:
let uploadRequest = superagent.post(url)
uploadRequest.attach('file', image);
Object.keys(params).forEach((key) => {
uploadRequest.field(key, params[key]);
});
uploadRequest.end((err, res) => {
if(err) {
alert(err);
return
}
You would need to use FromData as follows:
var url = `https://api.cloudinary.com/v1_1/${cloudName}/upload`;
var fd = new FormData();
fd.append("upload_preset", unsignedUploadPreset);
fd.append("tags", "browser_upload"); // Optional - add tag for image admin in Cloudinary
fd.append("signature", signature);
fd.append("file", file);
const config = {
headers: { "X-Requested-With": "XMLHttpRequest" },
onUploadProgress: function(progressEvent) {
// Do something with the native progress event
}
};
axios.post(url, fd, config)
.then(function (res) {
// File uploaded successfully
console.log(res.data);
})
.catch(function (err) {
console.error('err', err);
});
See full example here