From 494aa107795a4dc31a2a291f28f374fd444f8a44 Mon Sep 17 00:00:00 2001 From: Antoni Spaanderman <56turtle56@gmail.com> Date: Thu, 12 May 2022 14:06:12 +0200 Subject: [PATCH] selected some parts of #287 lower warning count to 466 --- package.json | 2 +- src/builtin/index.ts | 4 +- src/builtin/loop.ts | 40 ++++++------ src/builtin/mother.ts | 68 ++++++++++---------- src/builtin/welcome.ts | 31 +++++----- src/controllers/auth.ts | 2 +- src/controllers/chatTribes.ts | 2 +- src/controllers/invoices.ts | 3 +- src/controllers/media.ts | 5 +- src/controllers/messages.ts | 3 +- src/controllers/payment.ts | 7 ++- src/crypto/rsa.ts | 82 +++++++++++-------------- src/grpc/greenlight.ts | 19 +++--- src/grpc/interfaces.ts | 10 ++- src/grpc/lightning.ts | 70 +++++++++------------ src/helpers.ts | 36 +++++------ src/models/index.ts | 14 ++++- src/tests/utils/msg/sendTribeMessage.ts | 2 +- src/utils/msg.ts | 6 +- src/utils/tribes.ts | 8 +-- 20 files changed, 207 insertions(+), 207 deletions(-) diff --git a/package.json b/package.json index 38ddad7d4..4011d915e 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "dev": "rm -rf dist/ && tsc && cp -r public dist/public && node --inspect ./dist/app.js", "build-binaries": "rm -rf dist/ && tsc && cp config/app.json dist/config/app.json && cp config/config.json dist/config/config.json && pkg . --target node12-alpine-x64,node12-macos-x64 --out-path binaries", "start-ecs": "cp config/app.json dist/config/app.json && cp config/config.json dist/config/config.json && export NODE_ENV=production && node --max-old-space-size=128 dist/app.js", - "lint": "eslint ./src/*.ts ./src/**/*.ts --fix --max-warnings 517" + "lint": "eslint ./src/*.ts ./src/**/*.ts --fix --max-warnings 466" }, "keywords": [], "author": "", diff --git a/src/builtin/index.ts b/src/builtin/index.ts index 52cf1cf4d..9f6460335 100644 --- a/src/builtin/index.ts +++ b/src/builtin/index.ts @@ -7,14 +7,14 @@ import * as GitBot from './git' import { Msg } from '../network/interfaces' import { buildBotPayload } from '../controllers/bots' -async function init() { +async function init(): Promise { MotherBot.init() WelcomeBot.init() LoopBot.init() GitBot.init() } -function builtinBotEmit(msg: Msg) { +function builtinBotEmit(msg: Msg): void { setTimeout(() => { SphinxBot._emit('message', buildBotPayload(msg)) }, 1200) diff --git a/src/builtin/loop.ts b/src/builtin/loop.ts index f0d46d103..f26d1f1c7 100644 --- a/src/builtin/loop.ts +++ b/src/builtin/loop.ts @@ -6,17 +6,17 @@ import { spawn } from 'child_process' import { loadConfig } from '../utils/config' import { sphinxLogger } from '../utils/logger' import { getTribeOwnersChatByUUID } from '../utils/tribes' +import validate from 'bitcoin-address-validation' const config = loadConfig() -const validate = require('bitcoin-address-validation') const msg_types = Sphinx.MSG_TYPE let initted = false // const baseurl = 'https://localhost:8080' -export function init() { +export function init(): void { if (initted) return initted = true @@ -182,25 +182,27 @@ export function init() { } switch (cmd) { case 'help': - const embed = new Sphinx.MessageEmbed() - .setAuthor('LoopBot') - .setTitle('LoopBot Commands:') - .addFields([ - { - name: 'Send to your on-chain address', - value: '/loopout {ADDRESS} {AMOUNT}', - }, - { name: 'Set Channel', value: '/loopout setchan=***' }, - { name: 'Help', value: '/loopout help' }, - ]) - .setThumbnail(botSVG) - message.channel.send({ embed }) + message.channel.send({ + embed: new Sphinx.MessageEmbed() + .setAuthor('LoopBot') + .setTitle('LoopBot Commands:') + .addFields([ + { + name: 'Send to your on-chain address', + value: '/loopout {ADDRESS} {AMOUNT}', + }, + { name: 'Set Channel', value: '/loopout setchan=***' }, + { name: 'Help', value: '/loopout help' }, + ]) + .setThumbnail(botSVG) + }) return default: - const embed2 = new Sphinx.MessageEmbed() - .setAuthor('LoopBot') - .setDescription('Command not recognized') - message.channel.send({ embed: embed2 }) + message.channel.send({ + embed: new Sphinx.MessageEmbed() + .setAuthor('LoopBot') + .setDescription('Command not recognized') + }) return } } // end else diff --git a/src/builtin/mother.ts b/src/builtin/mother.ts index 7f734b685..7ef9c8edd 100644 --- a/src/builtin/mother.ts +++ b/src/builtin/mother.ts @@ -30,7 +30,7 @@ const builtInBotNames = { git: 'GitBot', } -export function init() { +export function init(): void { const client = new Sphinx.Client() client.login('_', finalAction) @@ -45,7 +45,7 @@ export function init() { if (!isAdmin) return switch (cmd) { - case 'install': + case 'install': { if (arr.length < 3) return const botName = arr[2] @@ -106,8 +106,8 @@ export function init() { } } return true - - case 'uninstall': + } + case 'uninstall': { if (arr.length < 3) return const botName2 = arr[2] const chat2 = await getTribeOwnersChatByUUID(message.channel.id) @@ -132,8 +132,8 @@ export function init() { .setDescription('Cant find a bot by that name') return message.channel.send({ embed }) } - - case 'search': + } + case 'search': { if (arr.length < 2) return const query = arr[2] const bots = await searchBots(query) @@ -143,35 +143,37 @@ export function init() { .setDescription('No bots found') return message.channel.send({ embed }) } - const embed3 = new Sphinx.MessageEmbed() - .setAuthor('MotherBot') - .setTitle('Bots:') - .addFields( - bots.map((b) => { - const maxLength = 35 - const value = - b.description.length > maxLength - ? b.description.substr(0, maxLength) + '...' - : b.description - return { name: b.unique_name, value } - }) - ) - .setThumbnail(botSVG) - message.channel.send({ embed: embed3 }) + message.channel.send({ + embed: new Sphinx.MessageEmbed() + .setAuthor('MotherBot') + .setTitle('Bots:') + .addFields( + bots.map((b) => { + const maxLength = 35 + const value = + b.description.length > maxLength + ? b.description.substr(0, maxLength) + '...' + : b.description + return { name: b.unique_name, value } + }) + ) + .setThumbnail(botSVG) + }) return true - + } default: - const embed = new Sphinx.MessageEmbed() - .setAuthor('MotherBot') - .setTitle('Bot Commands:') - .addFields([ - { name: 'Search for bots', value: '/bot search {SEARCH_TERM}' }, - { name: 'Install a new bot', value: '/bot install {BOTNAME}' }, - { name: 'Uninstall a bot', value: '/bot uninstall {BOTNAME}' }, - { name: 'Help', value: '/bot help' }, - ]) - .setThumbnail(botSVG) - message.channel.send({ embed }) + message.channel.send({ + embed: new Sphinx.MessageEmbed() + .setAuthor('MotherBot') + .setTitle('Bot Commands:') + .addFields([ + { name: 'Search for bots', value: '/bot search {SEARCH_TERM}' }, + { name: 'Install a new bot', value: '/bot install {BOTNAME}' }, + { name: 'Uninstall a bot', value: '/bot uninstall {BOTNAME}' }, + { name: 'Help', value: '/bot help' }, + ]) + .setThumbnail(botSVG) + }) } }) } diff --git a/src/builtin/welcome.ts b/src/builtin/welcome.ts index 715c0d746..aa8a7dc64 100644 --- a/src/builtin/welcome.ts +++ b/src/builtin/welcome.ts @@ -9,7 +9,7 @@ const msg_types = Sphinx.MSG_TYPE let initted = false -export function init() { +export function init(): void { if (initted) return initted = true @@ -61,7 +61,7 @@ export function init() { if (!isAdmin) return switch (cmd) { - case 'setmessage': + case 'setmessage': { if (arr.length < 3) return sphinxLogger.info(`setmsg ${arr[2]}`) const chat = await getTribeOwnersChatByUUID(message.channel.id) @@ -83,20 +83,21 @@ export function init() { .setDescription('Your welcome message has been updated') message.channel.send({ embed: resEmbed }) return - + } default: - const embed = new Sphinx.MessageEmbed() - .setAuthor('WelcomeBot') - .setTitle('Bot Commands:') - .addFields([ - { - name: 'Set welcome message', - value: '/welcome setmessage {MESSAGE}', - }, - { name: 'Help', value: '/welcome help' }, - ]) - .setThumbnail(botSVG) - message.channel.send({ embed }) + message.channel.send({ + embed: new Sphinx.MessageEmbed() + .setAuthor('WelcomeBot') + .setTitle('Bot Commands:') + .addFields([ + { + name: 'Set welcome message', + value: '/welcome setmessage {MESSAGE}', + }, + { name: 'Help', value: '/welcome help' }, + ]) + .setThumbnail(botSVG) + }) return } }) diff --git a/src/controllers/auth.ts b/src/controllers/auth.ts index 4007ae8e7..81947ea46 100644 --- a/src/controllers/auth.ts +++ b/src/controllers/auth.ts @@ -84,7 +84,7 @@ export async function requestTransportKey(req: Req, res) { return } - const transportTokenKeys: { [k: string]: string } = await rsa.genKeys() + const transportTokenKeys = await rsa.genKeys() fs.writeFileSync(config.transportPublicKeyLocation, transportTokenKeys.public) fs.writeFileSync( config.transportPrivateKeyLocation, diff --git a/src/controllers/chatTribes.ts b/src/controllers/chatTribes.ts index 684ec79c9..23b6f2206 100644 --- a/src/controllers/chatTribes.ts +++ b/src/controllers/chatTribes.ts @@ -761,7 +761,7 @@ export async function createTribeChatParams( } // make ts sig here w LNd pubkey - that is UUID - const keys: { [k: string]: string } = await rsa.genKeys() + const keys = await rsa.genKeys() const groupUUID = await tribes.genSignedTimestamp(owner.publicKey) const theContactIds = contactIds.includes(owner.id) ? contactIds diff --git a/src/controllers/invoices.ts b/src/controllers/invoices.ts index 19878b1ac..7ba7ae301 100644 --- a/src/controllers/invoices.ts +++ b/src/controllers/invoices.ts @@ -16,6 +16,7 @@ import * as bolt11 from '@boltz/bolt11' import { sphinxLogger } from '../utils/logger' import { Req } from '../types' import { Response } from 'express' +import { ChatPlusMembers } from '../network/send' function stripLightningPrefix(s: string): string { if (s.toLowerCase().startsWith('lightning:')) return s.substring(10) @@ -202,7 +203,7 @@ export const createInvoice = async (req: Req, res: Response): Promise => { success(res, jsonUtils.messageToJson(message, chat)) network.sendMessage({ - chat: chat, + chat: chat as Partial, sender: owner, type: constants.message_types.invoice, message: { diff --git a/src/controllers/media.ts b/src/controllers/media.ts index ddc5a7266..ee798262d 100644 --- a/src/controllers/media.ts +++ b/src/controllers/media.ts @@ -18,6 +18,7 @@ import { loadConfig } from '../utils/config' import { failure } from '../utils/res' import { logging, sphinxLogger } from '../utils/logger' import { Req } from '../types' +import { ChatPlusMembers } from '../network/send' const config = loadConfig() @@ -143,7 +144,7 @@ export const sendAttachmentMessage = async (req: Req, res) => { if (reply_uuid) msg.replyUuid = reply_uuid if (parent_id) msg.parentId = parent_id network.sendMessage({ - chat: chat, + chat: chat as Partial, sender: owner, type: constants.message_types.attachment, amount: amount || 0, @@ -230,7 +231,7 @@ export const purchase = async (req: Req, res) => { purchaser: owner.id, // for tribe, knows who sent } network.sendMessage({ - chat: { ...chat.dataValues, contactIds: [contact_id] }, + chat: { ...chat.dataValues, contactIds: JSON.stringify([ contact_id ]) }, sender: owner, type: constants.message_types.purchase, realSatsContactId: contact_id, // ALWAYS will be keysend, so doesnt matter if tribe owner or not diff --git a/src/controllers/messages.ts b/src/controllers/messages.ts index 7c2af8d13..72987b589 100644 --- a/src/controllers/messages.ts +++ b/src/controllers/messages.ts @@ -15,6 +15,7 @@ import * as short from 'short-uuid' import constants from '../constants' import { logging, sphinxLogger } from '../utils/logger' import { Req, Res } from '../types' +import { ChatPlusMembers } from '../network/send' // deprecated export const getMessages = async (req: Req, res: Res): Promise => { @@ -383,7 +384,7 @@ export const sendMessage = async (req: Req, res: Res): Promise => { if (recipientPic) msgToSend.recipientPic = recipientPic const sendMessageParams: SendMessageParams = { - chat: chat, + chat: chat as Partial, sender: owner, amount: amount || 0, type: msgtype, diff --git a/src/controllers/payment.ts b/src/controllers/payment.ts index d888c672f..c88c31ea9 100644 --- a/src/controllers/payment.ts +++ b/src/controllers/payment.ts @@ -1,4 +1,4 @@ -import { Message, Chat, models } from '../models' +import { Message, ChatRecord, models } from '../models' import { sendNotification } from '../hub' import * as socket from '../utils/socket' import * as jsonUtils from '../utils/json' @@ -14,6 +14,7 @@ import { anonymousKeysend } from './feed' import { sphinxLogger } from '../utils/logger' import { Req, Res } from '../types' import { sendConfirmation } from './confirmations' +import { ChatPlusMembers } from '../network/send' export const sendPayment = async (req: Req, res: Res): Promise => { if (!req.owner) return failure(res, 'no owner') @@ -120,11 +121,11 @@ export const sendPayment = async (req: Req, res: Res): Promise => { // if remote text map, put that in let theChat = chat if (contact_ids) { - theChat = { ...chat.dataValues, contactIds: contact_ids } as Chat + theChat = { ...chat.dataValues, contactIds: contact_ids } if (remote_text_map) msgToSend.content = remote_text_map } network.sendMessage({ - chat: theChat, + chat: theChat as Partial, sender: owner, type: constants.message_types.direct_payment, message: msgToSend as Message, diff --git a/src/crypto/rsa.ts b/src/crypto/rsa.ts index ac7bbb4e0..1e16b5ac2 100644 --- a/src/crypto/rsa.ts +++ b/src/crypto/rsa.ts @@ -3,14 +3,18 @@ import * as crypto from 'crypto' const BLOCK_SIZE = 256 const MAX_CHUNK_SIZE = BLOCK_SIZE - 11 // 11 is the PCKS1 padding -export function encrypt(key, txt) { +export interface KeyPair { + public: string, + private: string +} + +export function encrypt(key: string, txt: string): string { try { const buf = Buffer.from(txt) - let finalBuf = Buffer.from([]) + let finalBuf = Buffer.alloc(0) const n = Math.ceil(buf.length / MAX_CHUNK_SIZE) - const arr = Array(n).fill(0) const pubc = cert.pub(key) - arr.forEach((_, i) => { + for (let i = 0; i < n; i++) { const f = crypto.publicEncrypt( { key: pubc, @@ -18,22 +22,21 @@ export function encrypt(key, txt) { }, buf.subarray(i * MAX_CHUNK_SIZE, i * MAX_CHUNK_SIZE + MAX_CHUNK_SIZE) ) - finalBuf = Buffer.concat([finalBuf, f]) - }) + finalBuf = Buffer.concat([ finalBuf, f ]) + } return finalBuf.toString('base64') } catch (e) { return '' } } -export function decrypt(privateKey, enc) { +export function decrypt(privateKey: string | Buffer, enc: string): string { try { const buf = Buffer.from(enc, 'base64') let finalDec = '' const n = Math.ceil(buf.length / BLOCK_SIZE) - const arr = Array(n).fill(0) const privc = cert.priv(privateKey) - arr.forEach((_, i) => { + for (let i = 0; i < n; i++) { const b = crypto.privateDecrypt( { key: privc, @@ -42,32 +45,35 @@ export function decrypt(privateKey, enc) { buf.subarray(i * BLOCK_SIZE, i * BLOCK_SIZE + BLOCK_SIZE) ) finalDec += b.toString('utf-8') - }) + } return finalDec } catch (e) { return '' } } -export function genKeys(): Promise<{ [k: string]: string }> { - return new Promise((resolve, reject) => { +export function genKeys(): Promise { + return new Promise(resolve => { crypto.generateKeyPair( 'rsa', { modulusLength: 2048, }, (err, publicKey, privKey) => { + if (err) { + // TODO handle error + } const pubPEM = publicKey.export({ type: 'pkcs1', format: 'pem', }) - const pubBase64 = cert.unpub(pubPEM) + const pubBase64 = cert.unpub(pubPEM.toString()) const privPEM = privKey.export({ type: 'pkcs1', format: 'pem', }) - const privBase64 = cert.unpriv(privPEM) - resolve({ + const privBase64 = cert.unpriv(privPEM.toString()) + resolve({ public: pubBase64, private: privBase64, }) @@ -76,18 +82,19 @@ export function genKeys(): Promise<{ [k: string]: string }> { }) } -export function testRSA() { +export function testRSA(): void { crypto.generateKeyPair( 'rsa', { modulusLength: 2048, }, (err, publicKey, privateKey) => { + if (err) console.log('error', err) const pubPEM = publicKey.export({ type: 'pkcs1', format: 'pem', }) - const pub = cert.unpub(pubPEM) + const pub = cert.unpub(pubPEM.toString()) const msg = 'hi' const enc = encrypt(pub, msg) @@ -96,41 +103,22 @@ export function testRSA() { type: 'pkcs1', format: 'pem', }) - const priv = cert.unpriv(privPEM) + const priv = cert.unpriv(privPEM.toString()) const dec = decrypt(priv, enc) - console.log(`SUCESS: ${msg === dec}`) + console.log(`SUCCESS: ${msg === dec}`) } ) } +const beginPub = '-----BEGIN RSA PUBLIC KEY-----' +const endPub = '-----END RSA PUBLIC KEY-----' +const beginPriv = '-----BEGIN RSA PRIVATE KEY-----' +const endPriv = '-----END RSA PRIVATE KEY-----' + const cert = { - unpub: function (key) { - let s = key - s = s.replace('-----BEGIN RSA PUBLIC KEY-----', '') - s = s.replace('-----END RSA PUBLIC KEY-----', '') - return s.replace(/[\r\n]+/gm, '') - }, - unpriv: function (key) { - let s = key - s = s.replace('-----BEGIN RSA PRIVATE KEY-----', '') - s = s.replace('-----END RSA PRIVATE KEY-----', '') - return s.replace(/[\r\n]+/gm, '') - }, - pub: function (key) { - return ( - '-----BEGIN RSA PUBLIC KEY-----\n' + - key + - '\n' + - '-----END RSA PUBLIC KEY-----' - ) - }, - priv: function (key) { - return ( - '-----BEGIN RSA PRIVATE KEY-----\n' + - key + - '\n' + - '-----END RSA PRIVATE KEY-----' - ) - }, + unpub: (key: string): string => key.replace(beginPub, '').replace(endPub, '').trim(), + unpriv: (key: string): string => key.replace(beginPriv, '').replace(endPriv, '').trim(), + pub: (key: string | Buffer): string => beginPub + '\n' + key + '\n' + endPub, + priv: (key: string | Buffer): string => beginPriv + '\n' + key + '\n' + endPriv } diff --git a/src/grpc/greenlight.ts b/src/grpc/greenlight.ts index 70b19a939..b78cc4984 100644 --- a/src/grpc/greenlight.ts +++ b/src/grpc/greenlight.ts @@ -63,6 +63,7 @@ interface GreenlightIdentity { bolt12_key: string initialized: boolean } + export async function startGreenlightInit(): Promise { sphinxLogger.info('=> startGreenlightInit') try { @@ -107,9 +108,10 @@ interface ScheduleResponse { node_id: Buffer grpc_uri: string } + export function schedule(pubkey: string): Promise { sphinxLogger.info('=> Greenlight schedule') - return new Promise(async (resolve, reject) => { + return new Promise((resolve, reject) => { try { const s = loadScheduler() s.schedule( @@ -132,11 +134,11 @@ export function schedule(pubkey: string): Promise { }) } -async function recoverGreenlight(gid: GreenlightIdentity) { +async function recoverGreenlight(gid: GreenlightIdentity): Promise { sphinxLogger.info('=> recoverGreenlight') try { const challenge = await get_challenge(gid.node_id) - const signature = await sign_challenge(challenge) + const signature = sign_challenge(challenge) const res = await recover(gid.node_id, challenge, signature) const keyLoc = config.tls_key_location const chainLoc = config.tls_chain_location @@ -164,7 +166,7 @@ async function registerGreenlight( try { sphinxLogger.info('=> registerGreenlight') const challenge = await get_challenge(gid.node_id) - const signature = await sign_challenge(challenge) + const signature = sign_challenge(challenge) const res = await register( gid.node_id, gid.bip32_key + gid.bolt12_key, @@ -185,7 +187,7 @@ async function registerGreenlight( } export function get_challenge(node_id: string): Promise { - return new Promise(async (resolve, reject) => { + return new Promise((resolve, reject) => { try { const s = loadScheduler() s.getChallenge( @@ -227,7 +229,7 @@ export function register( challenge: string, signature: string ): Promise { - return new Promise(async (resolve, reject) => { + return new Promise((resolve, reject) => { try { const s = loadScheduler() s.register( @@ -258,7 +260,7 @@ export function recover( challenge: string, signature: string ): Promise { - return new Promise(async (resolve, reject) => { + return new Promise((resolve, reject) => { try { const s = loadScheduler() s.recover( @@ -287,15 +289,18 @@ interface HsmRequestContext { dbid: string // uint64 capabilities: string // uint64 } + export interface HsmRequest { request_id: number context: HsmRequestContext raw: Buffer } + interface HsmResponse { request_id: number raw: ByteBuffer } + export async function streamHsmRequests(): Promise { const capabilities_bitset = 1087 // 1 + 2 + 4 + 8 + 16 + 32 + 1024 try { diff --git a/src/grpc/interfaces.ts b/src/grpc/interfaces.ts index dc4d78083..6368dc94b 100644 --- a/src/grpc/interfaces.ts +++ b/src/grpc/interfaces.ts @@ -351,7 +351,7 @@ export function listPeersResponse( } export type Buf = Buffer | ByteBuffer | ArrayBuffer -type DestCustomRecords = { [key: string]: Buf } +type DestCustomRecords = { [k: string]: Buf } export interface KeysendRequest { amt: number final_cltv_delta: number @@ -531,6 +531,10 @@ export interface Invoice { features: { [k: string]: any } is_keysend: boolean } +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface Payment { + // if any fields are needed add them +} interface GreenlightOffchainPayment { label: string preimage: Buf @@ -614,13 +618,14 @@ export function connectPeerResponse( if (IS_GREENLIGHT) { return {} } - return {} + return {} } interface AmountsRes { satoshi: string millisatoshi: string } + function greenlightAmoutToAmounts(a: GreenlightAmount): AmountsRes { let satoshi = '' let millisatoshi = '' @@ -683,7 +688,6 @@ enum GreenlightChannelState { } function shortChanIDfromInt64(int: string): string { - if (typeof int !== 'string') return '' const l = long.fromString(int, true) const blockHeight = l.shiftRight(40) const txIndex = l.shiftRight(16).and(0xffffff) diff --git a/src/grpc/lightning.ts b/src/grpc/lightning.ts index c54ddfa46..29607d0a0 100644 --- a/src/grpc/lightning.ts +++ b/src/grpc/lightning.ts @@ -171,8 +171,8 @@ export async function queryRoute( routes: [], } } - return new Promise(async function (resolve, reject) { - const lightning = await loadLightning(true, ownerPubkey) // try proxy + const lightning = await loadLightning(true, ownerPubkey) // try proxy + return new Promise((resolve, reject) => { const options: { [k: string]: any } = { pub_key, amt } if (route_hint && route_hint.includes(':')) { const arr = route_hint.split(':') @@ -202,8 +202,8 @@ export type NewAddressType = 0 | 1 | 2 | 3 export async function newAddress( type: NewAddressType = NESTED_PUBKEY_HASH ): Promise { - return new Promise(async function (resolve, reject) { - const lightning = await loadLightning() + const lightning = await loadLightning() + return new Promise((resolve, reject) => { lightning.newAddress({ type }, (err, response) => { if (err) { reject(err) @@ -218,14 +218,14 @@ export async function newAddress( }) } -// for payingn invoice and invite invoice +// for paying invoice and invite invoice export async function sendPayment( payment_request: string, ownerPubkey?: string ): Promise { sphinxLogger.info('sendPayment', logging.Lightning) - return new Promise(async (resolve, reject) => { - const lightning = await loadLightning(true, ownerPubkey) // try proxy + const lightning = await loadLightning(true, ownerPubkey) // try proxy + return new Promise((resolve, reject) => { if (isProxy()) { const opts = { payment_request, @@ -289,8 +289,7 @@ export function keysend( sphinxLogger.info('keysend', logging.Lightning) return new Promise(async function (resolve, reject) { try { - const randoStr = crypto.randomBytes(32).toString('hex') - const preimage = ByteBuffer.fromHex(randoStr) + const preimage = ByteBuffer.wrap(crypto.randomBytes(32)) const dest_custom_records = { [`${LND_KEYSEND_KEY}`]: preimage, } @@ -427,7 +426,7 @@ export async function keysendMessage( let res: any = null const ts = new Date().valueOf() // WEAVE MESSAGE If TOO LARGE - await asyncForEach(Array.from(Array(n)), async (u, i) => { + for (let i = 0; i < n; i++) { const spliti = Math.ceil((opts.data || '').length / n) const m = (opts.data || '').substring(i * spliti, i * spliti + spliti) const isLastThread = i === n - 1 @@ -447,7 +446,7 @@ export async function keysendMessage( sphinxLogger.error(e) fail = true } - }) + } if (success && !fail) { resolve(res) } else { @@ -456,12 +455,6 @@ export async function keysendMessage( }) } -async function asyncForEach(array, callback) { - for (let index = 0; index < array.length; index++) { - await callback(array[index], index, array) - } -} - export async function signAscii( ascii: string, ownerPubkey?: string @@ -490,14 +483,14 @@ export function listInvoices(): Promise { }) } -export async function listAllInvoices(): Promise { +export async function listAllInvoices(): Promise { sphinxLogger.info(`=> list all invoices`) - const invs = await paginateInvoices(40) - return invs + return paginateInvoices(40) } -async function paginateInvoices(limit, i = 0) { + +async function paginateInvoices(limit: number, i = 0): Promise { try { - const r: any = await listInvoicesPaginated(limit, i) + const r = await listInvoicesPaginated(limit, i) const lastOffset = parseInt(r.first_index_offset) if (lastOffset > 0) { return r.invoices.concat(await paginateInvoices(limit, lastOffset)) @@ -507,7 +500,8 @@ async function paginateInvoices(limit, i = 0) { return [] } } -function listInvoicesPaginated(limit, offset) { + +function listInvoicesPaginated(limit: number, offset: number): Promise<{ first_index_offset: string, invoices: interfaces.Invoice[] }> { return new Promise(async (resolve, reject) => { const lightning = await loadLightning() lightning.listInvoices( @@ -525,15 +519,16 @@ function listInvoicesPaginated(limit, offset) { } // need to upgrade to .10 for this -export async function listAllPayments(): Promise { +export async function listAllPayments(): Promise { sphinxLogger.info('=> list all payments') const pays = await paginatePayments(40) // max num sphinxLogger.info(`pays ${pays && pays.length}`) return pays } -async function paginatePayments(limit, i = 0) { + +async function paginatePayments(limit: number, i = 0): Promise { try { - const r: any = await listPaymentsPaginated(limit, i) + const r = await listPaymentsPaginated(limit, i) const lastOffset = parseInt(r.first_index_offset) // this is "first" cuz its in reverse (lowest index) if (lastOffset > 0) { return r.payments.concat(await paginatePayments(limit, lastOffset)) @@ -543,10 +538,8 @@ async function paginatePayments(limit, i = 0) { return [] } } -export function listPaymentsPaginated( - limit: number, - offset: number -): Promise { + +export function listPaymentsPaginated(limit: number, offset: number): Promise<{ first_index_offset: string, payments: interfaces.Payment[] }> { return new Promise(async (resolve, reject) => { const lightning = await loadLightning() lightning.listPayments( @@ -563,7 +556,7 @@ export function listPaymentsPaginated( }) } -export function listAllPaymentsFull(): Promise { +export function listAllPaymentsFull(): Promise<{ payments: interfaces.Payment[] }> { sphinxLogger.info('=> list all payments') return new Promise(async (resolve, reject) => { const lightning = await loadLightning() @@ -578,13 +571,8 @@ export function listAllPaymentsFull(): Promise { } // msg is hex -export async function signMessage( - msg: string, - ownerPubkey?: string -): Promise { - // log('signMessage') - const r = await signBuffer(Buffer.from(msg, 'hex'), ownerPubkey) - return r +export async function signMessage(msg: string, ownerPubkey?: string): Promise { + return signBuffer(Buffer.from(msg, 'hex'), ownerPubkey) } export function signBuffer(msg: Buffer, ownerPubkey?: string): Promise { @@ -599,7 +587,7 @@ export function signBuffer(msg: Buffer, ownerPubkey?: string): Promise { const recidBytes = sigBuf.subarray(66, 67) // 31 is the magic EC recid (27+4) for compressed pubkeys const ecRecid = Buffer.from(recidBytes).readUIntBE(0, 1) + 31 - const finalRecid = Buffer.from('00', 'hex') + const finalRecid = Buffer.allocUnsafe(1) finalRecid.writeUInt8(ecRecid, 0) const finalSig = Buffer.concat([finalRecid, sigBytes], 65) resolve(zbase32.encode(finalSig)) @@ -628,7 +616,7 @@ export async function verifyBytes( return r } -interface VerifyResponse { +export interface VerifyResponse { valid: boolean pubkey: string } @@ -662,7 +650,7 @@ export function verifyMessage( ) ) ) - const recoveredPubkey = secp256k1.recover( + const recoveredPubkey: Buffer = secp256k1.recover( Buffer.from(hash), // 32 byte hash of message sigBytes, // 64 byte signature of message (not DER, 32 byte R and 32 byte S with 0x00 padding) recid, // number 1 or 0. This will usually be encoded in the base64 message signature diff --git a/src/helpers.ts b/src/helpers.ts index 4d600927e..9744d6265 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -5,10 +5,10 @@ import type { Msg, Payload, ChatMember } from './network/interfaces' import constants from './constants' import { logging, sphinxLogger } from './utils/logger' -export const findOrCreateChat = async (params) => { +export const findOrCreateChat = async (params: { chat_id: number, owner_id: number, recipient_id: number }): Promise => { const { chat_id, owner_id, recipient_id } = params // console.log("chat_id, owner_id, recipient_id", chat_id, owner_id, recipient_id) - let chat + let chat: ChatRecord const date = new Date() date.setMilliseconds(0) // console.log("findOrCreateChat", chat_id, typeof chat_id, owner_id, typeof owner_id) @@ -18,7 +18,7 @@ export const findOrCreateChat = async (params) => { }) // console.log('findOrCreateChat: chat_id exists') } else { - if (!owner_id || !recipient_id) return null + if (!owner_id || !recipient_id) return sphinxLogger.info(`chat does not exists, create new`) const owner: ContactRecord = await models.Contact.findOne({ where: { id: owner_id }, @@ -39,8 +39,8 @@ export const findOrCreateChat = async (params) => { chat = await models.Chat.create({ uuid: uuid, contactIds: JSON.stringify([ - parseInt(owner_id), - parseInt(recipient_id), + owner_id, + recipient_id, ]), createdAt: date, updatedAt: date, @@ -65,12 +65,12 @@ export const sendContactKeys = async ({ type: number contactIds: number[] sender: any - success?: Function - failure?: Function + success?: ({ destination_key: string, amount: number }) => void + failure?: (error: Error) => void dontActuallySendContactKey?: boolean contactPubKey?: string routeHint?: string -}) => { +}): Promise => { const msg = newkeyexchangemsg( type, sender, @@ -101,7 +101,7 @@ export const sendContactKeys = async ({ } const contact = await models.Contact.findOne({ where: { id: contactId } }) if (!(contact && contact.publicKey)) return - const destination_key = contact.publicKey + const destination_key: string = contact.publicKey const route_hint = contact.routeHint // console.log("=> KEY EXCHANGE", msg) @@ -143,11 +143,11 @@ export const performKeysendMessage = async ({ route_hint?: string amount: number msg: Partial - success?: Function - failure?: Function + success?: (arg: {destination_key: string, amount: number} | boolean) => void + failure?: (error: Error) => void sender: any extra_tlv?: { [k: string]: any } -}) => { +}): Promise => { const opts = { dest: destination_key, data: msg || {}, @@ -174,7 +174,7 @@ export async function findOrCreateContactByPubkeyAndRouteHint( senderAlias: string, owner: Contact, realAmount: number -) { +): Promise { let sender = await models.Contact.findOne({ where: { publicKey: senderPubKey, tenant: owner.id }, }) @@ -207,11 +207,7 @@ export async function findOrCreateContactByPubkeyAndRouteHint( return sender } -export async function findOrCreateChatByUUID( - chat_uuid, - contactIds, - tenant -): Promise { +export async function findOrCreateChatByUUID(chat_uuid: string, contactIds: number[], tenant: number): Promise { let chat = await models.Chat.findOne({ where: { uuid: chat_uuid, tenant, deleted: false }, }) @@ -230,7 +226,7 @@ export async function findOrCreateChatByUUID( return chat } -export async function sleep(ms) { +export async function sleep(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)) } @@ -356,7 +352,7 @@ export async function parseReceiveParams(payload: Payload): Promise<{ } } -export async function asyncForEach(array, callback) { +export async function asyncForEach(array: T[], callback: (value: T, index: number, array: T[]) => Promise): Promise { for (let index = 0; index < array.length; index++) { await callback(array[index], index, array) } diff --git a/src/models/index.ts b/src/models/index.ts index 296de6b59..b343d3eb0 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -1,5 +1,6 @@ // parse BIGINTs to number -require('pg').defaults.parseInt8 = true +import * as pg from 'pg' +pg.defaults.parseInt8 = true import { Sequelize } from 'sequelize-typescript' import * as path from 'path' import Chat, { ChatRecord } from './sql/chat' @@ -19,6 +20,7 @@ import RequestsTransportTokens from './sql/requestsTransportTokens' import * as minimist from 'minimist' import { loadConfig } from '../utils/config' import { isProxy } from '../utils/proxy' +import { readFileSync } from 'fs' const argv = minimist(process.argv.slice(2)) @@ -27,7 +29,7 @@ const configFile = argv.db : path.join(__dirname, '../../config/config.json') const env = process.env.NODE_ENV || 'development' -const config = require(configFile)[env] +const config = JSON.parse(readFileSync(configFile).toString())[env] const appConfig = loadConfig() @@ -81,4 +83,12 @@ export { BotMemberRecord, Invite, Subscription, + ChatBot, + Timer, + Bot, + Accounting, + MediaKey, + Lsat, + BotMember, + RequestsTransportTokens, } diff --git a/src/tests/utils/msg/sendTribeMessage.ts b/src/tests/utils/msg/sendTribeMessage.ts index cb5d7c348..7794e035e 100644 --- a/src/tests/utils/msg/sendTribeMessage.ts +++ b/src/tests/utils/msg/sendTribeMessage.ts @@ -18,7 +18,7 @@ export async function sendTribeMessage( t: Assertions, node1: NodeConfig, tribe: Chat, - text: String, + text: string, options?: SendMessageOptions ): Promise { //NODE1 SENDS TEXT MESSAGE TO NODE2 diff --git a/src/utils/msg.ts b/src/utils/msg.ts index ae231c510..cf8beaf5b 100644 --- a/src/utils/msg.ts +++ b/src/utils/msg.ts @@ -60,11 +60,11 @@ async function encryptTribeBroadcast( if (isTribeOwner) { // has been previously decrypted if (message.content) { - const encContent = await rsa.encrypt(contact.contactKey, message.content) + const encContent = rsa.encrypt(contact.contactKey, message.content.toString()) obj.content = encContent } if (message.mediaKey) { - const encMediaKey = await rsa.encrypt( + const encMediaKey = rsa.encrypt( contact.contactKey, message.mediaKey ) @@ -139,7 +139,7 @@ async function decryptMessage( content = m.content['chat'] } } - const decContent = rsa.decrypt(chat.groupPrivateKey, content) + const decContent = rsa.decrypt(chat.groupPrivateKey, content.toString()) obj.content = decContent } if (m.mediaKey) { diff --git a/src/utils/tribes.ts b/src/utils/tribes.ts index 21d694b44..ceabf4db8 100644 --- a/src/utils/tribes.ts +++ b/src/utils/tribes.ts @@ -41,7 +41,7 @@ export async function getTribeOwnersChatByUUID(uuid: string): Promise { model: models.Chat, mapToModel: true, // pass true here if you have any mapped fields } - ) as unknown as Chat + ) // console.log('=> getTribeOwnersChatByUUID r:', r) return r && r[0] && r[0].dataValues } catch (e) { @@ -138,7 +138,7 @@ async function initAndSubscribeTopics(onMessage: (topic: string, message: Buffer if (isProxy()) { const allOwners: Contact[] = await models.Contact.findAll({ where: { isOwner: true }, - }) as unknown as Contact[] + }) if (!(allOwners && allOwners.length)) return asyncForEach(allOwners, async c => { if (c.id === 1) return // the proxy non user @@ -170,7 +170,7 @@ async function subExtraHostsForTenant( tenant, host: { [Op.ne]: host }, // not the host from config }, - }) as unknown as Chat[] + }) if (!(externalTribes && externalTribes.length)) return const usedHosts: string[] = [] externalTribes.forEach(async (et) => { @@ -233,7 +233,7 @@ async function updateTribeStats(myPubkey) { ownerPubkey: myPubkey, deleted: false, }, - }) as unknown as Chat[] + }) await asyncForEach(myTribes, async (tribe) => { try { const contactIds = JSON.parse(tribe.contactIds)