From 3e3b1e9a03d1dfcba0ca47e8142e53de0cf005d0 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Fri, 20 Sep 2019 13:09:44 +0300 Subject: [PATCH] feat: add proposal processing #21 --- .env.example | 1 + .prettierrc | 15 ++ README.md | 4 +- package-lock.json | 92 +++++----- package.json | 36 +--- src/Main.js | 3 +- src/controllers/BandwidthProvider.js | 243 +++++++++++++++++++++++---- src/data/env.js | 9 +- src/model/Proposal.js | 55 ++++++ src/services/Connector.js | 17 ++ 10 files changed, 363 insertions(+), 112 deletions(-) create mode 100644 .prettierrc create mode 100644 src/model/Proposal.js diff --git a/.env.example b/.env.example index 40bb6e3..e232694 100644 --- a/.env.example +++ b/.env.example @@ -5,6 +5,7 @@ GLS_CYBERWAY_HTTP_URL= GLS_PROVIDER_PUBLIC_KEY= GLS_PROVIDER_WIF= GLS_PROVIDER_USERNAME= +GLS_PRISM_CONNECT= GLS_REGISTRATION_CONNECT= GLS_CHANNEL_TTL= GLS_STORAGE_CLEANUP_TIMEOUT= diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..a3a5bb6 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,15 @@ +{ + "singleQuote": true, + "tabWidth": 4, + "semi": true, + "trailingComma": "es5", + "printWidth": 100, + "overrides": [ + { + "files": ["*.yml", "*.json", ".prettierrc"], + "options": { + "tabWidth": 2 + } + } + ] +} diff --git a/README.md b/README.md index ca21de9..1f05f36 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,9 @@ - `GLS_PROVIDER_USERNAME` _(обязательно)_ - имя пользователя провайдера бендвича -- `GLS_REGISTRATION_CONNECT` _(обязательно)_ - ссылка на подключение к сервису регистрации +- `GLS_PRISM_CONNECT` _(обязательно)_ - ссылка для подключения к сервису призма + +- `GLS_REGISTRATION_CONNECT` _(обязательно)_ - ссылка для подключения к сервису регистрации - `GLS_CHANNEL_TTL` _(обязательно)_ - время жизни канала (время, которое будет хранится channelId в базе данных в памяти). **Важно:** \_storage проверяет, не превышено ли это значение лишь раз в определенное время, поэтому между тем, как данный лимит будет превышен, и тем, как канал будет фактически удален из памяти, может пройти существенное количество времени diff --git a/package-lock.json b/package-lock.json index 1f5e0ca..5d2a23f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ }, "@types/text-encoding": { "version": "0.0.35", - "resolved": "https://registry.npmjs.org/@types/text-encoding/-/text-encoding-0.0.35.tgz", + "resolved": "http://159.69.117.25:4873/@types%2ftext-encoding/-/text-encoding-0.0.35.tgz", "integrity": "sha512-jfo/A88XIiAweUa8np+1mPbm3h2w0s425YrI8t3wk5QxhH6UI7w517MboNVnGDeMSuoFwA8Rwmklno+FicvV4g==" }, "@types/ws": { @@ -62,7 +62,7 @@ }, "ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "resolved": "http://159.69.117.25:4873/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { "color-convert": "^1.9.0" @@ -75,12 +75,12 @@ }, "array-uniq": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "resolved": "http://159.69.117.25:4873/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" }, "async": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "resolved": "http://159.69.117.25:4873/async/-/async-2.6.2.tgz", "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "requires": { "lodash": "^4.17.11" @@ -103,7 +103,7 @@ }, "babel-runtime": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "resolved": "http://159.69.117.25:4873/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "requires": { "core-js": "^2.4.0", @@ -112,7 +112,7 @@ "dependencies": { "regenerator-runtime": { "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "resolved": "http://159.69.117.25:4873/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" } } @@ -185,7 +185,7 @@ }, "bson": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.1.tgz", + "resolved": "http://159.69.117.25:4873/bson/-/bson-1.1.1.tgz", "integrity": "sha512-jCGVYLoYMHDkOsbwJZBCqwMHyH4c+wzgI9hG7Z6SZJRXWr+x58pdIbm2i9a/jFGCkRJqRUr8eoI7lDWa0hTkxg==" }, "buffer-xor": { @@ -208,7 +208,7 @@ }, "chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "resolved": "http://159.69.117.25:4873/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { "ansi-styles": "^3.2.1", @@ -227,7 +227,7 @@ }, "color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "resolved": "http://159.69.117.25:4873/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "requires": { "color-name": "1.1.3" @@ -235,7 +235,7 @@ }, "color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "resolved": "http://159.69.117.25:4873/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colors": { @@ -364,12 +364,12 @@ }, "domelementtype": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "resolved": "http://159.69.117.25:4873/domelementtype/-/domelementtype-1.3.1.tgz", "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" }, "domhandler": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "resolved": "http://159.69.117.25:4873/domhandler/-/domhandler-2.4.2.tgz", "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", "requires": { "domelementtype": "1" @@ -377,7 +377,7 @@ }, "domutils": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "resolved": "http://159.69.117.25:4873/domutils/-/domutils-1.7.0.tgz", "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", "requires": { "dom-serializer": "0", @@ -405,12 +405,12 @@ }, "entities": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "resolved": "http://159.69.117.25:4873/entities/-/entities-1.1.2.tgz", "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" }, "eosjs-ecc": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/eosjs-ecc/-/eosjs-ecc-4.0.4.tgz", + "resolved": "http://159.69.117.25:4873/eosjs-ecc/-/eosjs-ecc-4.0.4.tgz", "integrity": "sha512-9wAYefts4TidHOu+eN9nAisZdWpUzlUimZrB63oP7+/s4xRNJEn2Vvep2ICRODpxpidbshM1L7WaSYW9oiV5gA==", "requires": { "bigi": "^1.4.2", @@ -443,7 +443,7 @@ }, "escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "resolved": "http://159.69.117.25:4873/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "etag": { @@ -511,12 +511,12 @@ }, "fast-deep-equal": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "resolved": "http://159.69.117.25:4873/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, "fast-json-stable-stringify": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "resolved": "http://159.69.117.25:4873/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "finalhandler": { @@ -586,7 +586,7 @@ }, "has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "resolved": "http://159.69.117.25:4873/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "hash-base": { @@ -600,7 +600,7 @@ }, "htmlparser2": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "resolved": "http://159.69.117.25:4873/htmlparser2/-/htmlparser2-3.10.1.tgz", "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", "requires": { "domelementtype": "^1.3.1", @@ -672,7 +672,7 @@ }, "json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "resolved": "http://159.69.117.25:4873/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stringify-safe": { @@ -702,22 +702,22 @@ }, "lodash.clonedeep": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "resolved": "http://159.69.117.25:4873/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" }, "lodash.escaperegexp": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "resolved": "http://159.69.117.25:4873/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" }, "lodash.isplainobject": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "resolved": "http://159.69.117.25:4873/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" }, "lodash.isstring": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "resolved": "http://159.69.117.25:4873/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" }, "lodash.mergewith": { @@ -860,7 +860,7 @@ }, "mpath": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.6.0.tgz", + "resolved": "http://159.69.117.25:4873/mpath/-/mpath-0.6.0.tgz", "integrity": "sha512-i75qh79MJ5Xo/sbhxrDrPSEG0H/mr1kcZXJ8dH6URU5jD/knFxCVqVC/gVSW7GIXL/9hHWlT9haLbCXWOll3qw==" }, "mquery": { @@ -931,12 +931,12 @@ }, "nuid": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nuid/-/nuid-1.1.0.tgz", + "resolved": "http://159.69.117.25:4873/nuid/-/nuid-1.1.0.tgz", "integrity": "sha512-C/JdZ6PtCqKsCEs4ni76nhBsdmuQgLAT/CTLNprkcLViDAnkk7qx5sSA8PVC2vmSsdBlSsFuGb52v6pwn1oaeg==" }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "resolved": "http://159.69.117.25:4873/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "on-finished": { @@ -949,12 +949,12 @@ }, "ow": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/ow/-/ow-0.4.0.tgz", + "resolved": "http://159.69.117.25:4873/ow/-/ow-0.4.0.tgz", "integrity": "sha512-kJNzxUgVd6EF5LoGs+s2/etJPwjfRDLXPTCfEgV8At77sRrV+PSFA8lcoW2HF15Qd455mIR2Stee/2MzDiFBDA==" }, "ow-lite": { "version": "0.0.2", - "resolved": "https://registry.npmjs.org/ow-lite/-/ow-lite-0.0.2.tgz", + "resolved": "http://159.69.117.25:4873/ow-lite/-/ow-lite-0.0.2.tgz", "integrity": "sha1-359QDmdAtlkKHpqWVzDUmo61l9E=" }, "parseurl": { @@ -979,7 +979,7 @@ "dependencies": { "supports-color": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "resolved": "http://159.69.117.25:4873/supports-color/-/supports-color-6.1.0.tgz", "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "requires": { "has-flag": "^3.0.0" @@ -1012,7 +1012,7 @@ }, "punycode": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "resolved": "http://159.69.117.25:4873/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "qs": { @@ -1022,7 +1022,7 @@ }, "random": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/random/-/random-2.1.1.tgz", + "resolved": "http://159.69.117.25:4873/random/-/random-2.1.1.tgz", "integrity": "sha512-8HQriGPwjc8R+7hPOI9ZphAEEWmIt/RmuqXZ682ww9kjK5HRGXcN7hgWUxZ9AabgjZm5wIa6EwapTI1sg11XXg==", "requires": { "babel-runtime": "^6.26.0", @@ -1033,7 +1033,7 @@ }, "randombytes": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "resolved": "http://159.69.117.25:4873/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "requires": { "safe-buffer": "^5.1.0" @@ -1110,7 +1110,7 @@ }, "sanitize-html": { "version": "1.20.1", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.20.1.tgz", + "resolved": "http://159.69.117.25:4873/sanitize-html/-/sanitize-html-1.20.1.tgz", "integrity": "sha512-txnH8TQjaQvg2Q0HY06G6CDJLVYCpbnxrdO0WN8gjCKaU5J0KbyGYhZxx5QJg3WLZ1lB7XU9kDkfrCXUozqptA==", "requires": { "chalk": "^2.4.1", @@ -1127,7 +1127,7 @@ }, "saslprep": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "resolved": "http://159.69.117.25:4873/saslprep/-/saslprep-1.0.3.tgz", "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", "optional": true, "requires": { @@ -1136,7 +1136,7 @@ }, "seedrandom": { "version": "2.4.4", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.4.tgz", + "resolved": "http://159.69.117.25:4873/seedrandom/-/seedrandom-2.4.4.tgz", "integrity": "sha512-9A+PDmgm+2du77B5i0Ip2cxOqqHjgNxnBgglxLcX78A2D6c2rTo61z4jnVABpF4cKeDMDG+cmXXvdnqse2VqMA==" }, "semver": { @@ -1198,7 +1198,7 @@ }, "sift": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz", + "resolved": "http://159.69.117.25:4873/sift/-/sift-7.0.1.tgz", "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==" }, "sliced": { @@ -1208,7 +1208,7 @@ }, "source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "resolved": "http://159.69.117.25:4873/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "sparse-bitfield": { @@ -1222,7 +1222,7 @@ }, "srcset": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/srcset/-/srcset-1.0.0.tgz", + "resolved": "http://159.69.117.25:4873/srcset/-/srcset-1.0.0.tgz", "integrity": "sha1-pWad4StC87HV6D7QPHEEb8SPQe8=", "requires": { "array-uniq": "^1.0.2", @@ -1244,7 +1244,7 @@ }, "supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "resolved": "http://159.69.117.25:4873/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "requires": { "has-flag": "^3.0.0" @@ -1260,7 +1260,7 @@ }, "text-encoding": { "version": "0.7.0", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz", + "resolved": "http://159.69.117.25:4873/text-encoding/-/text-encoding-0.7.0.tgz", "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==" }, "then-sleep": { @@ -1283,7 +1283,7 @@ }, "ts-nkeys": { "version": "1.0.12", - "resolved": "https://registry.npmjs.org/ts-nkeys/-/ts-nkeys-1.0.12.tgz", + "resolved": "http://159.69.117.25:4873/ts-nkeys/-/ts-nkeys-1.0.12.tgz", "integrity": "sha512-5TgA+wbfxTy/9pdSuAhvneuL65KKoI7phonzNQH2UhnorAQAWehUwHNLEuli596wu/Fxh0SAhMeKZVLNx4s7Ow==", "requires": { "tweetnacl": "^1.0.1" @@ -1291,7 +1291,7 @@ }, "tweetnacl": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.1.tgz", + "resolved": "http://159.69.117.25:4873/tweetnacl/-/tweetnacl-1.0.1.tgz", "integrity": "sha512-kcoMoKTPYnoeS50tzoqjPY3Uv9axeuuFAZY9M/9zFnhoVvRfxz9K29IMPD7jGmt2c8SW7i3gT9WqDl2+nV7p4A==" }, "type-is": { @@ -1310,7 +1310,7 @@ }, "uri-js": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "resolved": "http://159.69.117.25:4873/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "requires": { "punycode": "^2.1.0" @@ -1318,7 +1318,7 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "resolved": "http://159.69.117.25:4873/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { diff --git a/package.json b/package.json index 5bdd793..1e67158 100644 --- a/package.json +++ b/package.json @@ -1,39 +1,13 @@ { "name": "badwidth-service", "version": "1.0.0", - "description": "", + "description": "Bandwidth provider service", "main": "./src/Main.js", "scripts": { "start": "node src/index.js" }, "author": "golos.io", "license": "GPL-3.0", - "dependencies": { - "@types/node-fetch": "^2.1.4", - "@types/text-encoding": "0.0.35", - "cyberwayjs": "^20.0.0-beta7", - "gls-core-service": "^3.25.2", - "node-fetch": "^2.3.0", - "text-encoding": "^0.7.0" - }, - "prettier": { - "singleQuote": true, - "tabWidth": 4, - "semi": true, - "trailingComma": "es5", - "printWidth": 100, - "overrides": [ - { - "files": [ - "*.yml", - "*.json" - ], - "options": { - "tabWidth": 2 - } - } - ] - }, "repository": { "type": "git", "url": "git+https://github.com/GolosChain/bandwidth-service.git" @@ -42,6 +16,14 @@ "url": "https://github.com/GolosChain/bandwidth-service/issues" }, "homepage": "https://github.com/GolosChain/bandwidth-service#readme", + "dependencies": { + "@types/node-fetch": "^2.1.4", + "@types/text-encoding": "0.0.35", + "cyberwayjs": "^20.0.0-beta7", + "gls-core-service": "^3.25.2", + "node-fetch": "^2.3.0", + "text-encoding": "^0.7.0" + }, "devDependencies": { "@types/ws": "^6.0.1", "jayson": "^2.1.1", diff --git a/src/Main.js b/src/Main.js index d210ee5..d2d2966 100644 --- a/src/Main.js +++ b/src/Main.js @@ -1,5 +1,4 @@ const core = require('gls-core-service'); -const stats = core.utils.statsClient; const BasicMain = core.services.BasicMain; const env = require('./data/env'); const Connector = require('./services/Connector'); @@ -7,7 +6,7 @@ const MongoDB = core.services.MongoDB; class Main extends BasicMain { constructor() { - super(stats, env); + super(env); this.addNested(new Connector(), new MongoDB()); } } diff --git a/src/controllers/BandwidthProvider.js b/src/controllers/BandwidthProvider.js index 53e6511..77e06e2 100644 --- a/src/controllers/BandwidthProvider.js +++ b/src/controllers/BandwidthProvider.js @@ -7,6 +7,7 @@ const BasicController = core.controllers.Basic; const Logger = core.utils.Logger; const env = require('../data/env'); const Log = require('../utils/Log'); +const ProposalModel = require('../model/Proposal'); const { GLS_PROVIDER_WIF, GLS_PROVIDER_PUBLIC_KEY, @@ -14,6 +15,8 @@ const { GLS_CYBERWAY_HTTP_URL, } = env; +const PROPOSAL_ALLOWED_CONTRACTS = ['gls.vesting::delegate']; + const rpc = new JsonRpc(GLS_CYBERWAY_HTTP_URL, { fetch }); const requiredKeys = [GLS_PROVIDER_PUBLIC_KEY]; @@ -27,8 +30,8 @@ const api = new Api({ }); class BandwidthProvider extends BasicController { - constructor({ whitelist }) { - super(); + constructor({ connector, whitelist }) { + super({ connector }); this._whitelist = whitelist; this._logger = new Log(); @@ -40,50 +43,56 @@ class BandwidthProvider extends BasicController { params: { transaction, chainId }, }) { try { - const rawTrx = this._parseTransaction(transaction); + const rawTrx = this._decodeTransaction(transaction); const trx = await this._deserializeTransaction(rawTrx); - const isNeedSign = this._isNeedSigning(trx); + const isNeedProviding = this._verifyActionsAndCheckIsNeedProviding(trx); let finalTrx = rawTrx; - if (isNeedSign) { + if (isNeedProviding) { await this._checkWhitelist({ user, channelId }); finalTrx = await this._signTransaction(rawTrx, { chainId }); } - this._logEntry({ user, transaction: trx, isSigned: isNeedSign }); + this._logEntry({ user, transaction: trx, isSigned: isNeedProviding }); return await this._sendTransaction(finalTrx); - } catch (error) { - if (error.json && error.json.error) { - throw { - code: 1003, - message: 'Unexpected blockchain error', - data: error.json - }; - } + } catch (err) { + this._processTransactionPushError(err); + } + } + _processTransactionPushError(err) { + if (err.json && err.json.error) { throw { - code: 500, - message: 'Failed to transact -- ' + error, + code: 1003, + message: 'Unexpected blockchain error', + data: err.json, }; } + + throw { + code: 500, + message: 'Failed to transact -- ' + err, + }; } - _parseTransaction(transaction) { - let uint8array = null; + _decodeTransaction(transaction) { + return { + ...transaction, + serializedTransaction: this._decodeSerializedTransaction( + transaction.serializedTransaction + ), + }; + } + _decodeSerializedTransaction(serializedTransaction) { try { - uint8array = Serialize.hexToUint8Array(transaction.serializedTransaction); + return Serialize.hexToUint8Array(serializedTransaction); } catch (error) { Logger.error('Conversion hexToUint8Array failed:', error); throw error; } - - return { - ...transaction, - serializedTransaction: uint8array, - }; } async _deserializeTransaction({ serializedTransaction }) { @@ -95,16 +104,19 @@ class BandwidthProvider extends BasicController { } } - _isNeedSigning({ actions }) { - const provideBwAction = actions.find( - ({ account, name, authorization, data }) => - account === 'cyber' && - name === 'providebw' && - authorization.length === 1 && - authorization[0].actor === GLS_PROVIDER_USERNAME && - authorization[0].permission === 'providebw' && - data.provider === GLS_PROVIDER_USERNAME + _isBWProvideAction({ account, name, authorization, data }) { + return ( + account === 'cyber' && + name === 'providebw' && + authorization.length === 1 && + authorization[0].actor === GLS_PROVIDER_USERNAME && + authorization[0].permission === 'providebw' && + data.provider === GLS_PROVIDER_USERNAME ); + } + + _verifyActionsAndCheckIsNeedProviding({ actions }) { + const provideBwAction = actions.find(this._isBWProvideAction); if (!provideBwAction) { return false; @@ -189,6 +201,171 @@ class BandwidthProvider extends BasicController { throw error; } } + + async createProposal({ + routing: { channelId }, + auth: { user }, + params: { transaction, chainId }, + }) { + const rawTrx = this._decodeTransaction(transaction); + const trx = await this._deserializeTransaction(rawTrx); + + const isNeedProviding = this._verifyActionsAndCheckIsNeedProviding(trx); + + const { action, auth } = this._checkProposalRestrictionsAndGetAction(trx, user); + + let finalTrx = rawTrx; + + if (isNeedProviding) { + await this._checkWhitelist({ user, channelId }); + finalTrx = await this._signTransaction(rawTrx, { chainId }); + } + + const proposal = await ProposalModel.create({ + initiatorId: user, + waitingFor: { + userId: auth.actor, + permission: auth.permission, + }, + expirationTime: new Date(Date.now() + 3600000), + action: JSON.stringify(action), + serializedTransaction: transaction.serializedTransaction, + signatures: finalTrx.signatures, + }); + + return { + proposalId: proposal._id, + }; + } + + _checkProposalRestrictionsAndGetAction({ actions }, user) { + let targetActions = actions.filter(this._isBWProvideAction); + + if (targetActions.length !== 1) { + throw { + code: 1134, + message: + targetActions.length === 0 + ? 'No action for providing' + : 'Allowed only one action for providing', + }; + } + + const [targetAction] = targetActions; + + const contractMethod = `${targetAction.code}::${targetAction.action}`; + + if (!PROPOSAL_ALLOWED_CONTRACTS.includes(contractMethod)) { + throw { + code: 1135, + message: `Contract method '${contractMethod}' is not allowed for creating proposal`, + }; + } + + const needAuthFor = targetAction.authorization.filter(auth => auth.actor !== user); + + if (needAuthFor.length !== 1) { + throw { + code: 1136, + message: + needAuthFor.length === 0 + ? 'List of awaiting signs is empty' + : 'Proposal have more than one awaiting signs', + }; + } + + return { + action: targetAction, + auth: needAuthFor[0], + }; + } + + async getProposals({ auth: { user } }) { + const items = await ProposalModel.find( + { + 'waitingFor.userId': user, + expirationTime: { + $gt: new Date(), + }, + }, + { + _id: true, + initiatorId: true, + action: true, + serializedTransaction: true, + expirationTime: true, + }, + { + lean: true, + } + ); + + const { usernames } = await this.callService('prism', 'getUsernames', { + userIds: items.map(({ initiatorId }) => initiatorId), + }); + + for (const item of items) { + item.id = item._id; + item._id = undefined; + item.initiatorUsername = usernames[item.initiatorId]; + } + + return { + items, + }; + } + + async signAndExecuteProposal({ auth: { user }, params: { proposalId, signature } }) { + const proposal = await ProposalModel.findOne( + { + _id: proposalId, + 'waitingFor.userId': user, + }, + { + serializedTransaction: true, + signatures: true, + }, + { + lean: true, + } + ); + + if (!proposal) { + throw { + code: 404, + message: 'Proposal not found', + }; + } + + const signatures = proposal.signatures; + + if (!signatures.includes(signature)) { + signatures.push(signature); + } + + const serializedTransaction = this._decodeSerializedTransaction( + proposal.serializedTransaction + ); + + try { + const results = await api.pushSignedTransaction({ + signatures, + serializedTransaction, + }); + + try { + await ProposalModel.deleteOne({ + _id: proposalId, + }); + } catch (err) { + Logger.error('Proposal deleting failed:', err); + } + + return results; + } catch (err) { + this._processTransactionPushError(err); + } + } } module.exports = BandwidthProvider; diff --git a/src/data/env.js b/src/data/env.js index 92740bc..a27d5d1 100644 --- a/src/data/env.js +++ b/src/data/env.js @@ -1,3 +1,5 @@ +const core = require('gls-core-service'); + const env = process.env; if (!env.GLS_PROVIDER_WIF) { @@ -11,15 +13,16 @@ if (!env.GLS_PROVIDER_USERNAME) { if (!env.GLS_CYBERWAY_HTTP_URL) { throw new Error('Env variable GLS_CYBERWAY_HTTP_URL is required!'); } + module.exports = { - GLS_CONNECTOR_HOST: env.GLS_CONNECTOR_HOST || '127.0.0.0', - GLS_CONNECTOR_PORT: env.GLS_CONNECTOR_PORT || 3000, + ...core.data.env, GLS_PROVIDER_WIF: env.GLS_PROVIDER_WIF, GLS_PROVIDER_USERNAME: env.GLS_PROVIDER_USERNAME, GLS_PROVIDER_PUBLIC_KEY: env.GLS_PROVIDER_PUBLIC_KEY, + GLS_PRISM_CONNECT: env.GLS_PRISM_CONNECT, + GLS_REGISTRATION_CONNECT: env.GLS_REGISTRATION_CONNECT, GLS_CHANNEL_TTL: env.GLS_CHANNEL_TTL || 1000, GLS_CYBERWAY_HTTP_URL: env.GLS_CYBERWAY_HTTP_URL, - GLS_REGISTRATION_CONNECT: env.GLS_REGISTRATION_CONNECT, GLS_STORAGE_CLEANUP_TIMEOUT: env.GLS_STORAGE_CLEANUP_TIMEOUT || 1000 * 60 * 60, GLS_REGISTRATION_ENABLED: env.GLS_REGISTRATION_ENABLED === 'true', }; diff --git a/src/model/Proposal.js b/src/model/Proposal.js new file mode 100644 index 0000000..0224654 --- /dev/null +++ b/src/model/Proposal.js @@ -0,0 +1,55 @@ +const core = require('gls-core-service'); +const MongoDB = core.services.MongoDB; + +module.exports = MongoDB.makeModel( + 'Proposal', + { + initiatorId: { + type: String, + required: true, + }, + waitingFor: { + type: { + userId: { + type: String, + required: true, + }, + permission: { + type: String, + required: true, + }, + }, + }, + action: { + type: String, + required: true, + }, + serializedTransaction: { + type: String, + required: true, + }, + signatures: [ + { + type: String, + }, + ], + expirationTime: { + type: Date, + required: true, + }, + }, + { + index: [ + { + fields: { + 'waitingFor.userId': 1, + }, + }, + { + fields: { + expirationTime: 1, + }, + }, + ], + } +); diff --git a/src/services/Connector.js b/src/services/Connector.js index cbcca0a..4b47f6d 100644 --- a/src/services/Connector.js +++ b/src/services/Connector.js @@ -8,13 +8,17 @@ const env = require('../data/env'); class Connector extends BasicConnector { constructor() { super(); + this._storageService = new StorageService(); this.addNested(this._storageService); + this._whitelistController = new Whitelist({ connector: this, storage: this._storageService, }); + this._bandwidthProvider = new BandwidthProvider({ + connector: this, whitelist: this._whitelistController, }); } @@ -29,6 +33,18 @@ class Connector extends BasicConnector { handler: provider.provideBandwidth, scope: provider, }, + 'bandwidth.createProposal': { + handler: provider.createProposal, + scope: provider, + }, + 'bandwidth.getProposals': { + handler: provider.getProposals, + scope: provider, + }, + 'bandwidth.signAndExecuteProposal': { + handler: provider.signAndExecuteProposal, + scope: provider, + }, 'bandwidth.banUser': { handler: whitelist.banUser, scope: whitelist, @@ -39,6 +55,7 @@ class Connector extends BasicConnector { }, }, requiredClients: { + prism: env.GLS_PRISM_CONNECT, registration: env.GLS_REGISTRATION_CONNECT, }, });