move remaining code to typescript
This commit is contained in:
parent
f1df122264
commit
8aaaabec1e
76
poc.js
76
poc.js
|
@ -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);
|
||||
});
|
||||
|
||||
})()
|
|
@ -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 {
|
|
@ -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) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
declare module 'chance'
|
||||
declare module "chance";
|
||||
|
|
|
@ -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
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue