From 9638907e11fcb2ee7bddec841e6750c34567db29 Mon Sep 17 00:00:00 2001 From: hatim boufnichel Date: Thu, 3 Dec 2020 16:20:15 +0100 Subject: [PATCH 01/34] create tunnel on startup --- .env.example | 3 +- config/defaults.js | 3 +- main.js | 12 +--- package.json | 3 +- src/server.js | 50 +++++++++++++- yarn.lock | 158 ++++----------------------------------------- 6 files changed, 71 insertions(+), 158 deletions(-) diff --git a/.env.example b/.env.example index 1e0d824d..638679f8 100644 --- a/.env.example +++ b/.env.example @@ -4,4 +4,5 @@ MS_TO_TOKEN_EXPIRATION=4500000 DISABLE_SHOCK_ENCRYPTION=false CACHE_HEADERS_MANDATORY=true SHOCK_CACHE=true -TRUSTED_KEYS=true \ No newline at end of file +TRUSTED_KEYS=true +LOCAL_TUNNEL_SERVER=http://tunnel.example.com \ No newline at end of file diff --git a/config/defaults.js b/config/defaults.js index c6cce6b3..684bfcdb 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -48,6 +48,7 @@ module.exports = (mainnet = false) => { lndDirPath: lndDirectory, peers: ['https://gun.shock.network:8765/gun'], useTLS: false, - tokenExpirationMS: 259200000 + tokenExpirationMS: 259200000, + localtunnelHost:'http://tunnel.example.com' }; }; diff --git a/main.js b/main.js index 29f478bb..7f1ae125 100644 --- a/main.js +++ b/main.js @@ -6,26 +6,18 @@ const {version} = (JSON.parse(require('fs').readFileSync("./package.json", "utf- program .version(version) .option("-s, --serverport [port]", "web server http listening port (defaults to 8280)") - .option("-x, --httpsport [port]", "web server https listening port (defaults to 8283)") .option("-h, --serverhost [host]", "web server listening host (defaults to localhost)") .option("-l, --lndhost [host:port]", "RPC lnd host (defaults to localhost:10009)") - .option("-t, --usetls [path]", "path to a directory containing key.pem and cert.pem files") .option("-u, --user [login]", "basic authentication login") .option("-p, --pwd [password]", "basic authentication password") - .option("-r, --limituser [login]", "basic authentication login for readonly account") - .option("-w, --limitpwd [password]", "basic authentication password for readonly account") .option("-m, --macaroon-path [file path]", "path to admin.macaroon file") .option("-d, --lnd-cert-path [file path]", "path to LND cert file") .option("-f, --logfile [file path]", "path to file where to store the application logs") .option("-e, --loglevel [level]", "level of logs to display (debug, info, warn, error)") - .option("-n, --lndlogfile ", "path to lnd log file to send to browser") .option("-k, --le-email [email]", "lets encrypt required contact email") .option("-c, --mainnet", "run server on mainnet mode") + .option("-t, --tunnel","create a localtunnel to listen behind a firewall") .parse(process.argv); // load server -if (program.serverhost && program.leEmail) { - require("./app/server-le")(program); // Let"s Encrypt server version -} else { - require("./src/server")(program); // Standard server version -} +require("./src/server")(program); // Standard server version diff --git a/package.json b/package.json index 00fd587b..cd5ab657 100644 --- a/package.json +++ b/package.json @@ -39,11 +39,12 @@ "husky": "^4.2.5", "jsonfile": "^4.0.0", "jsonwebtoken": "^8.3.0", - "localtunnel": "^1.9.0", + "localtunnel": "git://github.com/shocknet/localtunnel#40cc2c2a46b05da2217bf2e20da11a5343a5cce7", "lodash": "^4.17.20", "method-override": "^2.3.7", "node-persist": "^3.1.0", "promise": "^8.0.1", + "qrcode-terminal": "^0.12.0", "ramda": "^0.27.1", "request": "^2.88.2", "request-promise": "^4.2.2", diff --git a/src/server.js b/src/server.js index 7a0c2a4c..6e514a98 100644 --- a/src/server.js +++ b/src/server.js @@ -6,6 +6,7 @@ * Module dependencies. */ const server = program => { + const localtunnel = require('localtunnel') const Http = require('http') const Express = require('express') const Crypto = require('crypto') @@ -21,6 +22,7 @@ const server = program => { const bodyParser = require('body-parser') const session = require('express-session') const methodOverride = require('method-override') + const qrcode = require('qrcode-terminal') const { unprotectedRoutes, sensitiveRoutes, @@ -36,6 +38,7 @@ const server = program => { const serverPort = program.serverport || defaults.serverPort const serverHost = program.serverhost || defaults.serverHost + const tunnelHost = process.env.LOCAL_TUNNEL_SERVER || defaults.localtunnelHost // setup winston logging ========== const logger = require('../config/log')( @@ -216,11 +219,56 @@ const server = program => { next() }) - const storageDirectory = Path.resolve(rootFolder, `${program.rootPath ? '.' : '..'}/.storage`); + const storageDirectory = Path.resolve( + rootFolder, + `${program.rootPath ? '.' : '..'}/.storage` + ) await Storage.init({ dir: storageDirectory }) + if (program.tunnel) { + // setup localtunnel ========== + const [tunnelToken, tunnelSubdomain, tunnelUrl] = await Promise.all([ + Storage.getItem('tunnel/token'), + Storage.getItem('tunnel/subdomain'), + Storage.getItem('tunnel/url') + ]) + const tunnelOpts = { port: serverPort, host: tunnelHost } + if (tunnelToken && tunnelSubdomain) { + tunnelOpts.tunnelToken = tunnelToken + tunnelOpts.subdomain = tunnelSubdomain + logger.info('Recreating tunnel... with subdomain: ' + tunnelSubdomain) + } else { + logger.info('Creating new tunnel... ') + } + const tunnel = await localtunnel(tunnelOpts) + logger.info('Tunnel created! connect to: ' + tunnel.url + ':80') + const dataToQr = JSON.stringify({ + internalIP: tunnel.url, + walletPort: 80, //change to 443 for https + externalIP: tunnel.url + }) + qrcode.generate(dataToQr, { small: true }) + if (!tunnelToken) { + await Promise.all([ + Storage.setItem('tunnel/token', tunnel.token), + Storage.setItem('tunnel/subdomain', tunnel.clientId), + Storage.setItem('tunnel/url', tunnel.url) + ]) + } + if (tunnelUrl && tunnel.url !== tunnelUrl) { + logger.error('New tunnel URL different from OLD tunnel url') + logger.error('OLD: ' + tunnelUrl + ':80') + logger.error('NEW: ' + tunnel.url + ':80') + logger.error('New pair required') + await Promise.all([ + Storage.setItem('tunnel/token', tunnel.token), + Storage.setItem('tunnel/subdomain', tunnel.clientId), + Storage.setItem('tunnel/url', tunnel.url) + ]) + } + } const getSessionSecret = async () => { const sessionSecret = await Storage.getItem('config/sessionSecret') diff --git a/yarn.lock b/yarn.lock index 74f7a8e2..66c0a700 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1511,11 +1511,6 @@ camelcase@^2.0.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= - camelcase@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -1658,7 +1653,7 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= -cliui@^3.0.3, cliui@^3.2.0: +cliui@^3.0.3: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= @@ -2277,7 +2272,7 @@ enquirer@^2.3.4: dependencies: ansi-colors "^3.2.1" -error-ex@^1.2.0, error-ex@^1.3.1: +error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -2762,14 +2757,6 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -2903,11 +2890,6 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -3636,11 +3618,6 @@ is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -4334,17 +4311,6 @@ listr2@1.3.8: through "^2.3.8" uuid "^7.0.2" -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -4355,15 +4321,14 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" -localtunnel@^1.9.0: - version "1.9.2" - resolved "https://registry.yarnpkg.com/localtunnel/-/localtunnel-1.9.2.tgz#0012fcabc29cf964c130a01858768aa2bb65b5af" - integrity sha512-NEKF7bDJE9U3xzJu3kbayF0WTvng6Pww7tzqNb/XtEARYwqw7CKEX7BvOMg98FtE9es2CRizl61gkV3hS8dqYg== +"localtunnel@git://github.com/shocknet/localtunnel#40cc2c2a46b05da2217bf2e20da11a5343a5cce7": + version "2.0.0" + resolved "git://github.com/shocknet/localtunnel#40cc2c2a46b05da2217bf2e20da11a5343a5cce7" dependencies: axios "0.19.0" debug "4.1.1" openurl "1.1.1" - yargs "6.6.0" + yargs "13.3.0" locate-path@^3.0.0: version "3.0.0" @@ -5161,13 +5126,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -5220,13 +5178,6 @@ path-dirname@^1.0.0: resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -5267,15 +5218,6 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -5298,11 +5240,6 @@ picomatch@^2.0.5: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" @@ -5313,18 +5250,6 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" @@ -5497,6 +5422,11 @@ pvutils@latest: resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.0.17.tgz#ade3c74dfe7178944fe44806626bd2e249d996bf" integrity sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ== +qrcode-terminal@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" + integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== + qs@6.7.0: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" @@ -5552,14 +5482,6 @@ react-is@^16.8.4: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.10.1.tgz#0612786bf19df406502d935494f0450b40b8294f" integrity sha512-BXUMf9sIOPXXZWqr7+c5SeOKJykyVr2u0UDzEf4LNGc6taGkQe1A9DFD07umCIXz45RLr9oAAwZbAJ0Pkknfaw== -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - read-pkg-up@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" @@ -5568,15 +5490,6 @@ read-pkg-up@^4.0.0: find-up "^3.0.0" read-pkg "^3.0.0" -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -5774,11 +5687,6 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= - require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" @@ -6316,7 +6224,7 @@ string-length@^2.0.0: astral-regex "^1.0.0" strip-ansi "^4.0.0" -string-width@^1.0.1, string-width@^1.0.2: +string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= @@ -6427,13 +6335,6 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -7010,11 +6911,6 @@ whatwg-url@^7.0.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= - which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" @@ -7188,7 +7084,7 @@ xmlhttprequest-ssl@~1.5.4: resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4= -y18n@^3.2.0, y18n@^3.2.1: +y18n@^3.2.0: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= @@ -7221,33 +7117,7 @@ yargs-parser@^13.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" - integrity sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw= - dependencies: - camelcase "^3.0.0" - -yargs@6.6.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" - integrity sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg= - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^4.2.0" - -yargs@^13.3.0: +yargs@13.3.0, yargs@^13.3.0: version "13.3.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== From b9273cfe85fa3e7f8106e02a48571e7a22c39159 Mon Sep 17 00:00:00 2001 From: CapDog <34176400+capitalistdog@users.noreply.github.com> Date: Sun, 6 Dec 2020 16:38:59 -0500 Subject: [PATCH 02/34] Update defaults.js --- config/defaults.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/defaults.js b/config/defaults.js index 684bfcdb..7341dd50 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -49,6 +49,6 @@ module.exports = (mainnet = false) => { peers: ['https://gun.shock.network:8765/gun'], useTLS: false, tokenExpirationMS: 259200000, - localtunnelHost:'http://tunnel.example.com' + localtunnelHost:'https://tunnel.rip' }; }; From bb6600a1f402a5dd730bf1c5dd0598a27fc691b6 Mon Sep 17 00:00:00 2001 From: CapDog <34176400+capitalistdog@users.noreply.github.com> Date: Sun, 6 Dec 2020 16:39:57 -0500 Subject: [PATCH 03/34] Update .env.example --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 638679f8..d3798f0d 100644 --- a/.env.example +++ b/.env.example @@ -5,4 +5,4 @@ DISABLE_SHOCK_ENCRYPTION=false CACHE_HEADERS_MANDATORY=true SHOCK_CACHE=true TRUSTED_KEYS=true -LOCAL_TUNNEL_SERVER=http://tunnel.example.com \ No newline at end of file +LOCAL_TUNNEL_SERVER=https://tunnel.rip From bae55cefd842ee1a13386e480de4840e23ce796e Mon Sep 17 00:00:00 2001 From: CapDog <34176400+capitalistdog@users.noreply.github.com> Date: Sun, 6 Dec 2020 17:20:39 -0500 Subject: [PATCH 04/34] Update server.js --- src/server.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server.js b/src/server.js index 6e514a98..66b3826e 100644 --- a/src/server.js +++ b/src/server.js @@ -243,10 +243,10 @@ const server = program => { logger.info('Creating new tunnel... ') } const tunnel = await localtunnel(tunnelOpts) - logger.info('Tunnel created! connect to: ' + tunnel.url + ':80') + logger.info('Tunnel created! connect to: ' + tunnel.url) const dataToQr = JSON.stringify({ internalIP: tunnel.url, - walletPort: 80, //change to 443 for https + walletPort: 443, externalIP: tunnel.url }) qrcode.generate(dataToQr, { small: true }) From 86cb987f956a25bd1c3445540f5b1f326b2c6d05 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Sun, 17 Jan 2021 19:44:24 -0400 Subject: [PATCH 05/34] upgrade shock-common --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d3a0b1fe..28331476 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "request-promise": "^4.2.6", "response-time": "^2.3.2", "shelljs": "^0.8.2", - "shock-common": "29.1.0", + "shock-common": "30.0.0", "socket.io": "2.1.1", "text-encoding": "^0.7.0", "tingodb": "^0.6.1", diff --git a/yarn.lock b/yarn.lock index a8777e20..22c9bbc9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6282,10 +6282,10 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -shock-common@29.1.0: - version "29.1.0" - resolved "https://registry.yarnpkg.com/shock-common/-/shock-common-29.1.0.tgz#3b6d8613fb7c73b8b76c98293a14ec168a9dc888" - integrity sha512-O2tK+TShF3ioAdP4K33MB5QUDTmMqzz+pZe/HnSbi9q1DyX/zQ2Uluzol1NDE/6Z2SSnVFA7/2vJKGaCEdMKoQ== +shock-common@30.0.0: + version "30.0.0" + resolved "https://registry.yarnpkg.com/shock-common/-/shock-common-30.0.0.tgz#86ee39d076fe48adf551265c55e012ab3201c8e9" + integrity sha512-GgXCNOyk/iu0FBbYcfqOy7obX4RdEn3Q4y8R970CQVk7PvxYt0nZeQwKWe49esKb2B3JL1LOF/yJ7jg7tGze3w== dependencies: immer "^6.0.6" lodash "^4.17.19" From 7c2366d6186436dbb0388a38a0f83023ae065954 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 18 Jan 2021 15:23:20 -0400 Subject: [PATCH 06/34] coordinates key --- services/gunDB/contact-api/key.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/gunDB/contact-api/key.js b/services/gunDB/contact-api/key.js index 837ffc7d..210fae06 100644 --- a/services/gunDB/contact-api/key.js +++ b/services/gunDB/contact-api/key.js @@ -62,3 +62,5 @@ exports.TOTAL_TIPS = 'totalTips' exports.PROFILE_BINARY = 'profileBinary' exports.POSTS_NEW = 'posts' + +exports.COORDINATES = 'coordinates' From f19f04a97cc83b76be296a968961cb2a1d8af0ef Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 18 Jan 2021 15:42:59 -0400 Subject: [PATCH 07/34] basic coordinates --- services/coordinates.js | 63 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 services/coordinates.js diff --git a/services/coordinates.js b/services/coordinates.js new file mode 100644 index 00000000..79031940 --- /dev/null +++ b/services/coordinates.js @@ -0,0 +1,63 @@ +/** + * @format + */ + +const Common = require('shock-common') +const mapValues = require('lodash/mapValues') +const pickBy = require('lodash/pickBy') +const Bluebird = require('bluebird') +const Logger = require('winston') +const Key = require('../services/gunDB/contact-api/key') + +const { getUser, getMySecret, mySEA } = require('./gunDB/Mediator') + +/** + * @param {string} coordID + * @param {Common.Coordinate} data + * @returns {Promise} + */ +export const writeCoordinate = async (coordID, data) => { + if (coordID !== data.id) { + throw new Error('CoordID must be equal to data.id') + } + + try { + const gunNode = getUser() + .get(Key.COORDINATES) + .get(coordID) + + /** + * Because there are optional properties, typescript can also allow them + * to be specified but with a value of `undefined`. Filter out these. + * @type {Record} + */ + const sanitizedData = pickBy(data, v => typeof v !== 'undefined') + + const encData = await Bluebird.props( + mapValues(sanitizedData, v => { + return mySEA.encrypt(v, getMySecret()) + }) + ) + gunNode.put(encData, ack => { + if (ack.err && typeof ack.err !== 'number') { + Logger.info( + `Error writting corrdinate, coordinate id: ${coordID}, data: ${JSON.stringify( + data, + null, + 2 + )}` + ) + Logger.error(ack.err) + } + }) + } catch (e) { + Logger.info( + `Error writing coordinate, coordinate id: ${coordID}, data: ${JSON.stringify( + data, + null, + 2 + )}` + ) + Logger.error(e.message) + } +} From d67b6ef6740f8ea1eb1ccab8827f908871da7b23 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 18 Jan 2021 15:43:12 -0400 Subject: [PATCH 08/34] use basic coordinates --- utils/lightningServices/v2.js | 88 +++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 25 deletions(-) diff --git a/utils/lightningServices/v2.js b/utils/lightningServices/v2.js index b933c63b..db9f8d6b 100644 --- a/utils/lightningServices/v2.js +++ b/utils/lightningServices/v2.js @@ -6,6 +6,8 @@ const logger = require('winston') const Common = require('shock-common') const Ramda = require('ramda') +const { writeCoordinate } = require('../../services/coordinates') + const lightningServices = require('./lightning-services') /** * @typedef {import('./types').PaymentV2} PaymentV2 @@ -213,12 +215,39 @@ const isValidSendPaymentInvoiceParams = sendPaymentInvoiceParams => { return true } +/** + * @param {string} payReq + * @returns {Promise} + */ +const decodePayReq = payReq => + Common.Utils.makePromise((res, rej) => { + lightningServices.lightning.decodePayReq( + { pay_req: payReq }, + /** + * @param {{ message: any; }} err + * @param {any} paymentRequest + */ + (err, paymentRequest) => { + if (err) { + rej(new Error(err.message)) + } else { + res(paymentRequest) + } + } + ) + }) + +/** + * @returns {Promise} + */ +const myLNDPub = () => Promise.resolve('afjsjkhasdjkhajksd') + /** * aklssjdklasd * @param {SendPaymentV2Request} sendPaymentRequest * @returns {Promise} */ -const sendPaymentV2 = sendPaymentRequest => { +const sendPaymentV2 = async sendPaymentRequest => { const { services: { router } } = lightningServices @@ -229,7 +258,10 @@ const sendPaymentV2 = sendPaymentRequest => { ) } - return new Promise((res, rej) => { + /** + * @type {import("./types").PaymentV2} + */ + const paymentV2 = await Common.makePromise((res, rej) => { const stream = router.sendPaymentV2(sendPaymentRequest) stream.on( @@ -268,6 +300,33 @@ const sendPaymentV2 = sendPaymentRequest => { } ) }) + + /** @type {Common.Coordinate} */ + const coord = { + amount: Number(paymentV2.value_sat), + id: paymentV2.payment_hash, + inbound: false, + timestamp: Date.now(), + toLndPub: await myLNDPub(), + fromLndPub: undefined, + invoiceMemo: undefined, + type: 'payment' + } + + if (sendPaymentRequest.payment_request) { + const invoice = await decodePayReq(sendPaymentRequest.payment_request) + + coord.invoiceMemo = invoice.description + coord.toLndPub = invoice.destination + } + + if (sendPaymentRequest.dest) { + coord.toLndPub = sendPaymentRequest.dest.toString('base64') + } + + await writeCoordinate(paymentV2.payment_hash, coord) + + return paymentV2 } /** @@ -380,28 +439,6 @@ const listPayments = req => { }) } -/** - * @param {string} payReq - * @returns {Promise} - */ -const decodePayReq = payReq => - Common.Utils.makePromise((res, rej) => { - lightningServices.lightning.decodePayReq( - { pay_req: payReq }, - /** - * @param {{ message: any; }} err - * @param {any} paymentRequest - */ - (err, paymentRequest) => { - if (err) { - rej(new Error(err.message)) - } else { - res(paymentRequest) - } - } - ) - }) - /** * @param {0|1} type * @returns {Promise} @@ -582,5 +619,6 @@ module.exports = { getChanInfo, listPeers, pendingChannels, - addInvoice + addInvoice, + myLNDPub } From 16e90ebe4eee2efd22f96931235609480d5417cd Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 18 Jan 2021 15:44:06 -0400 Subject: [PATCH 09/34] use basic coordinates --- services/gunDB/contact-api/actions.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/services/gunDB/contact-api/actions.js b/services/gunDB/contact-api/actions.js index e747deda..2d93fc29 100644 --- a/services/gunDB/contact-api/actions.js +++ b/services/gunDB/contact-api/actions.js @@ -11,7 +11,8 @@ const { ErrorCode } = Constants const { sendPaymentV2Invoice, - decodePayReq + decodePayReq, + myLNDPub } = require('../../../utils/lightningServices/v2') /** @@ -21,6 +22,7 @@ const { const Getters = require('./getters') const Key = require('./key') const Utils = require('./utils') +const { writeCoordinate } = require('../../coordinates') /** * @typedef {import('./SimpleGUN').GUNNode} GUNNode @@ -1074,6 +1076,26 @@ const sendSpontaneousPayment = async ( payment_request: orderResponse.response }) + await writeCoordinate(payment.payment_hash, { + id: payment.payment_hash, + type: (() => { + if (opts.type === 'post') { + return 'tip' + } else if (opts.type === 'user') { + return 'spontaneousPayment' + } + // ensures we handle all possible types + /** @type {never} */ + const assertNever = opts.type + + return assertNever && opts.type // please TS + })(), + amount: Number(payment.value_sat), + inbound: false, + timestamp: Date.now(), + toLndPub: await myLNDPub() + }) + return payment } catch (e) { logger.error('Error inside sendPayment()') From 9c1e980bd35acb7cc28ea86017de48c9df6bc08d Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 18 Jan 2021 15:44:33 -0400 Subject: [PATCH 10/34] use basic coordinates --- services/gunDB/contact-api/jobs/onOrders.js | 157 ++++++++------------ 1 file changed, 64 insertions(+), 93 deletions(-) diff --git a/services/gunDB/contact-api/jobs/onOrders.js b/services/gunDB/contact-api/jobs/onOrders.js index 5cc5e124..430c6e5f 100644 --- a/services/gunDB/contact-api/jobs/onOrders.js +++ b/services/gunDB/contact-api/jobs/onOrders.js @@ -2,7 +2,6 @@ * @format */ // @ts-check -const { performance } = require('perf_hooks') const logger = require('winston') const isFinite = require('lodash/isFinite') const isNumber = require('lodash/isNumber') @@ -14,7 +13,11 @@ const { } = Common const LightningServices = require('../../../../utils/lightningServices') - +const { + addInvoice, + myLNDPub +} = require('../../../../utils/lightningServices/v2') +const { writeCoordinate } = require('../../../coordinates') const Key = require('../key') const Utils = require('../utils') @@ -56,28 +59,6 @@ const ordersProcessed = new Set() let currentOrderAddr = '' -/** - * @param {InvoiceRequest} invoiceReq - * @returns {Promise} - */ -const _addInvoice = invoiceReq => - new Promise((resolve, rej) => { - const { - services: { lightning } - } = LightningServices - - lightning.addInvoice(invoiceReq, ( - /** @type {any} */ error, - /** @type {InvoiceResponse} */ response - ) => { - if (error) { - rej(error) - } else { - resolve(response) - } - }) - }) - /** * @param {string} addr * @param {ISEA} SEA @@ -104,8 +85,6 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { return } - const listenerStartTime = performance.now() - ordersProcessed.add(orderID) logger.info( @@ -114,8 +93,6 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { )} -- addr: ${addr}` ) - const orderAnswerStartTime = performance.now() - const alreadyAnswered = await getUser() .get(Key.ORDER_TO_RESPONSE) .get(orderID) @@ -126,12 +103,6 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { return } - const orderAnswerEndTime = performance.now() - orderAnswerStartTime - - logger.info(`[PERF] Order Already Answered: ${orderAnswerEndTime}ms`) - - const decryptStartTime = performance.now() - const senderEpub = await Utils.pubToEpub(order.from) const secret = await SEA.secret(senderEpub, getUser()._.sea) @@ -140,10 +111,6 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { SEA.decrypt(order.memo, secret) ]) - const decryptEndTime = performance.now() - decryptStartTime - - logger.info(`[PERF] Decrypt invoice info: ${decryptEndTime}ms`) - const amount = Number(decryptedAmount) if (!isNumber(amount)) { @@ -175,26 +142,19 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { `onOrders() -> Will now create an invoice : ${JSON.stringify(invoiceReq)}` ) - const invoiceStartTime = performance.now() - - const invoice = await _addInvoice(invoiceReq) - - const invoiceEndTime = performance.now() - invoiceStartTime - - logger.info(`[PERF] LND Invoice created in ${invoiceEndTime}ms`) + const invoice = await addInvoice( + invoiceReq.value, + invoiceReq.memo, + true, + invoiceReq.expiry + ) logger.info( 'onOrders() -> Successfully created the invoice, will now encrypt it' ) - const invoiceEncryptStartTime = performance.now() - const encInvoice = await SEA.encrypt(invoice.payment_request, secret) - const invoiceEncryptEndTime = performance.now() - invoiceEncryptStartTime - - logger.info(`[PERF] Invoice encrypted in ${invoiceEncryptEndTime}ms`) - logger.info( `onOrders() -> Will now place the encrypted invoice in order to response usergraph: ${addr}` ) @@ -205,9 +165,7 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { type: 'invoice' } - const invoicePutStartTime = performance.now() - - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { getUser() .get(Key.ORDER_TO_RESPONSE) .get(orderID) @@ -223,9 +181,7 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { res() } }) - }) - - const invoicePutEndTime = performance.now() - invoicePutStartTime + })) // invoices should be settled right away so we can rely on this single // subscription instead of life-long all invoices subscription @@ -234,46 +190,61 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { if (!Common.isPopulatedString(postID)) { throw new TypeError(`postID not a a populated string`) } - - const { r_hash } = invoice - - // A post tip order lifecycle is short enough that we can do it like this. - const stream = LightningServices.invoices.subscribeSingleInvoice({ - r_hash - }) - - /** - * @param {Common.InvoiceWhenListed} invoice - */ - const onData = invoice => { - if (invoice.settled) { - getUser() - .get('postToTipCount') - .get(postID) - .set(null) // each item in the set is a tip - - stream.off() - } - } - - stream.on('data', onData) - - stream.on('status', (/** @type {any} */ status) => { - logger.info(`Post tip, post: ${postID}, invoice status:`, status) - }) - stream.on('end', () => { - logger.warn(`Post tip, post: ${postID}, invoice stream ended`) - }) - stream.on('error', (/** @type {any} */ e) => { - logger.warn(`Post tip, post: ${postID}, error:`, e) - }) } - logger.info(`[PERF] Added invoice to GunDB in ${invoicePutEndTime}ms`) + // A post tip order lifecycle is short enough that we can do it like this. + const stream = LightningServices.invoices.subscribeSingleInvoice({ + r_hash: invoice.r_hash + }) - const listenerEndTime = performance.now() - listenerStartTime + /** @type {Common.Coordinate} */ + const coord = { + amount, + id: invoice.r_hash.toString(), + inbound: true, + timestamp: Date.now(), + type: 'invoice', + invoiceMemo: memo, + fromGunPub: order.from, + toGunPub: getUser()._.sea.pub, + toLndPub: await myLNDPub() + } - logger.info(`[PERF] Invoice generation completed in ${listenerEndTime}ms`) + if (order.targetType === 'post') { + coord.type = 'tip' + } else { + coord.type = 'spontaneousPayment' + } + + /** + * @param {Common.InvoiceWhenListed} invoice + */ + const onData = invoice => { + if (invoice.settled) { + if (order.targetType === 'post') { + getUser() + .get('postToTipCount') + // CAST: Checked above. + .get(/** @type {string} */ (order.postID)) + .set(null) // each item in the set is a tip + } + + writeCoordinate(invoice.r_hash.toString(), coord) + stream.off() + } + } + + stream.on('data', onData) + + stream.on('status', (/** @type {any} */ status) => { + logger.info(`Post tip, post: ${order.postID}, invoice status:`, status) + }) + stream.on('end', () => { + logger.warn(`Post tip, post: ${order.postID}, invoice stream ended`) + }) + stream.on('error', (/** @type {any} */ e) => { + logger.warn(`Post tip, post: ${order.postID}, error:`, e) + }) } catch (err) { logger.error( `error inside onOrders, orderAddr: ${addr}, orderID: ${orderID}, order: ${JSON.stringify( From b4a24ce7fc7b2685c9022cb579f3aa4c8289bd4e Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 18 Jan 2021 16:37:18 -0400 Subject: [PATCH 11/34] implement lnd pub getter method --- utils/lightningServices/v2.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/utils/lightningServices/v2.js b/utils/lightningServices/v2.js index db9f8d6b..45a03a52 100644 --- a/utils/lightningServices/v2.js +++ b/utils/lightningServices/v2.js @@ -240,7 +240,18 @@ const decodePayReq = payReq => /** * @returns {Promise} */ -const myLNDPub = () => Promise.resolve('afjsjkhasdjkhajksd') +const myLNDPub = () => + Common.makePromise((res, rej) => { + const { lightning } = lightningServices.getServices() + + lightning.getInfo({}, (err, data) => { + if (err) { + rej(new Error(err.message)) + } else { + res(data.identity_pubkey) + } + }) + }) /** * aklssjdklasd From c8883b55d14c2f4fcfc11cb4ab7073177e415da1 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Wed, 3 Feb 2021 10:31:57 -0400 Subject: [PATCH 12/34] use on(), wait 10 seconds for epub to arrive --- services/gunDB/contact-api/utils/index.js | 30 +++++++---------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/services/gunDB/contact-api/utils/index.js b/services/gunDB/contact-api/utils/index.js index bcab3105..fc2abcd3 100644 --- a/services/gunDB/contact-api/utils/index.js +++ b/services/gunDB/contact-api/utils/index.js @@ -210,33 +210,21 @@ const tryAndWait = async (promGen, shouldRetry = () => false) => { * @param {string} pub * @returns {Promise} */ -const pubToEpub = async pub => { +const pubToEpub = pub => { try { - const epub = await tryAndWait(async gun => { - const _epub = await CommonUtils.makePromise(res => { - gun + return timeout10( + CommonUtils.makePromise(res => { + require('../../Mediator/index') + .getGun() .user(pub) .get('epub') - .once( - data => { + .on(data => { + if (typeof data === 'string') { res(data) - }, - { - wait: 1000 } - ) + }) }) - - if (typeof _epub !== 'string') { - throw new TypeError( - `Expected gun.user(pub).get(epub) to be an string. Instead got: ${typeof _epub}` - ) - } - - return _epub - }) - - return epub + ) } catch (err) { logger.error(err) throw new Error(`pubToEpub() -> ${err.message}`) From b5c9cc2151f61633db8679682e4b9234230a370d Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Wed, 3 Feb 2021 11:09:55 -0400 Subject: [PATCH 13/34] catch log and rethrow --- services/gunDB/contact-api/utils/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/gunDB/contact-api/utils/index.js b/services/gunDB/contact-api/utils/index.js index fc2abcd3..3af89742 100644 --- a/services/gunDB/contact-api/utils/index.js +++ b/services/gunDB/contact-api/utils/index.js @@ -210,9 +210,9 @@ const tryAndWait = async (promGen, shouldRetry = () => false) => { * @param {string} pub * @returns {Promise} */ -const pubToEpub = pub => { +const pubToEpub = async pub => { try { - return timeout10( + const epub = await timeout10( CommonUtils.makePromise(res => { require('../../Mediator/index') .getGun() @@ -225,6 +225,8 @@ const pubToEpub = pub => { }) }) ) + + return epub } catch (err) { logger.error(err) throw new Error(`pubToEpub() -> ${err.message}`) From 61952b17f4b87dc5094dc0042774dae798da8b48 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 08:57:10 -0400 Subject: [PATCH 14/34] simplify --- services/coordinates.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/services/coordinates.js b/services/coordinates.js index 79031940..ac212256 100644 --- a/services/coordinates.js +++ b/services/coordinates.js @@ -22,10 +22,6 @@ export const writeCoordinate = async (coordID, data) => { } try { - const gunNode = getUser() - .get(Key.COORDINATES) - .get(coordID) - /** * Because there are optional properties, typescript can also allow them * to be specified but with a value of `undefined`. Filter out these. @@ -38,18 +34,22 @@ export const writeCoordinate = async (coordID, data) => { return mySEA.encrypt(v, getMySecret()) }) ) - gunNode.put(encData, ack => { - if (ack.err && typeof ack.err !== 'number') { - Logger.info( - `Error writting corrdinate, coordinate id: ${coordID}, data: ${JSON.stringify( - data, - null, - 2 - )}` - ) - Logger.error(ack.err) - } - }) + + getUser() + .get(Key.COORDINATES) + .get(coordID) + .put(encData, ack => { + if (ack.err && typeof ack.err !== 'number') { + Logger.info( + `Error writting corrdinate, coordinate id: ${coordID}, data: ${JSON.stringify( + data, + null, + 2 + )}` + ) + Logger.error(ack.err) + } + }) } catch (e) { Logger.info( `Error writing coordinate, coordinate id: ${coordID}, data: ${JSON.stringify( From 2d24040894792d11c0223ec1095bc82d4c3f0078 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 10:37:15 -0400 Subject: [PATCH 15/34] upgrade typescript --- package.json | 2 +- services/gunDB/Mediator/index.js | 12 +-- services/gunDB/contact-api/actions.js | 92 +++++++++---------- .../contact-api/jobs/onAcceptedRequests.js | 12 +-- yarn.lock | 8 +- 5 files changed, 63 insertions(+), 63 deletions(-) diff --git a/package.json b/package.json index 28331476..d4f5e685 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "rimraf": "^3.0.2", "ts-node": "^9.1.1", "ts-type": "^1.2.16", - "typescript": "^4.0.2" + "typescript": "latest" }, "lint-staged": { "*.js": [ diff --git a/services/gunDB/Mediator/index.js b/services/gunDB/Mediator/index.js index e7914de8..eddb2466 100644 --- a/services/gunDB/Mediator/index.js +++ b/services/gunDB/Mediator/index.js @@ -314,7 +314,7 @@ const authenticate = async (alias, pass, __user) => { // clock skew await new Promise(res => setTimeout(res, 2000)) - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { _user.get(Key.FOLLOWS).put( { unused: null @@ -327,7 +327,7 @@ const authenticate = async (alias, pass, __user) => { } } ) - }) + })) return ack.sea.pub } else { @@ -345,7 +345,7 @@ const authenticate = async (alias, pass, __user) => { // clock skew await new Promise(res => setTimeout(res, 2000)) - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { _user.get(Key.FOLLOWS).put( { unused: null @@ -358,7 +358,7 @@ const authenticate = async (alias, pass, __user) => { } } ) - }) + })) // move this to a subscription; implement off() ? todo API.Jobs.onAcceptedRequests(_user, mySEA) @@ -404,7 +404,7 @@ const authenticate = async (alias, pass, __user) => { await new Promise(res => setTimeout(res, 5000)) - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { _user.get(Key.FOLLOWS).put( { unused: null @@ -417,7 +417,7 @@ const authenticate = async (alias, pass, __user) => { } } ) - }) + })) API.Jobs.onAcceptedRequests(_user, mySEA) API.Jobs.onOrders(_user, gun, mySEA) diff --git a/services/gunDB/contact-api/actions.js b/services/gunDB/contact-api/actions.js index 2d93fc29..14fd4bf1 100644 --- a/services/gunDB/contact-api/actions.js +++ b/services/gunDB/contact-api/actions.js @@ -100,7 +100,7 @@ const __createOutgoingFeed = async (withPublicKey, user, SEA) => { timestamp: Date.now() } - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.OUTGOINGS) .get(newOutgoingFeedID) @@ -113,14 +113,14 @@ const __createOutgoingFeed = async (withPublicKey, user, SEA) => { res() } }) - }) + })) const encryptedForMeNewOutgoingFeedID = await SEA.encrypt( newOutgoingFeedID, mySecret ) - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.RECIPIENT_TO_OUTGOING) .get(withPublicKey) @@ -131,7 +131,7 @@ const __createOutgoingFeed = async (withPublicKey, user, SEA) => { res() } }) - }) + })) outgoingFeedID = newOutgoingFeedID } @@ -237,7 +237,7 @@ const acceptRequest = async ( const mySecret = require('../Mediator').getMySecret() const encryptedForMeIncomingID = await SEA.encrypt(incomingID, mySecret) - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.USER_TO_INCOMING) .get(senderPublicKey) @@ -248,7 +248,7 @@ const acceptRequest = async ( res() } }) - }) + })) //////////////////////////////////////////////////////////////////////////// // NOTE: perform non-reversable actions before destructive actions @@ -261,7 +261,7 @@ const acceptRequest = async ( ourSecret ) - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { gun .get(Key.HANDSHAKE_NODES) .get(handshakeAddress) @@ -278,7 +278,7 @@ const acceptRequest = async ( } } ) - }) + })) } /** @@ -287,7 +287,7 @@ const acceptRequest = async ( * @param {UserGUNNode} userNode */ const authenticate = (user, pass, userNode) => - new Promise((resolve, reject) => { + /** @type {Promise} */ (new Promise((resolve, reject) => { if (typeof user !== 'string') { throw new TypeError('expected user to be of type string') } @@ -317,7 +317,7 @@ const authenticate = (user, pass, userNode) => resolve() } }) - }) + })) /** * @param {string} publicKey @@ -349,7 +349,7 @@ const generateHandshakeAddress = async () => { const address = uuidv1() - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { user.get(Key.CURRENT_HANDSHAKE_ADDRESS).put(address, ack => { if (ack.err && typeof ack.err !== 'number') { rej(new Error(ack.err)) @@ -357,9 +357,9 @@ const generateHandshakeAddress = async () => { res() } }) - }) + })) - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { gun .get(Key.HANDSHAKE_NODES) .get(address) @@ -370,7 +370,7 @@ const generateHandshakeAddress = async () => { res() } }) - }) + })) } /** @@ -387,7 +387,7 @@ const cleanup = async pub => { const promises = [] promises.push( - new Promise((res, rej) => { + /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.USER_TO_INCOMING) .get(pub) @@ -398,11 +398,11 @@ const cleanup = async pub => { res() } }) - }) + })) ) promises.push( - new Promise((res, rej) => { + /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.RECIPIENT_TO_OUTGOING) .get(pub) @@ -413,11 +413,11 @@ const cleanup = async pub => { res() } }) - }) + })) ) promises.push( - new Promise((res, rej) => { + /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.USER_TO_LAST_REQUEST_SENT) .get(pub) @@ -428,12 +428,12 @@ const cleanup = async pub => { res() } }) - }) + })) ) if (outGoingID) { promises.push( - new Promise((res, rej) => { + /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.OUTGOINGS) .get(outGoingID) @@ -444,7 +444,7 @@ const cleanup = async pub => { res() } }) - }) + })) ) } @@ -618,7 +618,7 @@ const sendHandshakeRequest = async (recipientPublicKey, gun, user, SEA) => { }) }) - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.USER_TO_LAST_REQUEST_SENT) .get(recipientPublicKey) @@ -629,7 +629,7 @@ const sendHandshakeRequest = async (recipientPublicKey, gun, user, SEA) => { res() } }) - }) + })) // This needs to come before the write to sent requests. Because that write // triggers Jobs.onAcceptedRequests and it in turn reads from request-to-user @@ -644,7 +644,7 @@ const sendHandshakeRequest = async (recipientPublicKey, gun, user, SEA) => { timestamp } - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { //@ts-ignore user.get(Key.STORED_REQS).set(storedReq, ack => { if (ack.err && typeof ack.err !== 'number') { @@ -657,7 +657,7 @@ const sendHandshakeRequest = async (recipientPublicKey, gun, user, SEA) => { res() } }) - }) + })) } /** @@ -1147,7 +1147,7 @@ const generateOrderAddress = user => * @returns {Promise} */ const setBio = (bio, user) => - new Promise((resolve, reject) => { + /** @type {Promise} */ (new Promise((resolve, reject) => { if (!user.is) { throw new Error(ErrorCode.NOT_AUTH) } @@ -1171,7 +1171,7 @@ const setBio = (bio, user) => resolve() } }) - }).then( + })).then( () => new Promise((resolve, reject) => { user @@ -1255,7 +1255,7 @@ const disconnect = async pub => { * @returns {Promise} */ const setLastSeenApp = () => - new Promise((res, rej) => { + /** @type {Promise} */ (new Promise((res, rej) => { require('../Mediator') .getUser() .get(Key.LAST_SEEN_APP) @@ -1266,7 +1266,7 @@ const setLastSeenApp = () => res() } }) - }).then( + })).then( () => new Promise((res, rej) => { require('../Mediator') @@ -1386,7 +1386,7 @@ const createPost = async (tags, title, content) => { pageIdx = Number(pageIdx + 1).toString() } - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { require('../Mediator') .getUser() .get(Key.WALL) @@ -1407,7 +1407,7 @@ const createPost = async (tags, title, content) => { res() } ) - }) + })) const [postID, newPost] = await createPostNew(tags, title, content) @@ -1433,7 +1433,7 @@ const createPost = async (tags, title, content) => { }) if (shouldBeNewPage || numOfPages === 0) { - await new Promise(res => { + await /** @type {Promise} */ (new Promise(res => { require('../Mediator') .getUser() .get(Key.WALL) @@ -1445,7 +1445,7 @@ const createPost = async (tags, title, content) => { res() }) - }) + })) } const loadedPost = await new Promise(res => { @@ -1488,7 +1488,7 @@ const createPost = async (tags, title, content) => { * @returns {Promise} */ const deletePost = async (postId, page) => { - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { require('../Mediator') .getUser() .get(Key.WALL) @@ -1503,15 +1503,15 @@ const deletePost = async (postId, page) => { res() } }) - }) + })) } /** * @param {string} publicKey * @param {boolean} isPrivate Will overwrite previous private status. - * @returns {Promise} + * @returns {Promise} */ -const follow = (publicKey, isPrivate) => { +const follow = async (publicKey, isPrivate) => { /** @type {import('shock-common').Schema.Follow} */ const newFollow = { private: isPrivate, @@ -1519,7 +1519,7 @@ const follow = (publicKey, isPrivate) => { user: publicKey } - return new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { require('../Mediator') .getUser() .get(Key.FOLLOWS) @@ -1532,7 +1532,7 @@ const follow = (publicKey, isPrivate) => { res() } }) - }) + })) } /** @@ -1564,7 +1564,7 @@ const initWall = async () => { const promises = [] promises.push( - new Promise((res, rej) => { + /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.WALL) .get(Key.NUM_OF_PAGES) @@ -1575,11 +1575,11 @@ const initWall = async () => { res() } }) - }) + })) ) promises.push( - new Promise((res, rej) => { + /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.WALL) .get(Key.PAGES) @@ -1597,11 +1597,11 @@ const initWall = async () => { } } ) - }) + })) ) promises.push( - new Promise((res, rej) => { + /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.WALL) .get(Key.PAGES) @@ -1614,7 +1614,7 @@ const initWall = async () => { res() } }) - }) + })) ) await Promise.all(promises) diff --git a/services/gunDB/contact-api/jobs/onAcceptedRequests.js b/services/gunDB/contact-api/jobs/onAcceptedRequests.js index ba9cad5a..255cc107 100644 --- a/services/gunDB/contact-api/jobs/onAcceptedRequests.js +++ b/services/gunDB/contact-api/jobs/onAcceptedRequests.js @@ -92,7 +92,7 @@ const onAcceptedRequests = (user, SEA) => { const recipientEpub = await Utils.pubToEpub(recipientPub) const ourSecret = await SEA.secret(recipientEpub, user._.sea) - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { gun .get(Key.HANDSHAKE_NODES) .get(requestAddress) @@ -151,7 +151,7 @@ const onAcceptedRequests = (user, SEA) => { mySecret ) - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.USER_TO_INCOMING) .get(recipientPub) @@ -162,9 +162,9 @@ const onAcceptedRequests = (user, SEA) => { res() } }) - }) + })) - await new Promise((res, rej) => { + await /** @type {Promise} */ (new Promise((res, rej) => { user .get(Key.STORED_REQS) .get(id) @@ -175,12 +175,12 @@ const onAcceptedRequests = (user, SEA) => { res() } }) - }) + })) // ensure this listeners gets called at least once res() }) - }) + })) } catch (err) { logger.warn(`Jobs.onAcceptedRequests() -> ${err.message}`) logger.error(err) diff --git a/yarn.lock b/yarn.lock index 22c9bbc9..f0de2b4b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7031,10 +7031,10 @@ typescript-tuple@^2.2.1: dependencies: typescript-compare "^0.0.2" -typescript@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2" - integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ== +typescript@latest: + version "4.1.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.5.tgz#123a3b214aaff3be32926f0d8f1f6e704eb89a72" + integrity sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA== uglify-js@^3.1.4: version "3.10.2" From dc65a3332e1965890b3eab0be7e6f65d1b57e9a3 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 13:06:06 -0400 Subject: [PATCH 16/34] add assert-never, dev-correctness utility --- package.json | 1 + yarn.lock | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/package.json b/package.json index d4f5e685..4539a8f6 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "dependencies": { "@grpc/grpc-js": "^1.2.2", "@grpc/proto-loader": "^0.5.5", + "assert-never": "^1.2.1", "axios": "^0.21.1", "basic-auth": "^2.0.0", "big.js": "^5.2.2", diff --git a/yarn.lock b/yarn.lock index f0de2b4b..8e497962 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1105,6 +1105,11 @@ asn1js@^2.0.26: dependencies: pvutils latest +assert-never@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/assert-never/-/assert-never-1.2.1.tgz#11f0e363bf146205fb08193b5c7b90f4d1cf44fe" + integrity sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw== + assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" From d02eee46fb91d32a5a505a81b68444993ef14200 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 13:43:14 -0400 Subject: [PATCH 17/34] upgrade shock-common --- package.json | 2 +- services/gunDB/contact-api/actions.js | 16 +++++++++++----- services/gunDB/contact-api/jobs/onOrders.js | 20 ++++++++++---------- yarn.lock | 20 ++++++++++---------- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 4539a8f6..bcbf2dfd 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "request-promise": "^4.2.6", "response-time": "^2.3.2", "shelljs": "^0.8.2", - "shock-common": "30.0.0", + "shock-common": "latest", "socket.io": "2.1.1", "text-encoding": "^0.7.0", "tingodb": "^0.6.1", diff --git a/services/gunDB/contact-api/actions.js b/services/gunDB/contact-api/actions.js index 14fd4bf1..5a904599 100644 --- a/services/gunDB/contact-api/actions.js +++ b/services/gunDB/contact-api/actions.js @@ -942,7 +942,7 @@ const sendSpontaneousPayment = async ( amount, memo, feeLimit, - opts = { type: 'user' } + opts = { type: 'spontaneousPayment' } ) => { try { const SEA = require('../Mediator').mySEA @@ -967,8 +967,8 @@ const sendSpontaneousPayment = async ( targetType: opts.type } - if (opts.type === 'post') { - order.postID = opts.postID + if (opts.type === 'tip') { + order.ackInfo = opts.postID } logger.info(JSON.stringify(order)) @@ -1079,10 +1079,16 @@ const sendSpontaneousPayment = async ( await writeCoordinate(payment.payment_hash, { id: payment.payment_hash, type: (() => { - if (opts.type === 'post') { + if (opts.type === 'tip') { return 'tip' - } else if (opts.type === 'user') { + } else if (opts.type === 'spontaneousPayment') { return 'spontaneousPayment' + } else if (opts.type === 'contentReveal') { + return 'other' // TODO + } else if (opts.type === 'other') { + return 'other' // TODO + } else if (opts.type === 'torrentSeed') { + return 'other' // TODO } // ensures we handle all possible types /** @type {never} */ diff --git a/services/gunDB/contact-api/jobs/onOrders.js b/services/gunDB/contact-api/jobs/onOrders.js index 430c6e5f..08eb4e5c 100644 --- a/services/gunDB/contact-api/jobs/onOrders.js +++ b/services/gunDB/contact-api/jobs/onOrders.js @@ -185,10 +185,10 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { // invoices should be settled right away so we can rely on this single // subscription instead of life-long all invoices subscription - if (order.targetType === 'post') { - const { postID } = order - if (!Common.isPopulatedString(postID)) { - throw new TypeError(`postID not a a populated string`) + if (order.targetType === 'tip') { + const { ackInfo } = order + if (!Common.isPopulatedString(ackInfo)) { + throw new TypeError(`ackInfo(postID) not a a populated string`) } } @@ -210,7 +210,7 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { toLndPub: await myLNDPub() } - if (order.targetType === 'post') { + if (order.targetType === 'tip') { coord.type = 'tip' } else { coord.type = 'spontaneousPayment' @@ -221,11 +221,11 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { */ const onData = invoice => { if (invoice.settled) { - if (order.targetType === 'post') { + if (order.targetType === 'tip') { getUser() .get('postToTipCount') // CAST: Checked above. - .get(/** @type {string} */ (order.postID)) + .get(/** @type {string} */ (order.ackInfo)) .set(null) // each item in the set is a tip } @@ -237,13 +237,13 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { stream.on('data', onData) stream.on('status', (/** @type {any} */ status) => { - logger.info(`Post tip, post: ${order.postID}, invoice status:`, status) + logger.info(`Post tip, post: ${order.ackInfo}, invoice status:`, status) }) stream.on('end', () => { - logger.warn(`Post tip, post: ${order.postID}, invoice stream ended`) + logger.warn(`Post tip, post: ${order.ackInfo}, invoice stream ended`) }) stream.on('error', (/** @type {any} */ e) => { - logger.warn(`Post tip, post: ${order.postID}, error:`, e) + logger.warn(`Post tip, post: ${order.ackInfo}, error:`, e) }) } catch (err) { logger.error( diff --git a/yarn.lock b/yarn.lock index 8e497962..9c1755a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -183,9 +183,9 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/runtime@^7.6.3": - version "7.11.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" - integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== + version "7.12.18" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.18.tgz#af137bd7e7d9705a412b3caaf991fe6aaa97831b" + integrity sha512-BogPQ7ciE6SYAUPtlm9tWbgI9+2AgqSam6QivMgXgAT+fKbgppaj4ZX15MHeLC1PVF5sNk70huBu20XxWOs8Cg== dependencies: regenerator-runtime "^0.13.4" @@ -5113,9 +5113,9 @@ normalize-path@^3.0.0: integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== normalizr@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/normalizr/-/normalizr-3.6.0.tgz#b8bbc4546ffe43c1c2200503041642915fcd3e1c" - integrity sha512-25cd8DiDu+pL46KIaxtVVvvEPjGacJgv0yUg950evr62dQ/ks2JO1kf7+Vi5/rMFjaSTSTls7aCnmRlUSljtiA== + version "3.6.1" + resolved "https://registry.yarnpkg.com/normalizr/-/normalizr-3.6.1.tgz#d367ab840e031ff382141b8d81ce279292ff69fe" + integrity sha512-8iEmqXmPtll8PwbEFrbPoDxVw7MKnNvt3PZzR2Xvq9nggEEOgBlNICPXYzyZ4w4AkHUzCU998mdatER3n2VaMA== npm-bundled@^1.0.1: version "1.0.6" @@ -6287,10 +6287,10 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -shock-common@30.0.0: - version "30.0.0" - resolved "https://registry.yarnpkg.com/shock-common/-/shock-common-30.0.0.tgz#86ee39d076fe48adf551265c55e012ab3201c8e9" - integrity sha512-GgXCNOyk/iu0FBbYcfqOy7obX4RdEn3Q4y8R970CQVk7PvxYt0nZeQwKWe49esKb2B3JL1LOF/yJ7jg7tGze3w== +shock-common@latest: + version "31.1.0" + resolved "https://registry.yarnpkg.com/shock-common/-/shock-common-31.1.0.tgz#9c8f25d0d405a9a9c52849c2d96452c5ddd17267" + integrity sha512-1490v3gTY5ZNEB/Lelfix+6bI4mfFE8hVrtN4ijz0aj/Cl1ZP5ATKdYO+hffReI+4yDaPSAAWd/HYk9b497Kxw== dependencies: immer "^6.0.6" lodash "^4.17.19" From 6b685f0024089c525749f6e6e354b27c1b93e3e0 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 15:19:00 -0400 Subject: [PATCH 18/34] upgrade shock-common --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index bcbf2dfd..9854db5e 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "request-promise": "^4.2.6", "response-time": "^2.3.2", "shelljs": "^0.8.2", - "shock-common": "latest", + "shock-common": "32.0.0", "socket.io": "2.1.1", "text-encoding": "^0.7.0", "tingodb": "^0.6.1", diff --git a/yarn.lock b/yarn.lock index 9c1755a2..8c5b24e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6287,10 +6287,10 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -shock-common@latest: - version "31.1.0" - resolved "https://registry.yarnpkg.com/shock-common/-/shock-common-31.1.0.tgz#9c8f25d0d405a9a9c52849c2d96452c5ddd17267" - integrity sha512-1490v3gTY5ZNEB/Lelfix+6bI4mfFE8hVrtN4ijz0aj/Cl1ZP5ATKdYO+hffReI+4yDaPSAAWd/HYk9b497Kxw== +shock-common@32.0.0: + version "32.0.0" + resolved "https://registry.yarnpkg.com/shock-common/-/shock-common-32.0.0.tgz#bb7f70d7a572783c46aeae7420179935eb5096d4" + integrity sha512-1GorUFRpkRGXdKT9PImwnj2orpoJaESU/iD+rvL8sqFMLKazkW9LfLAcRwEWCvytWdKFJ35UO2gN49N8dPiRmA== dependencies: immer "^6.0.6" lodash "^4.17.19" From 07d21b6fcfbc68df49d132ca3d5117816f9daa05 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 10:11:28 -0400 Subject: [PATCH 19/34] new env variables --- .env.example | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 1e0d824d..4e8f0e13 100644 --- a/.env.example +++ b/.env.example @@ -4,4 +4,6 @@ MS_TO_TOKEN_EXPIRATION=4500000 DISABLE_SHOCK_ENCRYPTION=false CACHE_HEADERS_MANDATORY=true SHOCK_CACHE=true -TRUSTED_KEYS=true \ No newline at end of file +TRUSTED_KEYS=true +TORRENT_SEED_URL=https://webtorrent.shock.network +TORRENT_SEED_TOKEN=jibberish From a37993c80ecbad3c79665a6de44e7201cc72485e Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 10:18:39 -0400 Subject: [PATCH 20/34] add node-fetch --- package.json | 2 ++ yarn.lock | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9854db5e..1003da1f 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "localtunnel": "^1.9.0", "lodash": "^4.17.20", "method-override": "^2.3.7", + "node-fetch": "^2.6.1", "node-persist": "^3.1.0", "promise": "^8.1.0", "ramda": "^0.27.1", @@ -68,6 +69,7 @@ "@types/jest": "^24.0.18", "@types/jsonwebtoken": "^8.3.7", "@types/lodash": "^4.14.141", + "@types/node-fetch": "^2.5.8", "@types/ramda": "types/npm-ramda#dist", "@types/react": "16.x.x", "@types/socket.io": "^2.1.11", diff --git a/yarn.lock b/yarn.lock index 8c5b24e9..969a012d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -722,6 +722,14 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== +"@types/node-fetch@^2.5.8": + version "2.5.8" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb" + integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*": version "12.7.4" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.4.tgz#64db61e0359eb5a8d99b55e05c729f130a678b04" @@ -1838,7 +1846,7 @@ colour@~0.7.1: resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778" integrity sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g= -combined-stream@^1.0.6, combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -2946,6 +2954,15 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -4991,7 +5008,7 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-fetch@^2.3.0: +node-fetch@^2.3.0, node-fetch@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== From fc2821f78c10a0f095dc91d8e384459030df58b2 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 11:07:26 -0400 Subject: [PATCH 21/34] reflect paid content status --- services/gunDB/contact-api/actions.js | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/services/gunDB/contact-api/actions.js b/services/gunDB/contact-api/actions.js index 5a904599..04324207 100644 --- a/services/gunDB/contact-api/actions.js +++ b/services/gunDB/contact-api/actions.js @@ -1293,9 +1293,10 @@ const setLastSeenApp = () => * @param {string[]} tags * @param {string} title * @param {Common.Schema.ContentItem[]} content + * @param {ISEA} SEA * @returns {Promise<[string, Common.Schema.RawPost]>} */ -const createPostNew = async (tags, title, content) => { +const createPostNew = async (tags, title, content, SEA) => { /** @type {Common.Schema.RawPost} */ const newPost = { date: Date.now(), @@ -1311,6 +1312,23 @@ const createPostNew = async (tags, title, content) => { newPost.contentItems[uuid] = c }) + const mySecret = require('../Mediator').getMySecret() + + await Common.Utils.asyncForEach(content, async c => { + // @ts-expect-error + const uuid = Gun.text.random() + newPost.contentItems[uuid] = c + if ( + (c.type === 'image/embedded' || c.type === 'video/embedded') && + c.isPrivate + ) { + const encryptedMagnet = await SEA.encrypt(c.magnetURI, mySecret) + newPost.contentItems[uuid] = { ...c, magnetURI: encryptedMagnet } + } else { + newPost.contentItems[uuid] = c + } + }) + /** @type {string} */ const postID = await Common.makePromise((res, rej) => { const _n = require('../Mediator') @@ -1415,7 +1433,12 @@ const createPost = async (tags, title, content) => { ) })) - const [postID, newPost] = await createPostNew(tags, title, content) + const [postID, newPost] = await createPostNew( + tags, + title, + content, + require('../Mediator').mySEA + ) await Common.makePromise((res, rej) => { require('../Mediator') From 38bf829af12f191ec28957869d5b482bc567e02c Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 13:09:05 -0400 Subject: [PATCH 22/34] write coordinate before anything else --- services/gunDB/contact-api/jobs/onOrders.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/gunDB/contact-api/jobs/onOrders.js b/services/gunDB/contact-api/jobs/onOrders.js index 08eb4e5c..8496cdfe 100644 --- a/services/gunDB/contact-api/jobs/onOrders.js +++ b/services/gunDB/contact-api/jobs/onOrders.js @@ -221,6 +221,7 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { */ const onData = invoice => { if (invoice.settled) { + writeCoordinate(invoice.r_hash.toString(), coord) if (order.targetType === 'tip') { getUser() .get('postToTipCount') @@ -229,7 +230,6 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { .set(null) // each item in the set is a tip } - writeCoordinate(invoice.r_hash.toString(), coord) stream.off() } } From 09f717b1a3f6a5ed3e4fe1d4930b7571672205b3 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 14:33:55 -0400 Subject: [PATCH 23/34] several order types --- services/gunDB/contact-api/jobs/onOrders.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/services/gunDB/contact-api/jobs/onOrders.js b/services/gunDB/contact-api/jobs/onOrders.js index 8496cdfe..8d7a717e 100644 --- a/services/gunDB/contact-api/jobs/onOrders.js +++ b/services/gunDB/contact-api/jobs/onOrders.js @@ -11,6 +11,7 @@ const { Constants: { ErrorCode }, Schema } = Common +const { assertNever } = require('assert-never') const LightningServices = require('../../../../utils/lightningServices') const { @@ -222,12 +223,23 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { const onData = invoice => { if (invoice.settled) { writeCoordinate(invoice.r_hash.toString(), coord) + if (order.targetType === 'tip') { getUser() .get('postToTipCount') // CAST: Checked above. .get(/** @type {string} */ (order.ackInfo)) .set(null) // each item in the set is a tip + } else if (order.targetType === 'contentReveal') { + // TODO + } else if (order.targetType === 'spontaneousPayment') { + // no action required + } else if (order.targetType === 'torrentSeed') { + // TODO + } else if (order.targetType === 'other') { + // TODO + } else { + assertNever(order.targetType) } stream.off() From f4e6cb76c19cc2da1c683fd3623d97f351701b2b Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 15:34:42 -0400 Subject: [PATCH 24/34] gun uuid utility --- utils/index.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/utils/index.js b/utils/index.js index 90e80eee..516d762a 100644 --- a/utils/index.js +++ b/utils/index.js @@ -1,9 +1,21 @@ /** * @format */ +const Gun = require('gun') const { asyncFilter } = require('./helpers') -module.exports = { - asyncFilter +/** + * @returns {string} + */ +const gunUUID = () => { + // @ts-expect-error Not typed + const uuid = Gun.Text.random() + + return uuid +} + +module.exports = { + asyncFilter, + gunUUID } From f43982d5413a7903cb6166d7712912ba2a9783d1 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 15:37:20 -0400 Subject: [PATCH 25/34] content reveal order --- services/gunDB/contact-api/jobs/onOrders.js | 90 ++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/services/gunDB/contact-api/jobs/onOrders.js b/services/gunDB/contact-api/jobs/onOrders.js index 8d7a717e..ae048abe 100644 --- a/services/gunDB/contact-api/jobs/onOrders.js +++ b/services/gunDB/contact-api/jobs/onOrders.js @@ -21,6 +21,7 @@ const { const { writeCoordinate } = require('../../../coordinates') const Key = require('../key') const Utils = require('../utils') +const { gunUUID } = require('../../../../utils') const getUser = () => require('../../Mediator').getUser() @@ -220,7 +221,7 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { /** * @param {Common.InvoiceWhenListed} invoice */ - const onData = invoice => { + const onData = async invoice => { if (invoice.settled) { writeCoordinate(invoice.r_hash.toString(), coord) @@ -231,7 +232,92 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { .get(/** @type {string} */ (order.ackInfo)) .set(null) // each item in the set is a tip } else if (order.targetType === 'contentReveal') { - // TODO + // ----------------------------------------- + logger.debug('Content Reveal') + + //assuming digital product that only requires to be unlocked + const postID = order.ackInfo + + if (!Common.isPopulatedString(postID)) { + logger.error(`Invalid post ID`) + logger.error(postID) + return + } + + // TODO: do this reactively + const selectedPost = await new Promise(res => { + getUser() + .get(Key.POSTS_NEW) + .get(postID) + .load(res) + }) + + logger.debug(selectedPost) + + if (Common.isPost(selectedPost)) { + logger.error('Post id provided does not correspond to a valid post') + return + } + + /** + * @type {Record} + */ + const contentsToSend = {} + const mySecret = require('../../Mediator').getMySecret() + logger.debug('SECRET OK') + let privateFound = false + await Common.Utils.asyncForEach( + Object.entries(selectedPost.contentItems), + async ([contentID, item]) => { + if ( + item.type !== 'image/embedded' && + item.type !== 'video/embedded' + ) { + return //only visual content can be private + } + if (!item.isPrivate) { + return + } + privateFound = true + const decrypted = await SEA.decrypt(item.magnetURI, mySecret) + contentsToSend[contentID] = decrypted + } + ) + if (!privateFound) { + logger.error(`Post provided does not contain private content`) + return + } + const ackData = { unlockedContents: contentsToSend } + const toSend = JSON.stringify(ackData) + const encrypted = await SEA.encrypt(toSend, secret) + const ordResponse = { + type: 'orderAck', + response: encrypted + } + logger.debug('RES READY') + + const uuid = gunUUID() + orderResponse.ackNode = uuid + + await /** @type {Promise} */ (new Promise((res, rej) => { + getUser() + .get(Key.ORDER_TO_RESPONSE) + .get(uuid) + .put(ordResponse, ack => { + if (ack.err && typeof ack.err !== 'number') { + rej( + new Error( + `Error saving encrypted orderAck to order to response usergraph: ${ack}` + ) + ) + } else { + res() + } + }) + })) + logger.debug('RES SENT CONTENT') + + // ---------------------------------------------------------------------------------- } else if (order.targetType === 'spontaneousPayment') { // no action required } else if (order.targetType === 'torrentSeed') { From 6b86ab34a32f0dfcdf5e82872642146215fc2b73 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 15:59:38 -0400 Subject: [PATCH 26/34] torrent seed order type --- services/gunDB/contact-api/jobs/onOrders.js | 69 ++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/services/gunDB/contact-api/jobs/onOrders.js b/services/gunDB/contact-api/jobs/onOrders.js index ae048abe..ad757ccc 100644 --- a/services/gunDB/contact-api/jobs/onOrders.js +++ b/services/gunDB/contact-api/jobs/onOrders.js @@ -12,6 +12,8 @@ const { Schema } = Common const { assertNever } = require('assert-never') +const crypto = require('crypto') +const fetch = require('node-fetch') const LightningServices = require('../../../../utils/lightningServices') const { @@ -321,7 +323,72 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => { } else if (order.targetType === 'spontaneousPayment') { // no action required } else if (order.targetType === 'torrentSeed') { - // TODO + logger.debug('TORRENT') + const numberOfTokens = Number(order.ackInfo) + if (isNaN(numberOfTokens)) { + logger.error('ackInfo provided is not a valid number') + return + } + const seedUrl = process.env.TORRENT_SEED_URL + const seedToken = process.env.TORRENT_SEED_TOKEN + if (!seedUrl || !seedToken) { + logger.error('torrentSeed service not available') + return + } + logger.debug('SEED URL OK') + const tokens = Array(numberOfTokens) + for (let i = 0; i < numberOfTokens; i++) { + tokens[i] = crypto.randomBytes(32).toString('hex') + } + /**@param {string} token */ + const enrollToken = async token => { + const reqData = { + seed_token: seedToken, + wallet_token: token + } + // @ts-expect-error TODO + const res = await fetch(`${seedUrl}/api/enroll_token`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(reqData) + }) + if (res.status !== 200) { + throw new Error('torrentSeed service currently not available') + } + } + await Promise.all(tokens.map(enrollToken)) + logger.debug('RES SEED OK') + const ackData = { seedUrl, tokens } + const toSend = JSON.stringify(ackData) + const encrypted = await SEA.encrypt(toSend, secret) + const serviceResponse = { + type: 'orderAck', + response: encrypted + } + console.log('RES SEED SENT') + + const uuid = gunUUID() + orderResponse.ackNode = uuid + + await /** @type {Promise} */ (new Promise((res, rej) => { + getUser() + .get(Key.ORDER_TO_RESPONSE) + .get(uuid) + .put(serviceResponse, ack => { + if (ack.err && typeof ack.err !== 'number') { + rej( + new Error( + `Error saving encrypted orderAck to order to response usergraph: ${ack}` + ) + ) + } else { + res() + } + }) + })) + logger.debug('RES SENT SEED') } else if (order.targetType === 'other') { // TODO } else { From 6bdb660048d5256f8c1e80b4945a753be43b9dc4 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 16:41:31 -0400 Subject: [PATCH 27/34] wire up transaction endpooint --- services/gunDB/contact-api/actions.js | 1 + src/routes.js | 32 +++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/services/gunDB/contact-api/actions.js b/services/gunDB/contact-api/actions.js index 04324207..062f0f24 100644 --- a/services/gunDB/contact-api/actions.js +++ b/services/gunDB/contact-api/actions.js @@ -924,6 +924,7 @@ const sendHRWithInitialMsg = async ( * @typedef {object} SpontPaymentOptions * @prop {Common.Schema.OrderTargetType} type * @prop {string=} postID + * @prop {string=} ackInfo */ /** diff --git a/src/routes.js b/src/routes.js index f61a4857..a79b5eb7 100644 --- a/src/routes.js +++ b/src/routes.js @@ -1192,12 +1192,35 @@ module.exports = async ( app.post('/api/lnd/unifiedTrx', async (req, res) => { try { - const { type, amt, to, memo, feeLimit, postID } = req.body + const { type, amt, to, memo, feeLimit, postID, ackInfo } = req.body - if (type !== 'spont' && type !== 'post') { + if ( + type !== 'spont' && + type !== 'post' && + type !== 'spontaneousPayment' && + type !== 'tip' && + type !== 'torrentSeed' && + type !== 'contentReveal' && + type !== 'other' + ) { return res.status(415).json({ field: 'type', - errorMessage: `Only 'spont' and 'post' payments supported via this endpoint for now.` + errorMessage: `Only 'spontaneousPayment'| 'tip' | 'torrentSeed' | 'contentReveal' | 'other' payments supported via this endpoint for now.` + }) + } + + const typesThatShouldContainAckInfo = [ + 'tip', + 'torrentSeed', + 'contentReveal' + ] + + const shouldContainAckInfo = typesThatShouldContainAckInfo.includes(type) + + if (shouldContainAckInfo && !Common.isPopulatedString(ackInfo)) { + return res.status(400).json({ + field: 'ackInfo', + errorMessage: `Transactions of type ${typesThatShouldContainAckInfo} should contain an ackInfo field.` }) } @@ -1241,7 +1264,8 @@ module.exports = async ( return res.status(200).json( await GunActions.sendSpontaneousPayment(to, amt, memo, feeLimit, { type, - postID + postID, + ackInfo }) ) } catch (e) { From d568f5780ad750f7c8de866e58d472fd06b18203 Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 16:43:19 -0400 Subject: [PATCH 28/34] remove extraneous dep injection --- services/gunDB/contact-api/actions.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/services/gunDB/contact-api/actions.js b/services/gunDB/contact-api/actions.js index 062f0f24..e1fd403b 100644 --- a/services/gunDB/contact-api/actions.js +++ b/services/gunDB/contact-api/actions.js @@ -1294,10 +1294,10 @@ const setLastSeenApp = () => * @param {string[]} tags * @param {string} title * @param {Common.Schema.ContentItem[]} content - * @param {ISEA} SEA * @returns {Promise<[string, Common.Schema.RawPost]>} */ -const createPostNew = async (tags, title, content, SEA) => { +const createPostNew = async (tags, title, content) => { + const SEA = require('../Mediator').mySEA /** @type {Common.Schema.RawPost} */ const newPost = { date: Date.now(), @@ -1434,12 +1434,7 @@ const createPost = async (tags, title, content) => { ) })) - const [postID, newPost] = await createPostNew( - tags, - title, - content, - require('../Mediator').mySEA - ) + const [postID, newPost] = await createPostNew(tags, title, content) await Common.makePromise((res, rej) => { require('../Mediator') From 9b3b85cddc72637b0aff090b2350cba60dc89dae Mon Sep 17 00:00:00 2001 From: Daniel Lugo Date: Mon, 22 Feb 2021 17:19:21 -0400 Subject: [PATCH 29/34] remove unused code --- src/sockets.js | 62 +------------------------------------------------- 1 file changed, 1 insertion(+), 61 deletions(-) diff --git a/src/sockets.js b/src/sockets.js index 54537af8..f1a90196 100644 --- a/src/sockets.js +++ b/src/sockets.js @@ -66,66 +66,6 @@ module.exports = ( } } - const parseJSON = data => { - try { - if (typeof data === 'string') { - return JSON.parse(data) - } - - return data - } catch (err) { - return data - } - } - - const decryptEvent = ({ eventName, data, socket }) => { - try { - const deviceId = socket.handshake.query['x-shockwallet-device-id'] - if (Encryption.isNonEncrypted(eventName)) { - return data - } - - if (!data) { - return data - } - - const parsedData = parseJSON(data) - - if (!deviceId) { - throw { - field: 'deviceId', - message: 'Please specify a device ID' - } - } - - if (!Encryption.isAuthorizedDevice({ deviceId })) { - throw { - field: 'deviceId', - message: 'Please exchange keys with the API before using the socket' - } - } - - const decryptedKey = Encryption.decryptKey({ - deviceId, - message: parsedData.encryptedKey - }) - const decryptedMessage = Encryption.decryptMessage({ - message: parsedData.encryptedData, - key: decryptedKey, - iv: parsedData.iv - }) - const decryptedData = JSON.parse(decryptedMessage) - return decryptedData - } catch (err) { - logger.error( - `[SOCKET] An error has occurred while decrypting an event (${eventName}):`, - err - ) - - return socket.emit('encryption:error', err) - } - } - const onNewInvoice = (socket, subID) => { const { lightning } = LightningServices.services logger.warn('Subscribing to invoices socket...' + subID) @@ -677,7 +617,7 @@ module.exports = ( } /** - * @param {Common.Schema.SimpleReceivedRequest[]} receivedReqs + * @param {ReadonlyArray} receivedReqs */ const onReceivedReqs = receivedReqs => { const processed = receivedReqs.map(({ id, requestorPK, timestamp }) => { From 2a71fb4bb2164b902789a53fa269420080128ea7 Mon Sep 17 00:00:00 2001 From: CapDog <34176400+capitalistdog@users.noreply.github.com> Date: Tue, 23 Feb 2021 11:16:23 -0500 Subject: [PATCH 30/34] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c7dcc9c1..c3cde0d8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

ShockAPI

-![GitHub last commit](https://img.shields.io/github/last-commit/shocknet/wallet?style=flat-square) +![GitHub last commit](https://img.shields.io/github/last-commit/shocknet/api?style=flat-square) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![Chat](https://img.shields.io/badge/chat-on%20Telegram-blue?style=flat-square)](https://t.me/Shockwallet) [![Twitter Follow](https://img.shields.io/twitter/follow/ShockBTC?style=flat-square)](https://twitter.com/shockbtc) From 2acefa21d028342a902506065298475f63b5e09c Mon Sep 17 00:00:00 2001 From: hatim boufnichel Date: Fri, 26 Feb 2021 16:47:55 +0100 Subject: [PATCH 31/34] fixies --- config/defaults.js | 2 +- package.json | 2 +- yarn.lock | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/config/defaults.js b/config/defaults.js index 684bfcdb..7341dd50 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -49,6 +49,6 @@ module.exports = (mainnet = false) => { peers: ['https://gun.shock.network:8765/gun'], useTLS: false, tokenExpirationMS: 259200000, - localtunnelHost:'http://tunnel.example.com' + localtunnelHost:'https://tunnel.rip' }; }; diff --git a/package.json b/package.json index cd5ab657..24409ce2 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "lodash": "^4.17.20", "method-override": "^2.3.7", "node-persist": "^3.1.0", - "promise": "^8.0.1", + "promise": "^8.1.0", "qrcode-terminal": "^0.12.0", "ramda": "^0.27.1", "request": "^2.88.2", diff --git a/yarn.lock b/yarn.lock index 66c0a700..5e7e8649 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2890,6 +2890,25 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +gaxios@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-4.0.1.tgz#bc7b205a89d883452822cc75e138620c35e3291e" + integrity sha512-jOin8xRZ/UytQeBpSXFqIzqU7Fi5TqgPNLlUsSB8kjJ76+FiGBfImF8KJu++c6J4jOldfJUtt0YmkRj2ZpSHTQ== + dependencies: + abort-controller "^3.0.0" + extend "^3.0.2" + https-proxy-agent "^5.0.0" + is-stream "^2.0.0" + node-fetch "^2.3.0" + +gcp-metadata@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.2.1.tgz#31849fbcf9025ef34c2297c32a89a1e7e9f2cd62" + integrity sha512-tSk+REe5iq/N+K+SK1XjZJUrFPuDqGZVzCy2vocIHIGmPlTGsa8owXMJwGkrXr73NO0AzhPW4MF2DEHz7P2AVw== + dependencies: + gaxios "^4.0.0" + json-bigint "^1.0.0" + get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" From c543a6d74bd37d6bbe8b7329eb232be93027adfd Mon Sep 17 00:00:00 2001 From: hatim boufnichel Date: Fri, 26 Feb 2021 16:53:25 +0100 Subject: [PATCH 32/34] yarn fix --- yarn.lock | 5 ----- 1 file changed, 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index a66b0444..4fbe3b46 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3039,11 +3039,6 @@ gcp-metadata@^4.2.0: gaxios "^4.0.0" json-bigint "^1.0.0" -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" From e77b878fede09c572bc67db4676c37ae2254bdcb Mon Sep 17 00:00:00 2001 From: hatim boufnichel Date: Fri, 26 Feb 2021 16:57:24 +0100 Subject: [PATCH 33/34] syntax fix --- services/coordinates.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/coordinates.js b/services/coordinates.js index ac212256..d56981bb 100644 --- a/services/coordinates.js +++ b/services/coordinates.js @@ -16,7 +16,7 @@ const { getUser, getMySecret, mySEA } = require('./gunDB/Mediator') * @param {Common.Coordinate} data * @returns {Promise} */ -export const writeCoordinate = async (coordID, data) => { +module.exports.writeCoordinate = async (coordID, data) => { if (coordID !== data.id) { throw new Error('CoordID must be equal to data.id') } From 6d17564b3a921ad6e761dd115fcbba990de5cecd Mon Sep 17 00:00:00 2001 From: hatim boufnichel Date: Fri, 26 Feb 2021 17:09:57 +0100 Subject: [PATCH 34/34] close tunnel before a restart --- src/server.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/server.js b/src/server.js index c64f2913..02f7c033 100644 --- a/src/server.js +++ b/src/server.js @@ -161,6 +161,10 @@ const server = program => { // eslint-disable-next-line consistent-return const startServer = async () => { + /** + * @type {localtunnel.Tunnel} + */ + let tunnelRef = null try { LightningServices.setDefaults(program) if (!LightningServices.isInitialized()) { @@ -239,6 +243,7 @@ const server = program => { logger.info('Creating new tunnel... ') } const tunnel = await localtunnel(tunnelOpts) + tunnelRef = tunnel logger.info('Tunnel created! connect to: ' + tunnel.url) const dataToQr = JSON.stringify({ internalIP: tunnel.url, @@ -362,6 +367,9 @@ const server = program => { } catch (err) { logger.error({ exception: err, message: err.message, code: err.code }) logger.info('Restarting server in 30 seconds...') + if (tunnelRef) { + tunnelRef.close() + } await wait(30) startServer() return false