move remaining code to typescript

This commit is contained in:
Iuri Matias 2018-12-01 17:36:29 -05:00
parent f1df122264
commit 8aaaabec1e
5 changed files with 147 additions and 194 deletions

76
poc.js
View File

@ -1,76 +0,0 @@
const Web3 = require('web3');
const { utils: { asciiToHex, hexToAscii, sha3 } } = Web3;
const POW_TIME = 1;
const TTL = 10;
const POW_TARGET = 0.002;
const CHANNEL_NAME ="mytest"
const CHANNEL = Web3.utils.sha3(CHANNEL_NAME).slice(0, 10);
function createStatusPayload() {
let tag = '~#c4';
let content = 'Hello everyone, it\s status js';
let messageType = '~:public-group-user-message';
let clockValue = (new Date().getTime()) * 100;
let contentType = 'text/plain';
let timestamp = new Date().getTime();
return asciiToHex(
JSON.stringify([
tag,
[
content,
contentType,
messageType,
clockValue,
timestamp,
],
]),
);
}
(async () => {
let web3 = new Web3();
web3.setProvider(new Web3.providers.WebsocketProvider('ws://localhost:8546', {headers: {Origin: "statusjs"}}));
await web3.shh.setMinPoW(POW_TARGET);
let keys = {};
// keys.symKeyID = await web3.shh.newSymKey();
// keys.sig = await web3.shh.newKeyPair();
keys.symKeyID = await web3.shh.generateSymKeyFromPassword(CHANNEL_NAME);
keys.sig = await web3.shh.newKeyPair();
console.dir("keys generated");
console.dir(keys);
subscription = web3.shh.subscribe("messages", {
minPow: POW_TARGET,
symKeyID: keys.symKeyID,
topics: [CHANNEL]
}).on('data', (data) => {
console.dir("message received!");
console.dir(data);
console.dir(JSON.parse(hexToAscii(data.payload)));
}).on('error', () => {
console.dir("error receiving message");
});
web3.shh.post({
symKeyID: keys.symKeyID, // encrypts using the sym key ID
sig: keys.sig, // signs the message using the keyPair ID
ttl: TTL,
topic: CHANNEL,
payload: createStatusPayload(),
powTime: POW_TIME,
powTarget: POW_TARGET
}).then(() => {
console.dir('message sent!');
}).catch((e) => {
console.dir("error sending message");
console.dir(e);
});
})()

View File

@ -1,30 +1,38 @@
const Web3 = require('web3');
import utils from './utils.js';
import mailservers from './mailservers.js';
const constants = require('./constants');
const Web3 = require("web3");
import utils from "./utils.js";
import mailservers from "./mailservers.js";
const constants = require("./constants");
const { utils: { asciiToHex, hexToAscii } } = Web3;
function createStatusPayload(content, messageType, clockValue, isJson) {
const tag = constants.messageTags.message;
const oneMonthInMs = 60 * 60 * 24 * 31 * 1000;
if(clockValue < (new Date().getTime())){
function createStatusPayload(content: string, messageType: string, clockValue: number, isJson = false) {
const tag: string = constants.messageTags.message;
const oneMonthInMs: number = 60 * 60 * 24 * 31 * 1000;
if (clockValue < (new Date().getTime())) {
clockValue = (new Date().getTime() + oneMonthInMs) * 100;
}
const contentType = (isJson ? 'content/json' : 'text/plain');
const contentType = (isJson ? "content/json" : "text/plain");
const timestamp = new Date().getTime();
return asciiToHex(
JSON.stringify([
tag,
[content, contentType, messageType, clockValue, timestamp, ["^ ","~:text", content]],
[content, contentType, messageType, clockValue, timestamp, ["^ ", "~:text", content]],
]),
);
}
const _sig = new WeakMap();
const sig = new WeakMap();
class StatusJS {
private channels: any;
private contacts: any;
private userMessagesSubscription: any;
private mailservers: any;
private isHttpProvider: boolean;
private shh: any;
private chatRequestCb: any;
constructor() {
this.channels = {};
@ -34,16 +42,16 @@ class StatusJS {
this.isHttpProvider = false;
}
async connect(url, privateKey) {
let web3 = new Web3();
if(url.startsWith("ws://")){
public async connect(url: string, privateKey?: string) {
const web3: any = new Web3();
if (url.startsWith("ws://")) {
web3.setProvider(new Web3.providers.WebsocketProvider(url, {headers: {Origin: "statusjs"}}));
} else if(url.startsWith("http://") || url.startsWith("https://")) {
} else if (url.startsWith("http://") || url.startsWith("https://")) {
// Deprecated but required for statusd
web3.setProvider(new Web3.providers.HttpProvider(url));
this.isHttpProvider = true;
} else {
const net = require('net');
const net = require("net");
web3.setProvider(new Web3.providers.IpcProvider(url, net));
}
@ -51,59 +59,63 @@ class StatusJS {
this.mailservers = new mailservers(web3);
await web3.shh.setMinPoW(constants.post.POW_TARGET);
_sig.set(
sig.set(
this,
privateKey ? await this.generateWhisperKeyFromWallet(privateKey) : await web3.shh.newKeyPair()
privateKey ? await this.generateWhisperKeyFromWallet(privateKey) : await web3.shh.newKeyPair(),
);
}
isConnected() {
public isConnected() {
return this.shh.isListening();
}
async generateWhisperKeyFromWallet(key){
await this.shh.addPrivateKey(key);
return;
private async generateWhisperKeyFromWallet(key: string) {
const keyId = await this.shh.addPrivateKey(key);
return keyId;
}
async getPublicKey(){
const pubKey = await this.shh.getPublicKey(_sig.get(this));
public async getPublicKey() {
const pubKey = await this.shh.getPublicKey(sig.get(this));
return pubKey;
}
async getUserName(pubKey){
if(!pubKey) {
public async getUserName(pubKey?: any) {
if (!pubKey) {
pubKey = await this.getPublicKey();
}
return utils.generateUsernameFromSeed(pubKey);
}
async joinChat(channelName, cb) {
let channelKey = await this.shh.generateSymKeyFromPassword(channelName);
public async joinChat(channelName: string, cb?: any) {
const channelKey = await this.shh.generateSymKeyFromPassword(channelName);
this.channels[channelName] = {
channelName,
channelCode: Web3.utils.sha3(channelName).slice(0, 10),
channelKey,
channelName,
lastClockValue: 0,
channelCode: Web3.utils.sha3(channelName).slice(0, 10)
};
if (cb) cb();
if (cb) {
cb();
}
}
async addContact(contactCode, cb) {
public async addContact(contactCode: string, cb?: any) {
this.contacts[contactCode] = {
lastClockValue: 0,
username: utils.generateUsernameFromSeed(contactCode),
lastClockValue: 0
};
if (cb) cb();
if (cb) {
cb();
}
}
leaveChat(channelName) {
if(!this.isHttpProvider) {
public leaveChat(channelName: string) {
if (!this.isHttpProvider) {
this.channels[channelName].subscription.unsubscribe();
} else {
// TODO: fix me
//web3.shh.deleteMessageFilter(this.channels[channelName].filterId)
// web3.shh.deleteMessageFilter(this.channels[channelName].filterId)
// .then(result => {
// clearInterval(this.channels[channelName].interval);
// });
@ -111,217 +123,233 @@ class StatusJS {
delete this.channels[channelName];
}
async removeContact(contactCode, _cb) {
public async removeContact(contactCode: string) {
delete this.contacts[contactCode];
}
isSubscribedTo(channelName) {
public isSubscribedTo(channelName: string) {
return !!this.channels[channelName];
}
onMessage(par1, par2) {
if(typeof par1 === "function"){
public onMessage(par1: any, par2: any) {
if (typeof par1 === "function") {
this.onUserMessage(par1);
} else {
this.onChannelMessage(par1, par2);
}
}
onChatRequest(cb){
public onChatRequest(cb: any) {
this.chatRequestCb = cb;
}
onChannelMessage(channelName, cb) {
public onChannelMessage(channelName: string, cb: any) {
if (!this.channels[channelName]) {
return cb("unknown channel: " + channelName);
}
const filters = {
allowP2P: true,
symKeyID: this.channels[channelName].channelKey,
topics: [this.channels[channelName].channelCode],
allowP2P: true
};
const messageHandler = (data) => {
let username = utils.generateUsernameFromSeed(data.sig);
const messageHandler = (data: any) => {
const username = utils.generateUsernameFromSeed(data.sig);
const payloadArray = JSON.parse(hexToAscii(data.payload));
if(this.channels[channelName].lastClockValue < payloadArray[1][3]){
if (this.channels[channelName].lastClockValue < payloadArray[1][3]) {
this.channels[channelName].lastClockValue = payloadArray[1][3];
}
cb(null, {payload: hexToAscii(data.payload), data: data, username: username});
cb(null, {payload: hexToAscii(data.payload), data, username});
};
if(this.isHttpProvider){
if (this.isHttpProvider) {
this.shh.newMessageFilter(filters)
.then(filterId => {
.then((filterId: any) => {
this.channels[channelName].filterId = filterId;
this.channels[channelName].interval = setInterval(() => {
this.shh.getFilterMessages(filterId)
.then(data => {
data.map(d => {
.then((data: any) => {
data.map((d: any) => {
messageHandler(d);
});
})
.catch((err) => { cb(err); });
.catch((err: any) => { cb(err); });
}, 250);
});
} else {
this.channels[channelName].subscription = this.shh.subscribe("messages", filters)
.on('data', messageHandler)
.on('error', (err) => { cb(err); });
.on("data", messageHandler)
.on("error", (err: any) => { cb(err); });
}
}
onUserMessage(cb) {
public onUserMessage(cb: any) {
const filters = {
allowP2P: true,
minPow: constants.post.POW_TARGET,
privateKeyID: _sig.get(this),
privateKeyID: sig.get(this),
topics: [constants.topics.CONTACT_DISCOVERY_TOPIC],
allowP2P: true
};
const messageHandler = (data) => {
if(!this.contacts[data.sig]){
const messageHandler = (data: any) => {
if (!this.contacts[data.sig]) {
this.addContact(data.sig);
}
const payloadArray = JSON.parse(hexToAscii(data.payload));
if(this.contacts[data.sig].lastClockValue < payloadArray[1][3]){
if (this.contacts[data.sig].lastClockValue < payloadArray[1][3]) {
this.contacts[data.sig].lastClockValue = payloadArray[1][3];
}
if(payloadArray[0] === constants.messageTags.message){
cb(null, {payload: hexToAscii(data.payload), data: data, username: this.contacts[data.sig].username});
} else if(payloadArray[0] === constants.messageTags.chatRequest) {
if (payloadArray[0] === constants.messageTags.message) {
cb(null, {payload: hexToAscii(data.payload), data, username: this.contacts[data.sig].username});
} else if (payloadArray[0] === constants.messageTags.chatRequest) {
this.contacts[data.sig].displayName = payloadArray[1][0];
this.contacts[data.sig].profilePic = payloadArray[1][1];
if(this.chatRequestCb){
if (this.chatRequestCb) {
this.chatRequestCb(null, {
'username': this.contacts[data.sig].username,
'displayName': this.contacts[data.sig].displayName,
'profilePic': this.contacts[data.sig].profilePic,
displayName: this.contacts[data.sig].displayName,
profilePic: this.contacts[data.sig].profilePic,
username: this.contacts[data.sig].username,
});
}
}
};
if(this.isHttpProvider){
if (this.isHttpProvider) {
this.shh.newMessageFilter(filters)
.then(filterId => {
.then((filterId: any) => {
this.userMessagesSubscription = {};
this.userMessagesSubscription.filterId = filterId;
this.userMessagesSubscription.interval = setInterval(() => {
this.shh.getFilterMessages(filterId)
.then(data => {
data.map(d => {
.then((data: any) => {
data.map((d: any) => {
messageHandler(d);
});
})
.catch((err) => { cb(err); });
.catch((err: any) => { cb(err); });
}, 250);
});
} else {
this.userMessagesSubscription = this.shh.subscribe("messages", filters)
.on('data', (data) => { messageHandler(data); })
.on('error', (err) => { cb(err); });
.on("data", (data: any) => { messageHandler(data); })
.on("error", (err: any) => { cb(err); });
}
}
sendUserMessage(contactCode, msg, cb) {
if(!this.contacts[contactCode]){
public sendUserMessage(contactCode: string, msg: string, cb?: any) {
if (!this.contacts[contactCode]) {
this.addContact(contactCode);
}
this.contacts[contactCode].lastClockValue++;
this.shh.post({
pubKey: contactCode,
sig: _sig.get(this),
ttl: constants.post.TTL,
topic: constants.topics.CONTACT_DISCOVERY_TOPIC,
payload: createStatusPayload(msg, constants.messageTypes.USER_MESSAGE, this.contacts[contactCode].lastClockValue),
powTarget: constants.post.POW_TARGET,
powTime: constants.post.POW_TIME,
powTarget: constants.post.POW_TARGET
pubKey: contactCode,
sig: sig.get(this),
topic: constants.topics.CONTACT_DISCOVERY_TOPIC,
ttl: constants.post.TTL,
}).then(() => {
if (!cb) return;
if (!cb) {
return;
}
cb(null, true);
}).catch((e) => {
if (!cb) return;
}).catch((e: any) => {
if (!cb) {
return;
}
cb(e, false);
});
}
sendGroupMessage(channelName, msg, cb) {
public sendGroupMessage(channelName: string, msg: string, cb?: any) {
if (!this.channels[channelName]) {
if(!cb) return;
if (!cb) {
return;
}
return cb("unknown channel: " + channelName);
}
this.channels[channelName].lastClockValue++;
this.shh.post({
symKeyID: this.channels[channelName].channelKey,
sig: _sig.get(this),
ttl: constants.post.TTL,
topic: this.channels[channelName].channelCode,
payload: createStatusPayload(msg, constants.messageTypes.GROUP_MESSAGE, this.channels[channelName].lastClockValue),
powTarget: constants.post.POW_TARGET,
powTime: constants.post.POW_TIME,
powTarget: constants.post.POW_TARGET
sig: sig.get(this),
symKeyID: this.channels[channelName].channelKey,
topic: this.channels[channelName].channelCode,
ttl: constants.post.TTL,
}).then(() => {
if (!cb) return;
if (!cb) {
return;
}
cb(null, true);
}).catch((e) => {
if (!cb) return;
}).catch((e: any) => {
if (!cb) {
return;
}
cb(e, false);
});
}
sendJsonMessage(destination, msg, cb) {
public sendJsonMessage(destination: string, msg: string, cb?: any) {
if (constants.regExp.CONTACT_CODE_REGEXP.test(destination)) {
if(!this.contacts[destination]){
if (!this.contacts[destination]) {
this.addContact(destination);
}
this.contacts[destination].lastClockValue++;
this.shh.post({
pubKey: destination,
sig: _sig.get(this),
ttl: constants.post.TTL,
topic: constants.topics.CONTACT_DISCOVERY_TOPIC,
payload: createStatusPayload(msg, constants.messageTypes.USER_MESSAGE, this.contacts[destination].lastClockValue, true),
powTarget: constants.post.POW_TARGET,
powTime: constants.post.POW_TIME,
powTarget: constants.post.POW_TARGET
pubKey: destination,
sig: sig.get(this),
topic: constants.topics.CONTACT_DISCOVERY_TOPIC,
ttl: constants.post.TTL,
}).then(() => {
if (!cb) return;
if (!cb) {
return;
}
cb(null, true);
}).catch((e) => {
if (!cb) return;
}).catch((e: any) => {
if (!cb) {
return;
}
cb(e, false);
});
} else {
this.channels[destination].lastClockValue++;
this.shh.post({
symKeyID: this.channels[destination].channelKey,
sig: _sig.get(this),
ttl: constants.post.TTL,
topic: this.channels[destination].channelCode,
payload: createStatusPayload(JSON.stringify(msg), constants.messageTypes.GROUP_MESSAGE, this.channels[destination].lastClockValue, true),
powTarget: constants.post.POW_TARGET,
powTime: constants.post.POW_TIME,
powTarget: constants.post.POW_TARGET
sig: sig.get(this),
symKeyID: this.channels[destination].channelKey,
topic: this.channels[destination].channelCode,
ttl: constants.post.TTL,
}).then(() => {
if (!cb) return;
if (!cb) {
return;
}
cb(null, true);
}).catch((e) => {
if (!cb) return;
}).catch((e: any) => {
if (!cb) {
return;
}
cb(e, false);
});
}
}
sendMessage(destination, msg, cb){
public sendMessage(destination: string, msg: string, cb?: any) {
if (constants.regExp.CONTACT_CODE_REGEXP.test(destination)) {
this.sendUserMessage(destination, msg, cb);
} else {

View File

@ -9,7 +9,7 @@ class MailServers {
this.web3 = web3;
}
public async useMailserver(mailserver: string, cb?: Function) {
public async useMailserver(mailserver: string, cb?: any) {
const enode: string = mailserverList[mailserver];
if (!enode) {

2
src/types.d.ts vendored
View File

@ -1 +1 @@
declare module 'chance'
declare module "chance";

View File

@ -9,6 +9,7 @@
"interface-name": [true, "never-prefix"],
"member-ordering": [false],
"no-var-requires": false,
"ordered-imports": false,
"no-empty": false,
"no-console": false
},