Authenticated Commands With MtGox's Streaming API - node.js

I am using nodejs with socket.io-client to connect to the MtGox Streaming API described here: https://en.bitcoin.it/wiki/MtGox/API/Streaming#Authenticated_commands
The examples are written in php and I tried my best to convert them to JS but I keep getting a response from the server "Invalid call"
var sec_key_buffer = Buffer(secret_key, 'base64');
var hmac = crypto.createHmac('sha512', sec_key_buffer);
var nonce = Date.now() + "";
var id = crypto.createHash('md5').update(nonce).digest('hex');
var query = {
"call": 'private/info',
"id": id,
"nonce": nonce
};
var body = JSON.stringify(query);
var sign = hmac.update(body).digest('binary');
// The 'api_key' field has already stripped of the '-' character
var callBody = new Buffer(api_key + sign + body).toString('base64');
// 'connection' is the socket.io connection to 'https://socketio.mtgox.com/mtgox'
connection.json.send({
"op": "call",
"id": id,
"call": callBody,
"context": 'mtgox.com'
});
Any help would be appreciated.

Here's what seemed to work for me:
var io = require('socket.io-client');
var crypto = require('crypto');
var socket = io.connect('https://socketio.mtgox.com/mtgox');
var MTGOX_API_INFO = {
key: '<YOUR_KEY>',
secret: '<YOUR_SECRET>'
}
var MTGOX_CHANNELS = {
trade: 'dbf1dee9-4f2e-4a08-8cb7-748919a71b21',
depth: '24e67e0d-1cad-4cc0-9e7a-f8523ef460fe',
ticker: 'd5f06780-30a8-4a48-a2f8-7ed181b4a13f'
}
// unsubscribe from depth and trade messages
socket.emit('message', {
op: 'unsubscribe',
channel: MTGOX_CHANNELS.trade
});
socket.emit('message', {
op: 'unsubscribe',
channel: MTGOX_CHANNELS.depth
});
socket.emit('message', {
op: 'unsubscribe',
channel: MTGOX_CHANNELS.ticker
});
var getNonce = function() {
return ((new Date()).getTime() * 1000).toString();
}
var nonce = getNonce();
var requestId = crypto.createHash('md5').update(nonce).digest('hex');
var query = {
id: requestId,
call: 'private/info',
nonce: nonce
// params: {},
// item: 'BTC',
// currency: 'USD'
};
var queryJSON = JSON.stringify(query);
var signedQuery = crypto.createHmac('sha512', new Buffer(MTGOX_API_INFO.secret, 'base64')).update(queryJSON).digest('binary');
var binKey = (new Buffer(MTGOX_API_INFO.key.replace(/-/g, ''), 'hex')).toString('binary');
var buffer = new Buffer(binKey + signedQuery + queryJSON, 'binary');
var call = buffer.toString('base64');
var command = {
op: 'call',
id: requestId,
call: call,
context: 'mtgox.com'
};
console.log("REQUEST:", command);
socket.emit('message', command);
socket.on('message', function(data) {
console.log(data);
});
UPDATE: I've also abstracted it into a simple node module.

You must hex decode the api key to raw bytes before appending the hash and message content.
Not familiar enough with node.js to provide code, but in Java (using Guava) it's:
byte[] apiKey = BaseEncoding.base16().lowerCase().decode(API_KEY.replace("-", ""));

Related

Unable to deploy NFT in terminal

I already deployed my smart contract to my wallet and connected it to my Alchemy account.
Here are my codings (Note that my contract address, PUBLIC_KEY, PRIVATE_KEY, API_URL and alchemy address are edited for security purposes).
mint-nft.js
require('dotenv').config();
const API_URL = process.env.API_URL;
const PUBLIC_KEY = process.env.PUBLIC_KEY;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const { createAlchemyWeb3 } = require("#alch/alchemy-web3");
const web3 = createAlchemyWeb3(API_URL);
const contract = require("../artifacts/contracts/MyNFT.sol/MyNFT.json");
const contractAddress = "My_Contract_Adress";
const nftContract = new web3.eth.Contract(contract.abi, contractAddress);
async function mintNFT(tokenURI) {
const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, 'latest'); //get latest nonce
//the transaction
const tx = {
'from': PUBLIC_KEY,
'to': contractAddress,
'nonce': nonce,
'gas': 500000,
'data': nftContract.methods.mintNFT(PUBLIC_KEY, tokenURI).encodeABI()
};
const signPromise = web3.eth.accounts.signTransaction(tx, PRIVATE_KEY);
signPromise.then((signedTx) => {
web3.eth.sendSignedTransaction(signedTx.rawTransaction, function(err, hash) {
if (!err) {
console.log("The hash of your transaction is: ", hash, "\nCheck Alchemy's Mempool to view the status of your transaction!");
} else {
console.log("Something went wrong when submitting your transaction:", err)
}
});
}).catch((err) => {
console.log(" Promise failed:", err);
});
}
mintNFT("https://gateway.pinata.cloud/ipfs/My_NFT_Picture_Hash");
alchemyContext.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeAlchemyContext = void 0;
var tslib_1 = require("tslib");
var sturdy_websocket_1 = tslib_1.__importDefault(require("sturdy-websocket"));
var websocket_1 = require("websocket");
var jsonRpc_1 = require("../util/jsonRpc");
var version_1 = require("../version");
var alchemySendHttp_1 = require("./alchemySendHttp");
var alchemySendWebSocket_1 = require("./alchemySendWebSocket");
var httpProvider_1 = require("./httpProvider");
var sendPayload_1 = require("./sendPayload");
var webSocketProvider_1 = require("./webSocketProvider");
var NODE_MAX_WS_FRAME_SIZE = 100 * 1024 * 1024; // 100 MB
function makeAlchemyContext(url, config) {
var makePayload = jsonRpc_1.makePayloadFactory();
if (/^https?:\/\//.test(url)) {
var alchemySend = alchemySendHttp_1.makeHttpSender(url);
var _a = sendPayload_1.makePayloadSender(alchemySend, config), sendPayload = _a.sendPayload, setWriteProvider = _a.setWriteProvider;
var senders = jsonRpc_1.makeSenders(sendPayload, makePayload);
var provider = httpProvider_1.makeAlchemyHttpProvider(sendPayload);
return { provider: provider, senders: senders, setWriteProvider: setWriteProvider };
}
else if (/^wss?:\/\//.test(url)) {
var protocol = isAlchemyUrl(url) ? "alchemy-web3-" + version_1.VERSION : undefined;
var ws = new sturdy_websocket_1.default(url, protocol, {
wsConstructor: getWebSocketConstructor(),
});
var alchemySend = alchemySendWebSocket_1.makeWebSocketSender(ws);
var _b = sendPayload_1.makePayloadSender(alchemySend, config), sendPayload = _b.sendPayload, setWriteProvider = _b.setWriteProvider;
var senders = jsonRpc_1.makeSenders(sendPayload, makePayload);
var provider = new webSocketProvider_1.AlchemyWebSocketProvider(ws, sendPayload, senders);
return { provider: provider, senders: senders, setWriteProvider: setWriteProvider };
}
else {
throw new Error("Alchemy URL protocol must be one of http, https, ws, or wss. Recieved: " + url);
}
}
exports.makeAlchemyContext = makeAlchemyContext;
function getWebSocketConstructor() {
return isNodeEnvironment()
? function (url, protocols) {
return new websocket_1.w3cwebsocket(url, protocols, undefined, undefined, undefined, {
maxReceivedMessageSize: NODE_MAX_WS_FRAME_SIZE,
maxReceivedFrameSize: NODE_MAX_WS_FRAME_SIZE,
});
}
: WebSocket;
}
function isNodeEnvironment() {
return (typeof process !== "undefined" &&
process != null &&
process.versions != null &&
process.versions.node != null);
}
function isAlchemyUrl(url) {
return url.indexOf("alchemyapi.io") >= 0;
}
.env
API_URL = "https://eth-rinkeby.alchemyapi.io/v2/KEY"
PRIVATE_KEY = "MY_PRIVATE_KEY"
PUBLIC_KEY = "MY_PUBLIC_KEY"
But then I was trying to deploy my NFT with metadata and nft-mint.js, I got these error.
Can anyone please tell me what was the error about?
Your issue may be with dotenv not reading in the values in your .env.
If you add console.log(API_URL), is it correct or is it undefined?
If it is undefined, I was able to resolve the issue by adding the path to my .env like so:
require('dotenv').config({path:"../.env"});
(In my case my mint-nft.js was in scripts/mint-nft.js
and .env is in the root directory.)

Implement Redis in Node.js Bot Service

Bot Info
App ID: 776ba3b4-38e5-4582-809d-7c8d773cfe9b
SDK Platform: Node.js
SDK Version:
Active Channels: Direct Line
Deployment Environment: Auzure Bot Service
Issue Description
I Need Help implementing Redis to save Bot State. I'm working in a project that is really a requirement that we reduce as much latency as possibe. Right know we are using DocumentDB but since Redis works with memory this could be faster.
I've followed the tutorial using mongo DB, Microsoft Bot framework MongoDB as middle layer to store conversational states, data and context and I'm editing the file /lib/IStorageClient.js to connect, save and retrieve from redis.
Code Example
This is my implementation of the /lib/IStorageClient.js, instead of using MongoDB connection I've put Redis connection
"use strict";
var Consts = require('./Consts');
var redis = require('redis');
var IStorageClient = (function () {
function IStorageClient(options) {
this.options = options;
}
IStorageClient.prototype.initialize = function (callback) {
var _this = this;
var host = "MyRedis.redis.cache.windows.net";
var auth = "KEY";
var client = redis.createClient(6380,host , {auth_pass: auth, tls:
{servername: host}});
this.client = client;
callback(null);
};
IStorageClient.prototype.insertOrReplace = function (partitionKey, rowKey,
entity, isCompressed, callback) {
console.log("=========Insert IStorageClient===========")
var docDbEntity = { id: partitionKey + ',' + rowKey, data: entity,
isCompressed: isCompressed };
var host = "MyRedis.redis.cache.windows.net";
var auth = "KEY";
var client = redis.createClient(6380,host , {auth_pass: auth, tls:
{servername: host}});
client.set(partitionKey + ',' + rowKey, JSON.stringify(docDbEntity),
function(err, reply) {
console.log("=========SET===========");
console.log("ID: ",partitionKey + ',' + rowKey);
console.log("Result: ",docDbEntity);
});
};
IStorageClient.prototype.retrieve = function (partitionKey, rowKey,
callback) {
console.log("=========Retrieve IStorageClient===========")
var id = partitionKey + ',' + rowKey;
var host = "MyRedis.redis.cache.windows.net";
var auth = "KEY";
var client = redis.createClient(6380,host , {auth_pass: auth, tls:
{servername: host}});
//id
client.get(id, function(error, result){
console.log("=========Get===========");
console.log("Search: ",id);
console.log("Result: ",result);
if (error) {
console.log("Error:",error)
callback(error, null, null);
}
else if (result == null) {
callback(null, null, null);
}
else if (result.length == 0) {
callback(null, null, null);
}
else {
var finaldoc = JSON.parse(result);
callback(null, finaldoc, null);
}
});
};
IStorageClient.getError = function (error) {
if (!error)
return null;
return new Error('Error Code: ' + error.code + ' Error Body: ' +
error.body);
};
return IStorageClient;
}());
exports.IStorageClient = IStorageClient;
Reproduction Steps
Download Microsoft Bot framework MongoDB as middle layer to store conversational states, data and context
Replace /lib/IStorageClient.js with my implementation
Set a Redis account and key in the /lib/IStorageClient.js
Run in the bot emulator
Actual Results
I could see the json saving to Redis, also I could print the retrieve result in the console, but the thing is that the answer is not being received in the bot emulator.
You are looking for botbuilder-redis-storage middleware, available here:
GitHub - https://github.com/suttna/botbuilder-redis-storage
NPM - https://www.npmjs.com/package/botbuilder-redis-storage
Usage example:
var redis = require('redis')
var RedisStorage = require('botbuilder-redis-storage')
var builder = require('botbuilder')
// Initialize redis client
var redisClient = redis.createClient(process.env.REDIS_URL, { prefix: 'bot-storage:' });
// Create new storage with redis client
var storage = new RedisStorage(redisClient)
var connector = new builder.ChatConnector()
var bot = new builder.UniversalBot(connector)
// Configure bot to use the RedisStorage
bot.set('storage', storage)

Send message using telegram bot with Node.js

I'm doing a service to warn me of possible errors that can occur on my server , my doubt is , after I send a message as I finalize the execution or the way it is presenting the image below normal? For to complete the task I have to take a ctrl + c
code:
var util = require('util');
var TelegramBot = require('node-telegram-bot-api');
var token = '237907874:AAG8hK1lPWi1WRlqQT2';
var bot = new TelegramBot(token, {polling: true});
var millisecondsToWait = 5000;
robot = {
"alert": function teste(message) {
var toId = '-103822200';
var resp = util.format('alerta: %s', message);
bot.sendMessage(toId, resp);
}
}
robot.alert(process.argv[2]);
in cmd i execute this code
node.exe bot.js 'text send'
this is image
Looks like some error occurs but not captured:
var robot = { // Don't forget about var :)
"alert": function teste(message) {
var toId = '-103822200';
var resp = util.format('alerta: %s', message);
bot.sendMessage(toId, resp)
.catch(function(error){ // Catch possible error
console.error(error);
});
}
}

Payment gateway for using with nodejs that accepts INR

I'm looking for a payment gateway that supports INR, that I can use with a nodejs app. Can't find anything that works. Any suggestions and pointers would be helpful.
I think citruspay is a good choice. The following links show integrations with node js.
Merchant Hosted Checkout (Citrus.js)
var crypto = require('crypto');
function generateSignature(merchantTxnId, request) {
//Need to change with your Secret Key
var secret_key = "***SEcRETKey***";
//Need to change with your Access Key
var accesskey = "***Access Key***";
//Should be unique for every transaction
var txn_id = merchantTxnId;
//Need to change with your Order Amount
var amount = "1.00";
var data = 'merchantAccessKey=' + accesskey + '&transactionId=' + txn_id + '&amount=' + amount;
// generate hmac
var hmac = crypto.createHmac('sha1', secret_key);
hmac.update(data);
return hmac.digest('hex');
}
Now include this signature in PaymentObject
Then listen for post on the Return URL
You have to generate signature and compare with the signature sent in the post data from citrus to make sure data is not tampered in the way.
var http = require("http");
var qs = require('querystring');
var crypto = require('crypto');
var secret_key = "MERCHANT_SECRET_KEY";
http.createServer(function(request, response) {
var body = "";
if (request.method = "POST") {
request.on("data", function(data) { body += data; });
request.on("end", function() {
var post = qs.parse(body);
var data_string = post['TxId'] + post['TxStatus'] + post['amount']
+ post['pgTxnNo'] + post['issuerRefNo'] + post['authIdCode']
+ post['firstName'] + post['lastName'] + post['pgRespCode']
+ post['addressZip'];
var signature = crypto.createHmac('sha1',
secret_key).update(data_string).digest('hex');
if (signature == post['signature']) {
response.writeHead(200, {"Content-Type": "application/json"});
console.log(post);
response.write(JSON.stringify(post));
}
else {
response.writeHead(403, {"Content-Type": "application/json"});
var error = {error : 'Transaction Failed', message: 'Signature Verification Failed'};
response.write(JSON.stringify(error));
}
response.end();
});
}
}).listen(3000);

UCWA Lync authentication - 500 web ticket is invalid

I'm trying to create a simple client for Lync using Nodejs.
Base on http://ucwa.lync.com/documentation/KeyTasks-CreateApplication I've made someting like this.
It works until last step #9 when I should register my app with UCWA. Server responds with code 500 and silly explanation
There is a problem with the resource you are looking for, and it cannot be displayed
And headers
x-ms-diagnostics': '28032;source="mysource";reason="The web ticket is invalid."'
var http = require('request-promise');
var lync = {};
lync.setup = function(email, password){
var self = this;
var hostname = email.split('#');
this.username = email;
//discover urls
return http.get('http://lyncdiscover.'+hostname[1])
.then(function(d) {
var parsed = JSON.parse(d);
self.urls = {
self: parsed._links.self.href,
user: parsed._links.user.href,
xframe: parsed._links.xframe.href
};
return http.get(self.urls.user);
}).catch(function(err){
if(err.statusCode == 401){
var toParse = err.response.headers['www-authenticate'];
var Oauth = toParse.match(/https:\/\/[\d\w\./_-]*/i)[0];
var loginPost = {
grant_type: 'password',
username: email,
password: password
};
return http.post(Oauth, {form:loginPost});
}
return false
}).then(function(data){
var parsed = JSON.parse(data);
//setup authorization
http = http.defaults({
headers: {Authorization: parsed.token_type + ' ' + parsed.access_token}
});
//console.log(self.urls.user);
//console.log('Authorization:'+ parsed.token_type + ' ' + parsed.access_token);
return http.get(self.urls.user);
}).then(function(data){
var parsed = JSON.parse(data);
self.urls.applications = parsed._links.applications.href;
var registerApp = {
culture : "en-us",
endpointId : "2d9dc28d-4673-4035-825c-feb64be28e4e",
userAgent : "Test"
};
var r = "{'userAgent': 'NodeJs', 'endpointId' : '2d9dc28d-4673-4035-825c-feb64be28e4e', 'culture': 'en-US'}";
return http.post(self.urls.applications, {body: registerApp, json:true});
})
.then(function(data){
console.log(data);
})
.catch(function(err){
console.log(err);
return false;
});
};
//run app
lync.setup('login#domain.com', 'password').then(function(ret){
});
One key point here. It's not my server. I just have an account over there and I can login with official Lync client or Pidgin plugin.
Are there some extra steps to "allow" my app to work with UCWA?
#ShelbyZ
I can easily authorize using Oauth. I'm receiving authorization token so I'm logged in.
I'm receiving json similar to
"_links":{
"self":{"href":"link"},
"applications":{"href":"i need this"},
"xframe":{"href":"link"}
} }
Now. I need to "register my application" doing POST.
In this last step I get 500 code response.
I hope It's not related with that #Matthew Proctor said..
becouse I cannot simple administrate the server
Thank you #ShelbyZ
You were right, it was split-domain scenario. Now authorization works, and I can register my app. Also example for future generations
var http = require('request-promise');
var lync = {};
lync._authorize = function(){
var self = this;
var orgDomain = self.urls.user.match(/https:\/\/([\w\d\.]+)/i)[0];
//console.log(orgDomain);
http.get(self.urls.user).catch(function(err){
if(err.statusCode == 401){
var toParse = err.response.headers['www-authenticate'];
var Oauth = toParse.match(/https:\/\/[\d\w\./_-]+/i)[0];
var loginPost = {
grant_type: 'password',
username: self.username,
password: self.password
};
return http.post(Oauth, {form:loginPost});
}
}).then(function(data){
if(data) {
var parsed = JSON.parse(data);
//setup authorization
http = http.defaults({
headers: {Authorization: parsed.token_type + ' ' + parsed.access_token}
});
return http.get(self.urls.user);
}
}).then(function(data){
//check for split-domain scenario
var parsed = JSON.parse(data);
var domain = parsed._links.self.href.match(/https:\/\/([\w\d\.]+)/i)[0];
console.log('[1] '+orgDomain);
console.log('[2] '+domain);
if(domain!== orgDomain){
//split domain scenario
self.urls.user = self.urls.user.replace(orgDomain, domain);
http = http.defaults({
headers: {Authorization: null}
});
self._authorize();
} else { //create app
var parsed = JSON.parse(data);
self.urls.applications = parsed._links.applications.href;
var registerApp = {
culture : "en-us",
endpointId : "2d9dc28d-4673-4035-825c-feb64be28e4e",
userAgent : "NodeJs client"
};
return http.post(self.urls.applications, {body: registerApp, json:true});
}
}).then(function(app){
console.log(app);
});
};
lync.setup = function(email, password){
var self = this;
var hostname = email.split('#');
this.username = email;
this.password = password;
//discover urls
return http.get('http://lyncdiscover.'+hostname[1])
.then(function(d) {
var parsed = JSON.parse(d);
self.urls = {
self: parsed._links.self.href,
user: parsed._links.user.href,
xframe: parsed._links.xframe.href
};
return self._authorize();
});
};
//run app
lync.setup('username#domain.com', 'password');
I was getting the same error before I added my test domain to the list of Allowed Domains.
This can be updated via PowerShell, full details below:
Enabling UCWA and Configuring Allowed Domains
I've had clients see similar errors when running my code from http://localhost/, their fix was to test their code on a FQDN (ie http://testmyucwacode.mydomain.com/).

Resources