Node js reuse existing buff call - javascript

I use the following code which works as expected however I wonder if there is a way to improve is as Im doing New Buffer twice.
I need to encode two values now but more latter... , user and password.
I mean reduce boilerplate code
let secret = await getSecret("mt", "fe");
let adminBuff = new Buffer(secret.admin, 'base64');
let admin = adminBuff.toString('ascii');
let adminPass = new Buffer(secret.pass, 'base64');
let pass = adminPass.toString('ascii');

Use Buffer.from() since new Buffer is deprecated.
As for the reusability part, creating a function would be helpful. Something like the following:
function toAsciiString (value) {
const valueBuff = Buffer.from(value, 'base64');
return valueBuff.toString('ascii');
}
let secret = await getSecret("mt", "fe");
let admin = toAsciiString(secret.admin);
let pass = toAsciiString(secret.pass);
Hope this helps :)

You can iterate over the keys of the object "secret", process their values and create a new object containing the processing results.
For example:
let secret = await getSecret("mt", "fe");
const resultObj = {};
Object.keys(secret).forEach((key) => {
const newBuffer = new Buffer(secret[key], 'base64');
resultObj[key] = newBuffer.toString('ascii');
});

Related

Unable to remove data from json file on disk

I'm unable to find a way to remove whole line of JSON data(line) after it's used.
For some reason delete is not working or rather said not doing anything.
.JSON
[
{"id":"1","code":"super-S","expires_in":"","gives_currencies":"1.5","gives_items":"","number_of_attempts":"1","attempts_used":""},
{"id":"2","code":"wow!","expires_in":"","gives_currencies":"3","gives_items":"","number_of_attempts":"1","attempts_used":""},
{"id":"3","code":"slashme","expires_in":"","gives_currencies":"4","gives_items":"","number_of_attempts":"1","attempts_used":""},
{"id":"4","code":"randombla","expires_in":"","gives_currencies":"5","gives_items":"","number_of_attempts":"1","attempts_used":""}
]
code
//fs configuration
const fs = require('fs');
let rawdata = fs.readFileSync('test.json');
let mycodes = JSON.parse(rawdata);
//something above
const randomcode = mycodes[Math.floor(Math.random() * mycodes.length)];
console.log('Your code is:', randomcode['code']); //logs me a random code value
delete mycodes[randomcode];
The goal here is to select random code, which is done but then I need to remove it from .JSON file so it won't repeat. I tried several things but it's not working, delete.randomcode etc... the line never removed from the .JSON file.
Use Array.prototype.splice(index, deleteCount) instead of delete.
delete, on an Array, will just null the key, without removing it.
Save back your modified data using JSON.stringify(mycodes) to that same file.
const fs = require('fs');
const mycodes = JSON.parse(fs.readFileSync('./test.json'));
const randomIndex = Math.floor(Math.random() * mycodes.length);
const randomObject = mycodes[randomIndex];
console.log('Your code is:', randomObject.code); // Log a random code value
mycodes.splice(randomIndex, 1); // Remove one key at randomIndex
// Write back to file
fs.writeFileSync('test.json', JSON.stringify(mycodes, 0, 4), 'utf8');
If you already have that Object out of your Array, and since Objects are passed by reference (like pointer in memory), make use of the Array.prototype.indexOf(someObject) like:
const fs = require('fs');
const mycodes = JSON.parse(fs.readFileSync('./test.json'));
const randomIndex = Math.floor(Math.random() * mycodes.length);
const randomObject = mycodes[randomIndex];
// later in your code....
const objIndex = mycodes.indexOf(randomObject); // Get Object index in Array
mycodes.splice(objIndex, 1); // Remove it from array at that index
// Write back to file
fs.writeFileSync('test.json', JSON.stringify(mycodes, 0, 4), 'utf8');
You need to persist your data by writing it back to your JSON file after using JSON.stringify().
While you're at it, you can move your code into functions, which will make it easier to read and work with.
You might also want to read about editing arrays using Array.prototype.splice().
The delete operator is for deleting properties from objects. While you can use it to delete elements from an array, it will leave the index empty rather than closing the gap in the array after deletion.
const fs = require('fs');
// get a random element from any array
function getRandomElement (array) {
const randomElement = array[Math.floor(Math.random() * array.length)];
return randomElement;
}
function deleteElementFromArray (array, element) {
const index = array.indexOf(element);
if (index < 0) return false;
array.splice(index, 1);
return true;
}
// move the reading work inside a function
function readJson (filePath) {
const json = fs.readFileSync(filePath, {encoding: 'utf8'});
const data = JSON.parse(json);
return data;
}
// move the reading work inside a function
function writeJson (filePath, data) {
const json = JSON.stringify(data);
fs.writeFileSync(filePath, json);
}
const jsonFilePath = 'test.json';
const mycodes = readJson(jsonFilePath);
const randomcode = getRandomElement(mycodes);
console.log('Your code is:', randomcode['code']);
deleteElementFromArray(mycodes, randomcode);
writeJson(jsonFilePath, mycodes);

HDKeys Sign Verify

Trying to sign and verify a random string using private keys. I'm Using hdkeys and bip39 packages
Code:
const HDkey = require('hdkey')
const bip39 = require('bip39')
const mnemonic = bip39.generateMnemonic()
console.log('You recovery seed phrase: \n'+ mnemonic)
let genkey = HDkey.fromMasterSeed(Buffer.from(mnemonic, 'hex'))
let privKey = genkey.privateKey;
let pubKey = genkey.publicExtendedKey;
console.log()
console.log('Private Key: ' + privKey)
console.log()
console.log('Public Key: ' + pubKey)
const hash = "Adadadas"
genkey.sign(hash)
hdkey.verify(hash, sign)
But there comes an error:
if (!cond) throw new Error(msg)
^
Error: Expected message to be an Uint8Array
I'm new to this.
As the error message describes, the message to be signed should be a Uint8Array object with 256-bits (32-bytes) length. You need to hash your message.
const message = "Adadadas"
const hash = crypto.createHash('sha256');
hash.update(message);
const hashBuffer = hash.digest();
const hashUint8Array = new Uint8Array(hashBuffer);
const signature = genkey.sign(new Uint8Array(hashUint8Array))
const result = genkey.verify(hashUint8Array, signature)
console.log(result);
I had faced a similar issue while using hdkey. Function sign expects a Uint8Array(32) [or equivalent] as input. My intent was to validate sign/verify and so I was simply looking for an input that could be passed accordingly.
Here's what I got working eventually:
console.log('Attempting sign n verify...')
const txnObj = {
from: 'abc',
to: 'xyz'
}
console.log('txnObj:', txnObj);
const txnStr = JSON.stringify(txnObj);
console.log('txnStr:', txnStr);
const txnHash = sha256(txnStr);
console.log('txnHash:', txnHash);
const txnBuffer = Buffer.from(txnHash.toString(), 'hex');
console.log('txnBuffer:', txnBuffer);
const hashedUint8Array = new Uint8Array(txnBuffer);
console.log('hashUint8Array:', hashedUint8Array);
Here's the outcome:
Outcome of executing above code
Additionally, your signing prv and pub keys are not traceable in the provided code.
const hash = "Adadadas"
genkey.sign(hash)
hdkey.verify(hash, sign)
Suggest changing them as below ie. sign using your privKey and verify using your pubKey:
const hash = "Adadadas"
const signed = privKey.sign(hash)
pubKey.verify(hash, signed)

Query _id in mongodb

I'm trying to query a specific document and then delete that document.
I'm able to successfully query the document through this:
export async function findRecord(database, sub_db, query) {
let output = "";
const mongo = require('mongodb').MongoClient
const url = "mongodb+srv://...";
const client = await mongo.connect(url, {useNewUrlParser: true,useUnifiedTopology: true});
const db = client.db(database)
const collection = db.collection(sub_db)
const items = await collection.find(query).toArray();
client.close()
return items;
}
But when I console.log the data my _id is in an array. It looks like this: https://share.getcloudapp.com/rRun6j5J
Within the MongoDB docs I see to query like this: {"_id" : ObjectId("568c28fffc4be30d44d0398e")}, but because its printing an array I can't get it to look like that.
Frontend:
export async function button3_click(event) {
let query = {}
let output = await findRecord("domains","domains", query)
console.log(output)
let record_to_delete = output[0]._id
console.log(record_to_delete)
await deleteRecord("domains","domains",record_to_delete)
}
Backend:
export async function deleteRecord(database, sub_db, record_idobj) {
let output = "";
const mongo = require('mongodb').MongoClient
const url = "mongodb+srv://...";
const client = await mongo.connect(url, {useNewUrlParser: true,useUnifiedTopology: true});
const db = client.db(database)
const collection = db.collection(sub_db)
await collection.deleteOne({"_id": record_idobj})
client.close()
}
My end goal is to be able remove by _id...
Note: My frontend code might look weird because I'm in Wix Code, but everything else should be okay.
Please try to use use findOne instead of find.
collection.findOne({_id: _id})
As long as I understand, the answer to your question is given here.
You just need to make a String from your char array, which can be done easily with charArray.join(""); and then you create an ObjectId with ObjectId(string)

BCH transaction failed: Missing inputs 25

I am using Bitcoin Cash JS to create a transaction, and my code is as follows:
let BITBOXCli = require('bitbox-cli/lib/bitbox-cli').default;
const explorers = require('bitcore-explorers')
const insight = new explorers.Insight('https://test-bch-insight.bitpay.com')
let BITBOX = new BITBOXCli();
let txb = new BITBOX.TransactionBuilder('testnet');
var To = 'mkiuwbSQQVxMvvbBcYEKUdZgJfURhu3hrW'
var from = 'mvStb7hPtDCL8dmyifPGcYTuToVzf7ajTb';
var bch = require('bitcoincashjs')
var bchLib = require('#owstack/bch-lib')
const buf = new Buffer('b27ab45d3e3d157e8b95f800347974f9991cf13ceb814e1992f40c5e4e6d5253', 'hex')
const privateKey = new bch.PrivateKey(buf, bch.Networks.testnet)
const address = privateKey.toAddress('testnet')
insight.getUnspentUtxos(address.toString(), function (error, utxos) {
if (error) {
console.error(error)
return
}
console.log(utxos)
const utxo = {
txid: utxos[0].txid,
outputIndex: utxos[0].vout,
script: utxos[0].scriptPubKey,
satoshis: utxos[0].satoshis
}
const transaction = new bch.Transaction()
.from(utxo)
.to(To, 50000)
.sign(0, privateKey)
console.log(transaction.toString())
});
Now when I am running this code, I am able to get the raw transaction hash but I am not able to broadcast transaction and message is as follows:
Missing Inputs Error:-25
Any idea about this error?
Or is there any other way to create BCH transaction?
It looks like you're trying to create a simple transaction to send BCH from one address to another. There is now an example for this exact use case in the BITBOX SDK repository:
https://github.com/Bitcoin-com/bitbox-javascript-sdk/blob/master/examples/applications/wallet/send-bch/send-bch.js
There are also other examples there like creating a wallet checking a balance:
https://github.com/Bitcoin-com/bitbox-javascript-sdk/tree/master/examples/applications/wallet
There are even more examples in the Wormhole SDK. (Wormhole SDK is a superset of BITBOX, so it can do anything BITBOX can do):
https://github.com/Bitcoin-com/wormhole-sdk/tree/master/examples

Unable to add vector to FlatBuffer table (Javascript)

I am following the FlatBuffers Javascript tutorial but I am having trouble adding a vector of non-scalar items to the following object:
namespace test;
enum Availability : byte {
Unavailable = 0,
Available = 1
}
table Channel {
channelNumber:uint;
myState:Availability = Unavailable;
}
table ControlChannel {
channels:[Channel];
}
root_type ControlChannel;
As you can see the root object contains a vector of Channel objects. I successfully generated my javascript code, but while trying to create some test data it seems that the channels aren't added correctly. This is what I tried:
const fs = require('fs');
const flatbuffers = require('./flatbuffers').flatbuffers;
const test = require('./control-channel_generated').test;
// Create builder. The '1' is the 'initial size', whatever that means.
const builder = new flatbuffers.Builder(1);
// Create the first channel
test.Channel.startChannel(builder);
test.Channel.addChannelNumber(builder, 1);
const channel1 = test.Channel.endChannel(builder);
// Create another channel
test.Channel.startChannel(builder);
test.Channel.addChannelNumber(builder, 2);
test.Channel.addMyState(builder, test.Availability.Available);
const channel2 = test.Channel.endChannel(builder);
// Create a vector of the channels
const chans = [channel1, channel2];
const channels = test.ControlChannel.createChannelsVector(builder, chans);
// Create control channel and add the channels
test.ControlChannel.startControlChannel(builder);
test.ControlChannel.addChannels(builder, channels); // The resulting cc-test.data file is the same whether I comment this line or not
const controlChannel = test.ControlChannel.endControlChannel(builder);
// Control channel is finished
builder.finish(controlChannel);
// Create a buffer (to send it, write it etc)
const buf = builder.asUint8Array();
fs.writeFileSync('cc-test.data', buf);
console.log(`Data written to 'cc-test.data'.`);
This results in a file called cc-test.data which contains the buffer and no matter how many channels I try to add, the buffer is always exactly the same. I also tried parsing the data back like this:
const fs = require('fs');
const flatbuffers = require('./flatbuffers').flatbuffers;
const test = require('./control-channel_generated').test;
// Parse the data as a new byte array
const data = new Uint8Array(fs.readFileSync('./cc-test.data'));
const buf = new flatbuffers.ByteBuffer(data);
// This is where all the magic happens
const controlChannel = test.ControlChannel.getRootAsControlChannel(buf);
// You can not iterate over the channels directly, you have to get it by index
console.log(`ControlChannel has ${controlChannel.channelsLength()} channels:`);
for (var i = 0; i < controlChannel.channelsLength(); i++) {
const channel = controlChannel.channels(i);
console.log(`Channel ${channel.channelNumber()} (Available: ${channel.myState()})`);
}
This just prints ControlChannel has 0 channels every time. What am I missing?

Categories