Promisify all submethods on a node module - node.js

I'm trying to Promisify the stripe module but running into an issue.
If I run:
const stripe = Promise.promisifyAll(require('stripe')(secretKey));
const response = await stripe.accounts.retrieveAsync();
retrieveAsync isn't a function. I have to do something like this:
const accounts = Promise.promisifyAll(stripe.accounts);
const response = await accounts.retrieveAsync();
But obviously this doesn't scale well. How can I promisify all of the submethods of this module? Thanks

This seems to work:
let stripe = require('stripe')(secretKey);
Promise.promisifyAll(Object.getPrototypeOf(stripe));

Give a shot to it :
const stripe = Promise.promisifyAll(require('stripe')(secretKey));
const response = yield stripe.accounts.retrieve().promise();

It looks like that stripe v4.25 supports Promises, if you omit the callback.
With callback:
var stripe = require('stripe')('sk_test_XXX')
stripe.plans.retrieve('number_one_month', (err, res) => console.log(res))
{ id: 'number_one_month',
...
And with then():
stripe.plans.retrieve('number_one_month').then(console.log)
{ id: 'number_one_month',
...
But I didn't find it in the documentation.

Related

How to get cryptocurrency's price in EUR Node.js?

As a example in coinbase-api I can get cryptocurrency's price this way:
const eth_eur = await publicClient.getProductOrderBook('ETH-EUR', { level: 1 });
As you can see, I need pair cryptocurrency - eur, and that's important. So, how can I do it using binance api?
I was trying to use something like this:
const price = await binance.futuresFundingRate("ETHUSDT");
But this is not what I need. I need price in euro.
You can use the "Current average price" endpoint (docs) for base currencies that have pair against EUR.
Example:
const axios = require('axios');
axios.get('https://api.binance.com/api/v3/avgPrice?symbol=BTCEUR').then(response => {
const body = response.data;
console.log(body.price);
});
You can get the exchange rate easily with superface npm package
Example
npm install #superfaceai/one-sdk
npx #superfaceai/cli install crypto/exchange-rate
const { SuperfaceClient } = require("#superfaceai/one-sdk");
const sdk = new SuperfaceClient();
async function run() {
// Load the installed profile
const profile = await sdk.getProfile("crypto/exchange-rate");
// Use the profile
const result = await profile.getUseCase("GetExchangeRate").perform({
from: "ETH",
to: "EUR",
});
console.log(result.unwrap());
}
run();

UnhandledPromiseRejectionWarning: Error: `receipt` is mandatory razorpay

I'm following this documentation to create an order and they have clearly stated that the receipt is an optional parameter then why I'm getting
UnhandledPromiseRejectionWarning: Error: `receipt` is mandatory razorpay
here is the error
this is the code
const createOrder = async (req, res) => {
const amount = parseInt(req.body.amount) * 100;
const currency = req.body.currency;
var options = {
amount,
currency,
};
const instance = await razorpay.orders.create(options);
if (instance) {
const order_id = instance.id;
const transaction = new Transactions({ order_id, user_id,details:instance });
transaction.save();
res.status(200).json(instance);
}
};
This was a bug in the razorpay library that was fixed over a year ago.
Make sure you are using the latest version of the package. If the fix wasn't published, you could try using this commit directly:
npm i razorpay/razorpay-node#80044a4d1f54cdee6e8f5b81ddbcccba5812c175
If this doesn't work either, you could open an issue with the library on GitHub.

What to do when a node.js API function has no async version?

I am trying to create a secure random token
const crypto = require("crypto");
const { promisify } = require("util");
exports.createRandomToken = async () => {
const randomBytes = promisify(crypto.randomBytes);
const secretToken = await randomBytes(
parseInt(process.env.RANDOMBYTES_BYTES_NUMBER)
);
const secretTokenHex = secretToken.toString("hex"); //sync
return secretTokenHex;
};
Although crypto.randomBytes() has an async version,
buffer.toString() has not.
What could I do in this situation in order not to block the event loop (a must follow practice as express.js documentation says?

nodejs async/await nested API progress

I have an API that searches for the user-provided term, returns an array of results, then fires off async requests for each of the results and gets results for each of these second batch of requests. I'd like the API to report progress as it happens rather than just the final result. So, if I do the following request, I should get updates like so
$ curl 'http://server/?q=foobar'
searching for ${q}…
found 76… now getting images…
found 30 images… done
{
result
}
Most of relevant code is shown below. Fwiw, I am using hapijs for my application.
let imagesOfRecords = {};
const getImages = async function (q) {
console.log(`searching for ${q}…`);
const uri = `http://remoteserver/?q=${q}`;
const {res, payload} = await Wreck.get(uri);
const result = JSON.parse(payload.toString()).hits;
const numOfFoundRecords = result.total;
if (result.total) {
console.log(`found ${result.total}… now getting images…`);
const foundRecords = result.hits.map(getBuckets);
Promise.all(foundRecords).then(function() {
console.log(`found ${Object.keys(imagesOfRecords).length} images… done`);
reply(imagesOfRecords).headers = res.headers;
}).catch(error => {
console.log(error)
});
}
else {
console.log('nothing found');
reply(0).headers = res.headers;
}
};
const getBuckets = async function(record) {
const { res, payload } = await Wreck.get(record.links.self);
const bucket = JSON.parse(payload.toString()).links.bucket;
await getImageFiles(bucket, record.links.self);
};
const getImageFiles = async function(uri, record) {
const { res, payload } = await Wreck.get(uri);
const contents = JSON.parse(payload.toString()).contents;
imagesOfRecords[record] = contents.map(function(el) {
return el.links.self;
});
};
Once I can implement this, my next task would be to implement this progressive update in a web app that uses the above API.
To show result with each step of your requests for backend you can use EventEmitter, which will emit event on each progress step. You can read about events here.
Simple implementation:
const events = require('events');
const eventEmitter = new events.EventEmitter();
//your request code
Promise.all(foundRecords).then(function() {
console.log(`found ${Object.keys(imagesOfRecords).length} images… done`);
eventEmitter.emit('progress');
reply(imagesOfRecords).headers = res.headers;
})
const eventReaction = (e) => {
// do something with event, console log for example.
}
eventEmitter.on('progress', eventReaction);
More examples you can find here and here.
To show events to client you can use library socket.io. I think you can find pretty straightforward explanations how socket.io works in documentation.
If you want to send events between servers or processes and want to go little further, you can read more about 0MQ (zero mq) and it's node implementation

how to use firebase https trigger functions

I'm creating a token generator using firebase cloud functions and I wanted to use an https trigger to create the token, however I need to include data within the call to the url. I know it is possible but I don't necessarily know how to do it.
I need this so I can set values for certain variables in my function.
So the final url might look something like this in pseudo code:
https://tokengen/identity=/room=
here, identity and room are the two values I want to include for the variales for when calling the function.
so to reiterate,
I know you can request data using:
exports.token = functions.https.onRequest((request, response) => {
but how do I include data along with the https call to include as variables. An example would be greatly appreciated. As would any answers, suggestions, or references.
EDIT:
here's the updated code,
exports.tokenGenerator = functions.https.onRequest((request, response) => {
const { identity, roomName } = request.query;
const AccessToken = require('twilio').jwt.AccessToken;
const VideoGrant = AccessToken.VideoGrant;
const twilioAccountSid = '1xxxxxxxxxx';
const twilioApiKey = '1xxxxxxxxxx';
const twilioApiSecret = '1xxxxxxxxxx';
function generateToken(identity, roomName) {
const videoGrant = new VideoGrant({
room: roomName
});
const token = new AccessToken(twilioAccountSid, twilioApiKey, twilioApiSecret);
token.addGrant(videoGrant);
token.identity = identity;
return token.toJwt();
}
response.send(token.toJwt());
});
when I use the url it returns Error: could not handle the request
You can do something like this -
https://yourFB.cloudfunctions.net/token?identity=12&room=12
and you can use it like -
exports.token = functions.https.onRequest((request, response) => {
const { identity, room } = request.query;
...
});
Hope this helps.

Resources