Im trying to sign a BlockCypher transaction on the bitcoin testnet using bitcoinjs as described here but I keep getting the error:
{"error": "Couldn't deserialize request: invalid character 'x' in literal true (expecting 'r')"}
I have searched around and can find no documentation on what the problem is. Below is the code im using to try and sign the transaction.
var bitcoin = require("bitcoinjs-lib");
var buffer = require('buffer');
var keys = new bitcoin.ECPair.fromWIF('cMvPQZiG5mLARSjxbBwMxKwzhTHaxgpTsXB6ymx7SGAeYUqF8HAT', bitcoin.networks.testnet);
const publicKey = keys.publicKey;
console.log(keys.publicKey.toString("hex"));
var newtx = {
inputs: [{addresses: ['ms9ySK54aEC2ykDviet9jo4GZE6GxEZMzf']}],
outputs: [{addresses: ['msWccFYm5PPCn6TNPbNEnprA4hydPGadBN'], value: 1000}]
};
// calling the new endpoint, same as above
$.post('https://api.blockcypher.com/v1/btc/test3/txs/new', JSON.stringify(newtx))
.then(function(tmptx) {
// signing each of the hex-encoded string required to finalize the transaction
tmptx.pubkeys = [];
tmptx.signatures = tmptx.tosign.map(function(tosign, n) {
tmptx.pubkeys.push(keys.publicKey.toString("hex"));
return keys.sign(new buffer.Buffer(tosign, "hex")).toString("hex");
});
// sending back the transaction with all the signatures to broadcast
$.post('https://api.blockcypher.com/v1/btc/test3/txs/send', tmptx).then(function(finaltx) {
console.log(finaltx);
}).catch(function (response) {
console.log(response.responseText);
});
}).catch(function (response) {
console.log(response.responseText);
});
It seems this line return keys.sign(new buffer.Buffer(tosign, "hex")).toString("hex"); is the problem but im not sure on what is wrong.
This question was discussed and answered here. This post and this one are to be looked into in particular.
As far as I understand, according to the issue respective one was opened at BlockCypher repo. Although its status is still opened till this date, current BlockCypher JS docs respective API description contains altered version of the line
return keys.sign(new buffer.Buffer(tosign, "hex")).toString("hex");
with toDER() conversion prior to toString(), consequently it looks like this now
return keys.sign(new buffer.Buffer(tosign, "hex")).toDER().toString("hex");
Related
The Problem:
I have been unable to use Firebase (Google) Cloud Functions to collect and utilize device tokens for the cloud messaging feature.
Context:
I am a self-taught android-Java developer and have no JavaScript experience. Despite that, I believe I have code that should work and am not sure what the problem is. To my understanding, it could be one of three things:
Somehow my Firebase Realtime Database references are being called incorrectly and I am not retrieving data as expected.
I may need to use Promises to wait for all calls to be made before proceeding, however I don't really understand how I would incorporate that into the code I have.
I may be using multiple return statements incorrectly (which I am also fuzzy on).
My error message on the Firebase Realtime Database console is as follows:
#firebase/database: FIREBASE WARNING: Exception was thrown by user callback. Error: Registration token(s) provided to sendToDevice() must be a non-empty string or a non-empty array.
at FirebaseMessagingError.FirebaseError [as constructor] (/srv/node_modules/firebase-admin/lib/utils/error.js:42:28)
at FirebaseMessagingError.PrefixedFirebaseError [as constructor] (/srv/node_modules/firebase-admin/lib/utils/error.js:88:28)
at new FirebaseMessagingError (/srv/node_modules/firebase-admin/lib/utils/error.js:254:16)
at Messaging.validateRegistrationTokensType (/srv/node_modules/firebase-admin/lib/messaging/messaging.js:729:19)
at Messaging.sendToDevice (/srv/node_modules/firebase-admin/lib/messaging/messaging.js:328:14)
at admin.database.ref.once.snapshot (/srv/index.js:84:12)
at onceCallback (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:4933:51)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:4549:22
at exceptionGuard (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:698:9)
at EventList.raise (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:9684:17)
The above indicates I am not retrieving data either at all or by the time the return is called. My JavaScript function code is:
'use strict';
const admin = require('firebase-admin');
admin.initializeApp();
exports.pushNotification = functions.database.ref('/Chat Messages/{chatId}/{pushID}').onCreate((snapshot, context) => {
const valueObject = snapshot.after.val();
return admin.database().ref(`/Chat Basics/${valueObject.chatKey}/Chat Users`).once('value', statusSnapshot => {
var index = 0;
var totalkeys = statusSnapshot.numChildren();
var msgIDs = [];
statusSnapshot.forEach(msg=>{
msgIDs.push(msg.key.toString());
if(index === totalkeys - 1){
const payload = {
notification : {
title: valueObject.userName,
body: valueObject.message,
sound: "default"
}
}
sendNotificationPayload(valueObject.uid, payload);
}
index++;
});
});
});
function sendNotificationPayload(uid, payload){
admin.database()
.ref(`/User Token Data/${uid}`)
.once('value', snapshot=> {
var tokens = [];
//if(!snapshot.exists())return;
snapshot.forEach(item =>{
tokens.push(item.val())
});
admin.messaging()
.sendToDevice(tokens, payload)
.then(res => {
return console.log('Notification sent')
})
.catch(err => {
return console.log('Error in sending notification = '+err)
});
});
}
This code is mostly inspired by what was said to be a working example here from another Stack Overflow question here. I have successfully tested sending a notification to a single device by manually copying a device token into my function, so the function does run to completion. My Java code seems to be irrelevant to the problem, so I have not added it (please ask in the comments if you would like it added for further context).
What I Have Tried:
I have tried implementing promises into my code, but I don't think I was doing it properly. My main reference for this was here. I have also looked at the documentation for literally everything related to this topic, however my knowledge of JS is not sufficient to really apply barebones examples to my code.
My Firebase Realtime Database Nodes:
#1: Loop through chat members to collect user IDs:
"Chat Basics" : {
"1607801501690_TQY41wIfArhHDxEisyupZxwyHya2" : {
"Chat Users" : {
"JXrclZuu1aOwEpCe6KW8vSDea9h2" : true,
"TQY41wIfArhHDxEisyupZxwyHya2" : true
},
#2: Collect user tokens from collected IDs (ignore that tokens are matching):
"User Token Data" : {
"JXrclZuu1aOwEpCe6KW8vSDea9h2" : "duDR3KH3i3I:APA91bH_LCeslZlqL8akYw-LrM9Dv__nx4nU1TquCS0j6bGF1tlIARcheREuNdX1FheC92eelatBC8LO4t6gt8liRdFHV-NDuNLa13oHYxKgl3JBPPlrMo5rB5XhH7viTo4vfYOMftRi",
"TQY41wIfArhHDxEisyupZxwyHya2" : "duDR3KH3i3I:APA91bH_LCeslZlqL8akYw-LrM9Dv__nx4nU1TquCS0j6bGF1tlIARcheREuNdX1FheC92eelatBC8LO4t6gt8liRdFHV-NDuNLa13oHYxKgl3JBPPlrMo5rB5XhH7viTo4vfYOMftRi"
}
Conclusion:
Concrete examples would be much appreciated, especially since I am crunching right now. Thanks for your time and help!
Update:
After some more testing, it looks like the problem is definitely due to my lack of understanding of promises in two areas. Firstly, only one user is collected before the final return is called. Secondly, the final return is called before the 2nd forEach() loop can store snapshot data to an array.
For this code then, how may I modify (or rebuild) it so that it collects all keys before proceeding to retrieve token data from all keys - ultimately before returning the notification?
Just as with every question I post, I managed to figure out how to do it (tentatively) a few hours later. Below is a full example of how to send a notification to chat users based on a message sent (although it does not yet exclude the sender) to a given chat. The order of operations are as such:
User message is saved and triggers event. Relevant data the message contains are:
username, chat key, message
These are retrieved, with (username + message) as the (title + body) of the
notification respectively, and the chat key is used for user id reference.
Loop through chat user keys + collect.
Loop through array of chat user keys to collect array of device tokens.
Send notification when complete.
The code:
//Use firebase functions:log to see log
exports.pushNotification = functions.database.ref('/Chat Messages/{chatId}/{pushId}').onWrite((change, context) => {
const valueObject = change.after.val();
return admin.database().ref(`/Chat Basics/${valueObject.chatKey}/Chat Users`).once('value', statusSnapshot => {
var index = 0;
var totalkeys = statusSnapshot.numChildren();
var msgIDs = [];
statusSnapshot.forEach(msg=>{
msgIDs.push(msg.key.toString());
if(index === totalkeys - 1){
const payload = {
notification : {
title: valueObject.userName,
body: valueObject.message,
sound: "default"
}
}
let promises = [];
var tokens = [];
for(let i=0; i < msgIDs.length; i++){
let userId = msgIDs[i];
let promise = admin.database().ref(`/User Token Data/${userId}`).once('value', snapshot=> {
tokens.push(snapshot.val());
})
promises.push(promise);
}
return Promise.all(promises).then(() => {
return admin.messaging().sendToDevice(tokens, payload);
});
}
index++;
return false;
});
});
});
User profiles on GitHub display the number of contributions a user has made in the past year:
I'd like to display this information on my website, preferably without having to introduce any kind of backend. I've looked for it in several places. Nothing is listed in /users/(me)/. Short of scraping the page source, is there a way to retrieve this information? I don't see anything documented...
Have you seen the GithubAPI? Using it, you could run the request from your js file, without implemeting any backend.
For your purpose, I think you could use the following request https://api.github.com/users/yourUserName/events. That gives you as result, a list of events related to youUserName.
e.g
[
{
"id": "xxxxxxx",
"type": "PushEvent",
"actor": {.......},
"repo": {......},
"payload": {.......},
"public": true,
"created_at": "2016-11-17T21:33:15Z"
},
.....
]
You should go through the list and filter the type = PushEvent and created_at = lastYear.
I hope this can help you!
Update: that service is just giving the results for the last 3 months, so other possibility is to check (users/username/repos) and after that check the commits over them (repos/username/repoName/commits)
I've settled for parsing the HTML of my profile page using PHP. I begin by downloading the HTML for my profile page:
$githubProfile = file_get_contents('https://github.com/controversial');
next I find the position of the phrase contributions in the last year on the page. The whitespace is strange between contributions and in the last year so I'm using a regex to match any amount of space.
$contributionsIndex = preg_match(
'/contributions\s+in the last year/',
$githubProfile,
$matches,
PREG_OFFSET_CAPTURE
);
$index = $matches[0][1];
Finally, I iterate backwards from this point until I come across a character that is neither a number or a comma in the number. Once this condition becomes false, I know I've found the beginning of the number:
$endIndex = $index;
while (is_numeric($githubProfile[$index-2]) || $githubProfile[$index-2] == ',')
$index--;
$contributionsCount = substr($githubProfile, $index-1, $endIndex-$index);
Finally, I echo the number out (without commas)
echo(str_replace(',', '', $contributionsCount));
Finally, I use an AJAX call from my JavaScript page to get the value from the PHP script.
function get(url, callback) {
/* eslint-disable no-console */
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = e => (callback || console.log)(e.target.responseText);
xhr.onerror = () => console.log('error');
xhr.send();
/* eslint-enable no-console */
}
// Fill in GitHub contributions count
get('contributions-count.php', (resp) => {
document.getElementById('gh-contributions-count').innerText = resp;
});
I'm sure this will be accomplishable more cleanly in the future with GitHub's GraphQL API, but that's still in preview stages.
It's also possible to parse the svg calendar data with a xml parser and then sum all data-count entries. To avoid CORS issue, you can use a proxy like urlreq living on http://urlreq.appspot.com/req :
const user = 'controversial';
fetch('https://urlreq.appspot.com/req?method=GET&url=https://github.com/users/' + user + '/contributions')
.then(function(response) {
return response.text();
})
.then(function(text) {
xmlDoc = new DOMParser().parseFromString(text, 'text/xml');
var nodes = xmlDoc.getElementsByTagName('rect');
var count = 0;
for (var i = 0; i < nodes.length; i++) {
count += parseInt(nodes[i].getAttribute('data-count'));
}
console.log('contributions count : ' + count);
})
.catch(function(error) {
console.log('Request failed', error)
});
Another example using the command line with curl & xmlstarlet can be found here
The ultimate goal is to detect changes between an existing Parse object and the incoming update using the beforeSave function in Cloud Code.
From the Cloud Code log available through parse.com, one can see the input to beforeSave contains a field called original and another one called update.
Cloud Code log:
Input: {"original": { ... }, "update":{...}
I wonder if, and how, we can access the original field in order to detect changing fields before saving.
Note that I've already tried several approaches for solving this without success:
using (object).changedAttributes()
using (object).previousAttributes()
fetching the existing object, before updating it with the new data
Note on request.object.changedAttributes():
returns false when using in beforeSave and afterSave -- see below for more details:
Log for before_save -- summarised for readability:
Input: { original: {units: '10'}, update: {units: '11'} }
Result: Update changed to { units: '11' }
[timestamp] false <--- console.log(request.object.changedAttributes())
Log for corresponding after_save:
[timestamp] false <--- console.log(request.object.changedAttributes())
There is a problem with changedAttributes(). It seems to answer false all the time -- or at least in beforeSave, where it would reasonably be needed. (See here, as well as other similar posts)
Here's a general purpose work-around to do what changedAttributes ought to do.
// use underscore for _.map() since its great to have underscore anyway
// or use JS map if you prefer...
var _ = require('underscore');
function changesOn(object, klass) {
var query = new Parse.Query(klass);
return query.get(object.id).then(function(savedObject) {
return _.map(object.dirtyKeys(), function(key) {
return { oldValue: savedObject.get(key), newValue: object.get(key) }
});
});
}
// my mre beforeSave looks like this
Parse.Cloud.beforeSave("Dummy", function(request, response) {
var object = request.object;
var changedAttributes = object.changedAttributes();
console.log("changed attributes = " + JSON.stringify(changedAttributes)); // null indeed!
changesOn(object, "Dummy").then(function(changes) {
console.log("DIY changed attributes = " + JSON.stringify(changes));
response.success();
}, function(error) {
response.error(error);
});
});
When I change someAttribute (a number column on a Dummy instance) from 32 to 1222 via client code or data browser, the log shows this:
I2015-06-30T20:22:39.886Z]changed attributes = false
I2015-06-30T20:22:39.988Z]DIY changed attributes =
[{"oldValue":32,"newValue":1222}]
I am currently using LDAP JS for Authentication in Angular JS app and everything works perfectly fine.
I am now building a new view and the requirement I have is this:
I have text box in which admin will write may be a few letters of a user id present in LDAP.
I want to show app matching ID present in LDAP on a typeahead/suggestions. I know how typeahead works so that's not an issue. The issue is how can I pass a rejex or pattern matching kind of a thing for uid in search() method.
My sample code is here:
function GetAllLDAPUser(dnFilter, res) {
client.search('uid=**WHAT-PATTERN-CAN-I-PASS-HERE**' + dnFilter, opts, function(err, result) {
result.on('searchEntry', function(entry) {
// I usually read entry.object or entry.raw here , that works
});
result.on('end', function(result) {
.......
});
}
}
}
So the question is what should I pass in place of
WHAT-PATTERN-CAN-I-PASS-HERE
Results :
Suppose I type an. The typeahead will show all user id starting with an like ana, anamon, analisa etc.
I have written the final solution and closed the issue on the project's repository
For pattern matching, we need to play with the 'filter' field in option object which we pass to the search method. So I ended up doing something like below:
var dnFilter = 'ou=People,o=Intra,dc=YOURCOMPANY,dc=com'; //depends on your LDAP settings.
var query;
var matchedUsers = [];
query.LDAPName = "dummy"; //some name which resides in LDAP
//You can even have one simple variable rather than having this query object.
opts = {
scope: 'sub',
filter: (shcDisplayName = '+ query.LDAPName + ')
'
};
//Do not use 'shcDisplayName' , this will be any variable stored in your LDAP object. You need get
//the structure of LDAP end point you are working on. For me, I had one variable 'shcDisplayName'
//on which I wanted to play so I am using this variable in my filter.
client.search(dnFilter, opts, function(err, result) {
result.on('searchEntry', function(entry) {
matchedUsers.push({
'Name': entry.object.shcDisplayName,
'Id': entry.object.uid
});
}
result.on('end', function(result) {
if (matchedUsers.length) { //if any match was found.
//send the json result back
res.json(matchedUsers);
//if you want to send json back, do not use res.send() otherwise you will end up getting
//circular reference error.
}
}
result.on('error', function(ex) {
//Handle errors here if any
});
});
}
}
I want to update a field within the User class without being logged in as a user. From reading online and other responses people say I should use the 'masterkey' to do so. Here is my cloud code where I have added in the master key. The code is executed but when I go to my data browser the totalScore and predictions values are still the same and not updated to the new values.
Parse.initialize("key", "key");
Parse.Cloud.define("userUpdate", function(request, response) {
Parse.Cloud.useMasterKey();
var publicReadACL = new Parse.ACL();
publicReadACL.setPublicWriteAccess(true);
request.object.setACL(publicReadACL);
var User = Parse.Object.extend("User");
var query = new Parse.Query(User);
query.equalTo("username", request.params.username);
query.find({
success: function(user) {
user.set("totalScore", request.params.totalS);
user.set("totalPredictions", request.params.totalG);
user.save()
},
error: function() {
response.error("f");
}
});
});
Any help would be massively appreciated.
Hopefully you've figured this out by now, but if you haven't...I would first say check to make sure that you're passing the "totalScore" and "totalPredictions" as numbers. If you pass them as strings and Parse is expecting a Number, it won't update. And generally, I believe it's best practice to query the user class as follows:
var query = new Parse.Query(Parse.User);
query.get(user.objectId, {
success: function(userAgain) {
userAgain.set("totalScore", totalScore);
userAgain.save(null, {
error: function(userAgain, error) {
// This will error, since the Parse.User is not authenticated
}
});
}
});
Then of course you'd still need to include the master key stuff etc...