Try to calculate 2 values from callback (Binance Api using JavaScript) - javascript

I have 2 different code to get data:
first is to get by balance account
the second is to get the current value of the coin
I need to calculate the number of coins that I can buy with the balance
(Balance*coin value = quantity)
I have tried many options to get the value outside of the function without luck.
first code: (get balance)
binance.balance((error, balances) => {
if ( error ) return console.error(error);
console.info("BTT balance: ", balances.BTT.available);
});
Second code (get coin value)
binance.prices('BTTUSDT',(error, ticker)=>{
console.info("Hello:: ", ticker.BTTUSDT);
});

Dive in callback hell:
binance.balance((error, balances) => {
if ( error ) return console.error(error);
console.info("BTT balance: ", balances.BTT.available);
binance.prices('BTTUSDT',(error, ticker)=>{
if ( error ) return console.error(error);
// Balance*coin
});
});
Or use Promises:
const getBalance = () => new Promise((resolve, reject) => {
binance.balance((error, balances) => {
if(error) {
reject(error);
return;
}
resolve(balances.BTT.available);
});
const getCoins = () => new Promise((resolve, reject) => {
binance.prices('BTTUSDT', (error, ticker) => {
if(error) {
reject(error);
return;
}
resolve(ticker.BTTUSDT);
});
(async () => {
const balance = await getBalance();
const coins = await getCoins();
console.info(balance * coins);
})();

Related

Getting PostgresSQL 42703 error (invalid column error)

I am working on a React project with PostgreSQL database, this is the first time I am using it, and I am getting 42703 error on querying a particular column.
Below is the code I have written to query
const getList = (userId) => {
return new Promise(function (resolve, reject) {
pool.query(`SELECT items FROM public."user" where id=${userId}`, (error, results) => {
if (error) {
reject(error)
}
resolve(results);
})
})
}
I have defined this getList function and then I am making an api call to call this function by passing the userId like this
app.get(`/expenses`, verifySession(), async (req, res) => {
const userId = req.session.userId;
database.getList(userId)
.then(response => {
res.status(200).send(response);
})
.catch(error => {
res.status(500).send(error);
})
})
I even tried passing the userId directly as shown below , still it gives me the same error , which probably means I am querying in a wrong way
app.get(`/expenses`, verifySession(), async (req, res) => {
//const userId = req.session.userId;
database.getList('17a6dea6-a63e-4da7-9910-df7eddb672e6')
.then(response => {
res.status(200).send(response);
})
.catch(error => {
res.status(500).send(error);
})
})
Only when I directly write the string in the query it works properly like this
const getList = (userId) => {
return new Promise(function (resolve, reject) {
pool.query(`SELECT items FROM public."user" where id='17a6dea6-a63e-4da7-9910-df7eddb672e6'`, (error, results) => {
if (error) {
reject(error)
}
resolve(results);
})
})
}
Can someone please help we with what is exactly going wrong and if my syntax is correct or not ?
This is the frontend part of where I am calling the api.
function getDataForUser() {
fetch(`http://localhost:3001/data`)
.then(response => {
return response.json();
}).then(data => {
console.log(data.rows[0]);
})
}
This problem happened because you didn't use a single quotation for string type in the query. When using where id=${userId} and called with 17a6dea6-a63e-4da7-9910-df7eddb672e6 converted to where id=17a6dea6-a63e-4da7-9910-df7eddb672e6 and this make problem.
You can use two scenarios to handle it:
Use the single quotation for string type:
const getList = (userId) => {
return new Promise(function (resolve, reject) {
pool.query(`SELECT items FROM public."user" where id='${userId}'`, (error, results) => {
if (error) {
reject(error)
}
resolve(results);
})
})
}
Use parameter binding (As default it converted type)
const getList = (userId) => {
return new Promise(function (resolve, reject) {
pool.query(`SELECT items FROM public."user" where id=$1`, [userId], (error, results) => {
if (error) {
reject(error)
}
resolve(results);
})
})
}

async function not getting result

I am trying to get the result of an async function in my calculateOrderAmount function but it returns undefined.
The console.log in the called function returns the good result, but inside calculateOrderAmount, I get undefined. Here is my code:
getMultiStrats = async () => {
await MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return err
}
if(!multiStrats) {
return console.log('MultiStrat not found')
}
console.log('returns MultiStrat: ' + multiStrats)
return multiStrats
})
.catch(err => console.log(err))
}
async function calculateOrderAmount(balance, ticker){
const multiState = await StrategyController.getMultiStrats().catch((err) => console.log(err))
console.log('multiState: ' + multiState)
some logic
}
Here is the console log:
multiState: undefined
returns MultiStrat: {
_id: 5ff73c74d1135b39fc709b80,
positionsCount: 1,
inTradeCount: 0,
__v: 0
}
What did I miss? Thanks you very much for your time!
The current approach is pretty unclear--there's no need for .catch, async, await all at once. return multiStrats returns from the inside of the callback, not from getMultiStrats. The async/await on getMultiStrats is superfluous, just adding another promise wrapper that doesn't accomplish anything.
Given that findOne as shown here uses a callback rather than a promise, you can either use callbacks all the way or you can promisify findOne as follows, using .then and .catch in the caller:
const MultiStrats = {
findOne: (obj, cb) => cb(null, "I'm a multistrat!")
};
const StrategyController = {
getMultiStrats: () => new Promise((resolve, reject) =>
MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return reject(err);
}
else if (multiStrats) {
return resolve(multiStrats);
}
reject(Error("Multistrat not found"));
})
)
};
const calculateOrderAmount = (balance, ticker) =>
StrategyController
.getMultiStrats()
.then(multiState => {
console.log('multiState: ' + multiState)
// some logic
})
.catch(err => console.error(err))
;
calculateOrderAmount();
Or use async/await and try/catch:
const MultiStrats = {
findOne: (obj, cb) => cb(null, "I'm a multistrat!")
};
const StrategyController = {
getMultiStrats: () => new Promise((resolve, reject) =>
MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return reject(err);
}
else if (multiStrats) {
return resolve(multiStrats);
}
reject(Error("Multistrat not found"));
})
)
};
const calculateOrderAmount = async (balance, ticker) => {
try {
const multiState = await StrategyController.getMultiStrats();
console.log('multiState: ' + multiState)
// some logic
}
catch (err) {
console.error(err);
}
};
calculateOrderAmount();
If this is MongoDB's findOne and already returns a promise, then you can just return the promise to the caller, optionally awaiting it and throwing for the null result:
const MultiStrats = {
findOne: async query => "I'm a multistrat!"
};
const StrategyController = {
getMultiStrats: async () => {
const result = await MultiStrats.findOne({});
if (result) {
return result;
}
throw Error("Multistrat not found");
}
};
const calculateOrderAmount = (balance, ticker) =>
StrategyController
.getMultiStrats()
.then(multiState => {
console.log('multiState: ' + multiState);
// some logic
})
.catch(err => console.error(err))
;
calculateOrderAmount();
You cannot return values from an inner callback and reach the outer function, I would suggest
1- only use promises
2- wrap your code with promise to be sure that await will return the async result the way you expect to have.
getMultiStrats = async () => {
return new Promise((resolve, reject) => {
MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return err
}
if (!multiStrats) {
console.log('MultiStrat not found')
reject('MultiStrat not found')
}
console.log('returns MultiStrat: ' + multiStrats)
resolve(multiStrats);
})
.catch(err => {
console.log(err);
reject(err)
})
})
}
async function calculateOrderAmount(balance, ticker) {
try {
const multiState = await StrategyController.getMultiStrats()
console.log('multiState: ' + multiState)
// some logic
} catch (error) {
console.error(error);
}
}
Assuming that you use mongoose. I suggest using the promise interface like described in the documentation.
const getMultiStrats = async () => {
const query = MultiStrats.findOne({});
let multiStrats;
try {
multiStrats = await query.exec();
} catch (error) {
return error;
}
if (multiStrats) {
console.log("returns MultiStrat: " + multiStrats);
} else {
console.log("MultiStrat not found");
}
return multiStrats;
}
I would personally not return the error, but instead just let the error be thrown. With the above code the caller of getMultiStrats has to figure out if there return value is the expected result or an error. If you don't catch the error, it is thrown further up to the caller.
const getMultiStrats = async () => {
const multiStrats = await MultiStrats.findOne({}).exec();
if (multiStrats) {
console.log("returns MultiStrat: " + multiStrats);
} else {
console.log("MultiStrat not found");
}
return multiStrats;
}
You can further simplify this if you where to leave the console.log of of the equation.
const getMultiStrats = () => MultiStrats.findOne({}).exec();

Un-nest JavaScript Firestore Functions

How can I rewrite this code to not be nested in itself? I also need access to the values obtained in the previous functions calls.
return docRef2.doc(`/users_stripe/${context.params.userID}`).get()
.then(snapshot => {
console.log("augu", snapshot);
return stripe.customers.createSource( jsonParser(snapshot._fieldsProto.id, "stringValue"),
{ source: jsonParser(snap._fieldsProto.token, "stringValue") },
function(err, card) {
console.log("listen people", card);
return docRef2.doc(`/users_stripe/${context.params.userID}/ptypes/ptypes`)
.set(card);
});
})
I am not sure what your code is doing here. I tried to write a pseudo/sample code that might give you an idea.
My code is not checked, so might contain problem.
let fun1 = () => {
return new Promise((resolve, reject) => {
docRef2.doc('/route').get().then(snapshot => {
if( snapshot ) resolve(snapshot);
else reject(snapshot);
})
})
}
let fun2 = (snapshot) => {
return new Promies((resolve, reject)=>{
stripe.customers.createSource(jsonParser(snapshot._fieldsProto.id, "stringValue"),
{ source: jsonParser(snap._fieldsProto.token, "stringValue") },
function (err, card) {
if (err) reject(false);// or whatever you wanna return
else resolve(card);
});
})
}
async function fun(){
let res1 = await fun1(); // Should contain snapshot
let res2 = await fun2(res1); // Should contain card
return docRef2.doc(`/users_stripe/${context.params.userID}/ptypes/ptypes`)
.set(card);
}

How to call a function after the other function is done?

My problem is that i coded a simple overstock function for my game-items trading site (site working with socket.io!). And when the site is loading, two functions getting user and site inventories with items and listing them into two boxes, but the user inv loads faster and info about overstock comes later as the bot inv is loaded. I need to execute the "get user inventory" function after the "get bot inventory" function is fully done. I tried to set a sleep function between them, but it worked only for the main function that loading whole functions. In other words sleep(2000) delays loading both inventories when it set between this two functions.
sorry for my bad english :-D
Aaand there is my code (i left only important part):
io.on('connection', (socket) => {
var userObject = false
if (
typeof socket.handshake.session.passport !== 'undefined' &&
typeof socket.handshake.session.passport.user !== 'undefined' &&
typeof socket.handshake.session.passport.user.id !== 'undefined'
) {
userObject = socket.handshake.session.passport.user
}
socket.emit('site', config.site)
socket.emit('user', userObject)
socket.on('get bot inv', (id) => {
Trade.getInventory(config.bots[id].steamID64, config.appID, config.contextID, (err, data) => {
socket.emit('bot inv', { error: err, items: data })
})
})
socket.on('get user inv', (steamID64) => {
Trade.getInventory(steamID64, config.appID, config.contextID, (err, data) => {
socket.emit('user inv', { error: err, items: data })
})
})
socket.on('get bots inv', () => {
const params = []
Object.keys(config.bots).forEach((index) => {
const bot = config.bots[index]
params.push({
id: index,
steamID64: bot.steamID64,
appID: config.appID,
contextID: config.contextID,
})
})
Trade.getInventories(params, (data) => {
socket.emit('bots inv', data)
socket.emit('bots floats', Trade.getFloatValues())
})
})
})
Look into promises.
var promise1 = new Promsie((resolve, reject) => {
socket.on('get bot inv', (id) => {
Trade.getInventory(config.bots[id].steamID64, config.appID, config.contextID, (err, data) => {
socket.emit('bot inv', { error: err, items: data })
resolve();
})
})
})
var promise2 = new Promsie((resolve, reject) => {
socket.on('get user inv', (steamID64) => {
Trade.getInventory(steamID64, config.appID, config.contextID, (err, data) => {
socket.emit('user inv', { error: err, items: data })
resolve();
})
})
})
If you want to wait until one finishes
promise1.then(() => {return promise2});
If you want N things to execute and await all of them, use the following
Promise.all([promise1, promise2]).then(() => {execute something else});
For further documentation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
You might want to use promises. At first, encapsulate the socket listeners and the API call with promises:
const getUserId = new Promise(res => socket.on('get bot inv', res));
const getBotId = new Promise(res => socket.on('get bot inv', res));
function getInventory(id) {
return new Promise((res, rej) => {
Trade.getInventory(id, config.appID, config.contextID, (err, data) => {
if(err) rej(err) else res(data);
});
}
Then its easy to chain the promises:
(async function() {
const userID = await getUserId;
const data = await getInventory(userID);
socket.emit({ data });
const botID = await getBotId;
const botData = await getInventory(config.bots[botID].steamID64);
socket.emit({ botData });
})();

How to do recursive requests to an API with promise in Node.js?

I need to read data from API that only gives 100 results per query and a timestamp from where to get the next 100.
I've managed to do multiple requests one after another with the code below, but for some reason it never returns to the original promise. It gets stuck on the "No more orders to fetch".
app.get('/test', (req, res) => {
const getOrders = (from) => {
return request(mcfApiUrl + "changes?created_after_ts="+from+"&key="+mcfKey)
.then(xml => convert.xmlDataToJSON(xml,{explicitArray:false,mergeAttrs:true}))
.then(orders => checkForMore(orders));
}
const checkForMore = (orders) => {
return new Promise((resolve, reject) => {
if (orders['Orders']['orders'] == 100){
getOrders(orders['Orders']['time_to']);
console.log("Fetched "+ orders['Orders']['orders']+" orders");
console.log("More orders available from: "+moment(orders['Orders']['time_to']*1000).format());
}
else {
console.log("Fetched "+ orders['Orders']['orders']+" orders");
console.log("No more orders to fetch");
resolve(orders);
}
});
};
var fromdate = 1483999200;
getOrders(fromdate)
.then(output => res.send("Done")) // It never gets here
.catch(err => console.log(err));
});
What am I missing?
Your issue is that you're not resolving the checkForMore promise for all options.
const checkForMore = (orders) => {
return new Promise((resolve, reject) => {
if (orders['Orders']['orders'] == 100){
getOrders(orders['Orders']['time_to']); // <-- not resolved
}
else {
resolve(orders);
}
});
};
Just wrapping the call to getOrders with resolve will fix that.
resolve(getOrders(orders['Orders']['time_to']))
However, you don't really need to create a new promise:
const checkForMore = (orders) =>
orders['Orders']['orders'] == 100
? getOrders(orders['Orders']['time_to'])
: Promise.resolve(orders);
In fact, your entire function can be shrunk into a few lines:
const getOrders = (from) =>
request(mcfApiUrl + "changes?created_after_ts="+from+"&key="+mcfKey)
.then(xml => convert.xmlDataToJSON(xml,{explicitArray:false,mergeAttrs:true}))
.then(orders =>
orders.Orders.orders == 100
? getOrders(orders.Orders.time_to)
: Promise.resolve(orders)
);
Now, if you want to accumulate all the orders, you need to maintain some state through the recursion levels.
You can do that either with a global state or an additional parameter:
const getOrders = (from, allOrders = []) =>
// ^ accumulation container
request(mcfApiUrl + "changes?created_after_ts="+from+"&key="+mcfKey)
.then(xml => convert.xmlDataToJSON(xml,{explicitArray:false,mergeAttrs:true}))
.then(orders => {
allOrders.push(orders); // <-- accumulate
return orders.Orders.orders == 100
? getOrders(orders.Orders.time_to, allOrders) // <-- pass through recursion
: Promise.resolve(allOrders)
});

Categories