diff --git a/.gitignore b/.gitignore index 476f8843c..df2de66a2 100644 --- a/.gitignore +++ b/.gitignore @@ -62,3 +62,6 @@ typings/ # backend ignores backend/db + +# frontend ignores +frontend/cypress/videos diff --git a/backend/Dockerfile b/backend/Dockerfile index 2a4602955..e85748337 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -14,4 +14,4 @@ RUN mkdir ./db && \ chown -R nobody: . USER nobody -CMD ["/bin/sh", "-c", "exec npm run start"] +CMD ["/bin/sh", "-c", "if stat -t .env-* >/dev/null 2>&1 ; then for env in .env-*; do source \"$env\" && npm run start & done ; wait ; else exec npm run start ; fi"] diff --git a/backend/config/config.json b/backend/config/config.json deleted file mode 100644 index fff37c625..000000000 --- a/backend/config/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "development": { - "dialect": "sqlite", - "storage": "db/development-database.sqlite" - }, - "test": { - "dialect": "sqlite", - "storage": "db/test-database.sqlite" - }, - "production": { - "dialect": "sqlite", - "storage": "db/production-database.sqlite" - } -} diff --git a/backend/config/database.js b/backend/config/database.js new file mode 100644 index 000000000..fce26057f --- /dev/null +++ b/backend/config/database.js @@ -0,0 +1,17 @@ +const dbPrefix = + process.env.NEAR_DB_PREFIX || process.env.WAMP_NEAR_NETWORK_NAME; + +module.exports = { + development: { + dialect: "sqlite", + storage: `db/${dbPrefix || "development"}-database.sqlite` + }, + test: { + dialect: "sqlite", + storage: `db/${dbPrefix || "test"}-database.sqlite` + }, + production: { + dialect: "sqlite", + storage: `db/${dbPrefix || "production"}-database.sqlite` + } +}; diff --git a/backend/models/index.js b/backend/models/index.js index 62986a2ab..fb406b20e 100644 --- a/backend/models/index.js +++ b/backend/models/index.js @@ -5,7 +5,7 @@ const path = require("path"); const Sequelize = require("sequelize"); const basename = path.basename(__filename); const env = process.env.NODE_ENV || "development"; -const config = require(__dirname + "/../config/config.json")[env]; +const config = require(__dirname + "/../config/database")[env]; const db = {}; const sequelize = new Sequelize( diff --git a/backend/package-lock.json b/backend/package-lock.json index e78898b54..6fbae0cf9 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -4,24 +4,6 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, "@types/bn.js": { "version": "4.11.5", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.5.tgz", @@ -31,9 +13,9 @@ } }, "@types/node": { - "version": "12.6.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.7.tgz", - "integrity": "sha512-Dagl2ASgoIeJCD/HWqgAPIZABYQdNHIUg11wz7JpvXSj0pUlP2ASBNvPp3J14Wmw3PS/NcFFtU1BkdFtz83qvA==" + "version": "12.11.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.11.7.tgz", + "integrity": "sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==" }, "abbrev": { "version": "1.1.1", @@ -41,9 +23,9 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", @@ -56,14 +38,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -83,14 +57,6 @@ "readable-stream": "^2.0.6" } }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - } - }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -105,9 +71,9 @@ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, "asynckit": { "version": "0.4.0", @@ -140,25 +106,15 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base-x": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.6.tgz", - "integrity": "sha512-4PaF8u2+AlViJxRVjurkLTxpp7CaFRD/jo5rPT9ONnKxyhQ8f59yzamEvq7EkriG56yn5On4ONyaG75HLqr46w==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.7.tgz", + "integrity": "sha512-zAKJGuQPihXW22fkrfOclUUZXM2g92z5GzlSMHxhO6r6Qj+Nm0ccaGNBzDZojzwOMkpjAv4J0fOv1U4go+a4iw==", "requires": { "safe-buffer": "^5.0.1" } @@ -186,14 +142,14 @@ } }, "bluebird": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", - "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==" + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", + "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==" }, "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.0.0.tgz", + "integrity": "sha512-bVwDX8AF+72fIUNuARelKAlQUNtPOfG2fRxorbVvFk4zpHbqLrPdOGfVg5vrKwVzLLePqPBiATaOZNELQzmS0A==" }, "brace-expansion": { "version": "1.1.11", @@ -221,17 +177,6 @@ "node-gyp-build": "~3.7.0" } }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, "capability": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/capability/-/capability-0.2.5.tgz", @@ -253,45 +198,10 @@ "nofilter": "^1.0.1" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, "chownr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" - }, - "cli-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", - "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", - "dev": true, - "requires": { - "ansi-regex": "^2.1.1", - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.14", - "timers-ext": "^0.1.5" - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==" }, "cls-bluebird": { "version": "2.1.0", @@ -307,19 +217,6 @@ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -338,68 +235,21 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "config-chain": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", - "dev": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, - "core-js": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", - "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", - "dev": true - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true - } - } - }, "crypto-js": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -416,12 +266,6 @@ "ms": "^2.1.1" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -452,11 +296,6 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" - }, "dottie": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.1.tgz", @@ -471,41 +310,6 @@ "safer-buffer": "^2.1.0" } }, - "editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true - } - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, "error-polyfill": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/error-polyfill/-/error-polyfill-0.1.2.tgz", @@ -516,90 +320,6 @@ "u3": "^0.1.0" } }, - "es5-ext": { - "version": "0.10.50", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", - "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "^1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -620,15 +340,6 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -644,23 +355,12 @@ "mime-types": "^2.1.12" } }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, "fs-minipass": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz", - "integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "requires": { - "minipass": "^2.2.1" + "minipass": "^2.6.0" } }, "fs.realpath": { @@ -681,49 +381,6 @@ "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" } }, "getpass": { @@ -735,9 +392,9 @@ } }, "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", + "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -747,12 +404,6 @@ "path-is-absolute": "^1.0.0" } }, - "graceful-fs": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", - "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==", - "dev": true - }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -767,11 +418,6 @@ "har-schema": "^2.0.0" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -815,9 +461,9 @@ } }, "ignore-walk": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", "requires": { "minimatch": "^3.0.4" } @@ -846,33 +492,18 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, "is-bluebird": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI=" }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-typedarray": { "version": "1.0.0", @@ -884,49 +515,16 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, - "js-beautify": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.10.0.tgz", - "integrity": "sha512-OMwf/tPDpE/BLlYKqZOhqWsd3/z2N3KOlyn1wsCRGFwViE8LOQTcDtathQvHvZc+q+zWmcNAbwKSC+iJoMaH2Q==", - "dev": true, - "requires": { - "config-chain": "^1.1.12", - "editorconfig": "^0.15.3", - "glob": "^7.1.3", - "mkdirp": "~0.5.1", - "nopt": "~4.0.1" - } - }, "js-sha256": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -955,15 +553,6 @@ "delimit-stream": "0.1.0" } }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -975,84 +564,10 @@ "verror": "1.10.0" } }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, "lodash": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz", - "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==" - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, - "memoizee": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", - "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.45", - "es6-weak-map": "^2.0.2", - "event-emitter": "^0.3.5", - "is-promise": "^2.1", - "lru-queue": "0.1", - "next-tick": "1", - "timers-ext": "^0.1.5" - } + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, "mime-db": { "version": "1.40.0", @@ -1067,12 +582,6 @@ "mime-db": "1.40.0" } }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1087,27 +596,20 @@ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "minipass": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" - }, - "dependencies": { - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" - } } }, "minizlib": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "requires": { - "minipass": "^2.2.1" + "minipass": "^2.9.0" } }, "mkdirp": { @@ -1124,9 +626,9 @@ "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" }, "moment-timezone": { - "version": "0.5.26", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.26.tgz", - "integrity": "sha512-sFP4cgEKTCymBBKgoxZjYzlSovC20Y6J7y3nanDc5RoBIXKlZhoYwBoZGe3flwU6A372AcRwScH8KiwV6zjy1g==", + "version": "0.5.27", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.27.tgz", + "integrity": "sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw==", "requires": { "moment": ">= 2.9.0" } @@ -1153,17 +655,17 @@ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" }, "nearlib": { - "version": "github:nearprotocol/nearlib#ca98e8939c1bd3a8800d98ef425d4bf01c75b27e", - "from": "github:nearprotocol/nearlib#master", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/nearlib/-/nearlib-0.17.0.tgz", + "integrity": "sha512-1Pek0Aoxdv1TXMKyD28OjPz3V1Zw6PpLyt4t2KBrPDIngwtjuJcujvVmE9jKDe3NAKSAC1TA2sW2iWQQT2wKDQ==", "requires": { "@types/bn.js": "^4.11.5", - "bn.js": "^4.11.5", + "bn.js": "^5.0.0", "bs58": "^4.0.0", "error-polyfill": "^0.1.2", "http-errors": "^1.7.2", "js-sha256": "^0.9.0", "node-fetch": "^2.3.0", - "tslint": "^5.18.0", "tweetnacl": "^1.0.1", "typescript": "^3.5.1" }, @@ -1195,18 +697,6 @@ } } }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", @@ -1236,9 +726,9 @@ }, "dependencies": { "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, @@ -1262,23 +752,14 @@ "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==" }, "npm-packlist": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.4.tgz", - "integrity": "sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw==", + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.6.tgz", + "integrity": "sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg==", "requires": { "ignore-walk": "^3.0.1", "npm-bundled": "^1.0.1" } }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", @@ -1326,17 +807,6 @@ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -1351,70 +821,11 @@ "os-tmpdir": "^1.0.0" } }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - }, - "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -1425,32 +836,10 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, "psl": { - "version": "1.1.33", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.33.tgz", - "integrity": "sha512-LTDP2uSrsc7XCb5lO7A8BI1qYxRe/8EqlRvMeEl6rsnYAqDOl8xHR+8lSAIVfrNaSAlTPTNOCgNjWcoUL3AZsw==" - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", + "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==" }, "punycode": { "version": "2.1.1", @@ -1502,12 +891,6 @@ "util-deprecate": "~1.0.1" } }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -1535,26 +918,6 @@ "uuid": "^3.3.2" } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", - "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", - "requires": { - "path-parse": "^1.0.6" - } - }, "retry-as-promised": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", @@ -1564,9 +927,9 @@ } }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "requires": { "glob": "^7.1.3" } @@ -1587,53 +950,30 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, "sequelize": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.10.1.tgz", - "integrity": "sha512-wE7jOUABVD9Kr8pAchRqk5quHoqE3tUHfKJ/WdLyZjHx4oMK5YWv1MEiny9DmiOlXOf1JNXwbPL9imSvzFq7aw==", + "version": "5.21.1", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.21.1.tgz", + "integrity": "sha512-JI+53MwcClfCFUPJT/l2dDzSpEzWAueyCZus33L/yhJxKTisfdd9OHrUPQ6/dI5nR5eIYT/EafrjkqTAlEQS2w==", "requires": { "bluebird": "^3.5.0", "cls-bluebird": "^2.1.0", "debug": "^4.1.1", "dottie": "^2.0.0", "inflection": "1.12.0", - "lodash": "^4.17.11", + "lodash": "^4.17.15", "moment": "^2.24.0", "moment-timezone": "^0.5.21", - "retry-as-promised": "^3.1.0", - "semver": "^6.1.1", + "retry-as-promised": "^3.2.0", + "semver": "^6.3.0", "sequelize-pool": "^2.3.0", "toposort-class": "^1.0.1", - "uuid": "^3.2.1", + "uuid": "^3.3.3", "validator": "^10.11.0", - "wkx": "^0.4.6" - }, - "dependencies": { - "semver": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz", - "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==" - } - } - }, - "sequelize-cli": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-5.5.0.tgz", - "integrity": "sha512-twVQ02alCpr2XvxNmpi32C48WZs6xHTH1OFTfTS5Meg3BVqOM8ghiZoml4FITFjlD8sAJSQjlAHTwqTbuolA6Q==", - "dev": true, - "requires": { - "bluebird": "^3.5.3", - "cli-color": "^1.4.0", - "fs-extra": "^7.0.1", - "js-beautify": "^1.8.8", - "lodash": "^4.17.5", - "resolve": "^1.5.0", - "umzug": "^2.1.0", - "yargs": "^13.1.0" + "wkx": "^0.4.8" } }, "sequelize-pool": { @@ -1651,46 +991,20 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, "shimmer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, "sqlite3": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.0.9.tgz", - "integrity": "sha512-IkvzjmsWQl9BuBiM4xKpl5X8WCR4w0AeJHRdobCdXZ8dT/lNc1XS6WqvY35N6+YzIIgzSBeY5prdFObID9F9tA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.0.tgz", + "integrity": "sha512-RvqoKxq+8pDHsJo7aXxsFR18i+dU2Wp5o12qAJOV5LNcDt+fgJsc2QKKg3sIRfXrN9ZjzY1T7SNe/DFVqAXjaw==", "requires": { "nan": "^2.12.1", "node-pre-gyp": "^0.11.0", @@ -1719,14 +1033,13 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -1738,70 +1051,30 @@ } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - } + "ansi-regex": "^2.0.0" } }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, "tar": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", - "integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==", + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", "requires": { "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.3.5", + "minipass": "^2.8.6", "minizlib": "^1.2.1", "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", "yallist": "^3.0.3" - }, - "dependencies": { - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" - } - } - }, - "timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true, - "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" } }, "toidentifier": { @@ -1830,39 +1103,6 @@ } } }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" - }, - "tslint": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.19.0.tgz", - "integrity": "sha512-1LwwtBxfRJZnUvoS9c0uj8XQtAnyhWr9KlNvDIdB+oXyT+VpsOAaEhEgKi1HrZ8rq0ki/AAnbGSv4KM6/AfVZw==", - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^3.2.0", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.29.0" - } - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "requires": { - "tslib": "^1.8.1" - } - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -1876,38 +1116,16 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, - "type": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/type/-/type-1.0.1.tgz", - "integrity": "sha512-MAM5dBMJCJNKs9E7JXo4CXRAansRfG0nlJxW7Wf6GZzSOvH31zClSaHdIMWLehe/EGMBkqeC55rrkaOr5Oo7Nw==", - "dev": true - }, "typescript": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", - "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==" + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.4.tgz", + "integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==" }, "u3": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/u3/-/u3-0.1.0.tgz", "integrity": "sha1-AGCSdmO2g1PFOc2pnpUR1mh+3Z0=" }, - "umzug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.2.0.tgz", - "integrity": "sha512-xZLW76ax70pND9bx3wqwb8zqkFGzZIK8dIHD9WdNy/CrNfjWcwQgQkGCuUqcuwEBvUm+g07z+qWvY+pxDmMEEw==", - "dev": true, - "requires": { - "babel-runtime": "^6.23.0", - "bluebird": "^3.5.3" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -1931,9 +1149,9 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" }, "validator": { "version": "10.11.0", @@ -1955,125 +1173,39 @@ "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=" }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "requires": { "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } } }, "wkx": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.7.tgz", - "integrity": "sha512-pHf546L96TK8RradLt1cWaIffstgv/zXZ14CGz5KnBs1AxBX0wm+IDphjJw0qrEqRv8P9W9CdTt8Z1unMRZ19A==", + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz", + "integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==", "requires": { "@types/node": "*" } }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.1.0.tgz", - "integrity": "sha512-Swie2C4fs7CkwlHu1glMePLYJJsWjzhl1vm3ZaLplD0h7OMkZyZ6kLTB/OagiU923bZrPFXuDTeEqaEN4NWG4g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", + "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", "requires": { "async-limiter": "^1.0.0" } }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", - "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.0" - } - }, - "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" } } } diff --git a/backend/package.json b/backend/package.json index 26337ba02..b50ee01de 100644 --- a/backend/package.json +++ b/backend/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "start": "node src/index.js" + "start": "env NODE_ENV=production node src/index.js", + "start:testnet": "env NEAR_RPC_URL=https://rpc.nearprotocol.com NEAR_DB_PREFIX=testnet npm run start" }, "repository": { "type": "git", @@ -19,9 +20,9 @@ "homepage": "https://github.com/nearprotocol/near-explorer#readme", "dependencies": { "autobahn": "19.4.1", - "nearlib": "github:nearprotocol/nearlib#master", - "sequelize": "^5.10.1", - "sqlite3": "^4.0.9", - "ws": "^7.1.0" + "nearlib": "^0.17.0", + "sequelize": "^5.21.1", + "sqlite3": "^4.1.0", + "ws": "^7.2.0" } } diff --git a/backend/src/config.js b/backend/src/config.js index 3515ceed2..5f5a193a3 100644 --- a/backend/src/config.js +++ b/backend/src/config.js @@ -1,4 +1,4 @@ -exports.nearRpcUrl = process.env.NEAR_RPC_URL || "https://rpc.nearprotocol.com"; +exports.nearRpcUrl = process.env.NEAR_RPC_URL || "http://localhost:3030"; exports.syncFetchQueueSize = process.env.NEAR_SYNC_FETCH_QUEUE_SIZE || 1000; exports.syncSaveQueueSize = process.env.NEAR_SYNC_SAVE_QUEUE_SIZE || 10; exports.bulkDbUpdateSize = process.env.NEAR_SYNC_BULK_DB_UPDATE_SIZE || 10; @@ -7,6 +7,8 @@ exports.regularSyncNewNearcoreStateInterval = exports.regularSyncMissingNearcoreStateInterval = process.env.NEAR_REGULAR_SYNC_MISSING_NEARCORE_STATE_INTERVAL || 60000; +exports.wampNearNetworkName = + process.env.WAMP_NEAR_NETWORK_NAME || "localhostnet"; exports.wampNearExplorerUrl = process.env.WAMP_NEAR_EXPLORER_URL || "ws://localhost:8080/ws"; exports.wampNearExplorerBackendSecret = diff --git a/backend/src/sync.js b/backend/src/sync.js index 06d9c96f6..1adfd538b 100644 --- a/backend/src/sync.js +++ b/backend/src/sync.js @@ -128,7 +128,29 @@ async function saveBlocksFromRequests(requests) { return [blockResult.value]; }); - return await saveBlocks(blocks); + const transactionsByBlock = await Promise.all( + blocks.map(async block => { + try { + const detailedChunks = await Promise.all( + block.chunks.map(chunk => nearRpc.chunk(chunk.chunk_hash)) + ); + return detailedChunks.map(chunk => chunk.transactions); + } catch (error) { + throw error; + return null; + } + }) + ); + + const blocksWithTransactions = blocks.flatMap((block, i) => { + const transactions = transactionsByBlock[i]; + if (transactions === null) { + return []; + } + block.transactions = transactions.flatMap(it => it); + return [block]; + }); + return await saveBlocks(blocksWithTransactions); } async function syncNearcoreBlocks(topBlockHeight, bottomBlockHeight) { diff --git a/backend/src/wamp.js b/backend/src/wamp.js index 9d75ea1e2..2dc6df848 100644 --- a/backend/src/wamp.js +++ b/backend/src/wamp.js @@ -3,6 +3,7 @@ const autobahn = require("autobahn"); const models = require("../models"); const { + wampNearNetworkName, wampNearExplorerUrl, wampNearExplorerBackendSecret } = require("./config"); @@ -33,6 +34,10 @@ wampHandlers["nearcore-query"] = async ([path, data]) => { return await nearRpc.query(path, data); }; +wampHandlers["nearcore-tx"] = async ([transactionHash, accountId]) => { + return await nearRpc.sendJsonRpc("tx", [transactionHash, accountId]); +}; + function setupWamp() { const wamp = new autobahn.Connection({ realm: "near-explorer", @@ -59,7 +64,7 @@ function setupWamp() { console.log("WAMP connection is established. Waiting for commands..."); for (const [name, handler] of Object.entries(wampHandlers)) { - const uri = `com.nearprotocol.explorer.${name}`; + const uri = `com.nearprotocol.${wampNearNetworkName}.explorer.${name}`; try { await session.register(uri, handler); } catch (error) { diff --git a/docker-compose.yml b/docker-compose.yml index 317fb1a65..f3a0df713 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,13 +6,13 @@ services: environment: - WAMP_NEAR_EXPLORER_PORT=8080 - WAMP_NEAR_EXPLORER_BACKEND_SECRET=back - - WAMP_NEAR_EXPLORER_FRONTEND_SECRET=front ports: - 8080:8080 backend: build: ./backend environment: + - NEAR_RPC_URL=https://rpc.nearprotocol.com - WAMP_NEAR_EXPLORER_URL=ws://wamp:8080/ws - WAMP_NEAR_EXPLORER_BACKEND_SECRET=back @@ -22,6 +22,5 @@ services: - PORT=3000 - WAMP_NEAR_EXPLORER_URL=ws://localhost:8080/ws - WAMP_NEAR_EXPLORER_INTERNAL_URL=ws://wamp:8080/ws - - WAMP_NEAR_EXPLORER_FRONTEND_SECRET=front ports: - 3000:3000 diff --git a/frontend/next.config.js b/frontend/next.config.js index ac83d51fb..e73a171c9 100644 --- a/frontend/next.config.js +++ b/frontend/next.config.js @@ -3,6 +3,25 @@ const withCSS = require("@zeit/next-css"); const defaultWampNearExplorerUrl = "ws://localhost:8080/ws"; +let nearNetworks; +if (process.env.NEAR_NETWORKS) { + nearNetworks = JSON.parse(process.env.NEAR_NETWORKS); +} else { + nearNetworks = [ + { + name: "localhostnet", + explorerLink: "http://localhost:3000", + aliases: ["localhost:3000", "localhost", "127.0.0.1", "127.0.0.1:3000"] + } + ]; +} +const nearNetworkAliases = {}; +for (const nearNetwork of nearNetworks) { + for (const alias of nearNetwork.aliases) { + nearNetworkAliases[alias] = nearNetwork; + } +} + module.exports = withCSS({ serverRuntimeConfig: { wampNearExplorerUrl: @@ -11,6 +30,8 @@ module.exports = withCSS({ defaultWampNearExplorerUrl }, publicRuntimeConfig: { + nearNetworks, + nearNetworkAliases, wampNearExplorerUrl: process.env.WAMP_NEAR_EXPLORER_URL || defaultWampNearExplorerUrl, googleAnalytics: process.env.NEAR_EXPLORER_GOOGLE_ANALYTICS diff --git a/frontend/package.json b/frontend/package.json index 17ac6bd5a..75cd338b9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,8 +6,12 @@ "typecheck": "tsc --noEmit", "test": "npm run typecheck && jest", "dev": "next", + "dev:local-wamp": "env WAMP_NEAR_EXPLORER_URL=ws://localhost:8080/ws npm run dev", + "dev:production-wamp": "env 'NEAR_NETWORKS=[{\"name\": \"testnet\", \"explorerLink\": \"http://localhost:3000/\", \"aliases\": [\"localhost:3000\", \"127.0.0.1:3000\"]}]' WAMP_NEAR_EXPLORER_URL=wss://near-explorer-wamp.onrender.com/ws npm run dev", "build": "next build", "start": "next start", + "start:local-wamp": "env WAMP_NEAR_EXPLORER_URL=ws://localhost:8080/ws npm run start", + "start:production-wamp": "env 'NEAR_NETWORKS=[{\"name\": \"testnet\", \"explorerLink\": \"http://localhost:3000/\", \"aliases\": [\"localhost:3000\", \"127.0.0.1:3000\"]}]' WAMP_NEAR_EXPLORER_URL=wss://near-explorer-wamp.onrender.com/ws npm run start", "e2e:test": "npm start & cypress run", "e2e": "cypress run", "e2e:chrome": "cypress run --browser chrome", @@ -17,8 +21,7 @@ "cy:version": "cypress version", "cy:open": "cypress open", "cy:run": "cypress run", - "test:ci": "start-server-and-test start:dev 3000 cy:run", - "start:dev": "env WAMP_NEAR_EXPLORER_URL=wss://near-explorer-wamp.onrender.com/ws next" + "test:ci": "start-server-and-test start:production-wamp 3000 cy:run" }, "repository": { "type": "git", diff --git a/frontend/src/components/accounts/AccountDetails.tsx b/frontend/src/components/accounts/AccountDetails.tsx index 0bbe7a76f..eeb2b65fd 100644 --- a/frontend/src/components/accounts/AccountDetails.tsx +++ b/frontend/src/components/accounts/AccountDetails.tsx @@ -37,14 +37,14 @@ export default ({ account }: Props) => { } /> - + } + text={} /> - + ", () => { account={{ id: "account", amount: "1", - staked: "1", + locked: "1", storageUsage: 0, storagePaidAt: 1, inTransactionsCount: 0, diff --git a/frontend/src/components/accounts/__tests__/__snapshots__/AccountDetails.test.tsx.snap b/frontend/src/components/accounts/__tests__/__snapshots__/AccountDetails.test.tsx.snap index 482f56653..e994741aa 100644 --- a/frontend/src/components/accounts/__tests__/__snapshots__/AccountDetails.test.tsx.snap +++ b/frontend/src/components/accounts/__tests__/__snapshots__/AccountDetails.test.tsx.snap @@ -77,7 +77,7 @@ exports[` renders 1`] = `
renders 1`] = ` className="jsx-3005147464 card-cell-title-img" src="/static/images/icon-m-filter.svg" /> - Staked + Locked
renders 1`] = `
{ let blocks; if (text === null || text === undefined || text.trim().length === 0) { - blocks = await BlocksApi.getLatestBlocksInfo(); + blocks = await new BlocksApi().getLatestBlocksInfo(); } else { - blocks = await BlocksApi.searchBlocks(text); + blocks = await new BlocksApi().searchBlocks(text); } setBlocks(() => blocks); diff --git a/frontend/src/components/blocks/BlocksList.jsx b/frontend/src/components/blocks/BlocksList.jsx index 43c67942f..ec48e3487 100644 --- a/frontend/src/components/blocks/BlocksList.jsx +++ b/frontend/src/components/blocks/BlocksList.jsx @@ -1,17 +1,23 @@ import LoadingOverlay from "react-loading-overlay"; -import * as BlocksApi from "../../libraries/explorer-wamp/blocks"; +import BlocksApi from "../../libraries/explorer-wamp/blocks"; import BlocksRow from "./BlocksRow"; export default class extends React.Component { + constructor(props) { + super(props); + + this._blocksApi = new BlocksApi(); + } + componentDidMount() { this._blockLoader = document.getElementById("block-loader"); document.addEventListener("scroll", this._onScroll); this._loadBlocks(); - BlocksApi.getTotal().then(total => { + this._blocksApi.getTotal().then(total => { this.props.setPagination(pagination => { return { ...pagination, total }; }); @@ -60,7 +66,7 @@ export default class extends React.Component { _loadBlocks = async () => { let blocks; if (this.props.pagination.stop === null) { - blocks = await BlocksApi.getLatestBlocksInfo(); + blocks = await this._blocksApi.getLatestBlocksInfo(); } else { blocks = await this._getNextBatch(this.props.pagination); } @@ -81,12 +87,12 @@ export default class extends React.Component { let blocks = []; try { if (pagination.search) { - blocks = await BlocksApi.searchBlocks( + blocks = await this._blocksApi.searchBlocks( pagination.search, pagination.stop ); } else { - blocks = await BlocksApi.getPreviousBlocks( + blocks = await this._blocksApi.getPreviousBlocks( pagination.stop, pagination.count ); diff --git a/frontend/src/components/dashboard/DashboardHeader.jsx b/frontend/src/components/dashboard/DashboardHeader.jsx index 91fca9148..04dea2f22 100644 --- a/frontend/src/components/dashboard/DashboardHeader.jsx +++ b/frontend/src/components/dashboard/DashboardHeader.jsx @@ -67,9 +67,9 @@ export default ({ - Filter 1 - Filter 2 - Filter 3 + Accounts + Transactions + Blocks @@ -79,7 +79,7 @@ export default ({ 🔎 (
- + diff --git a/frontend/src/components/nodes/Nodes.jsx b/frontend/src/components/nodes/Nodes.jsx index c2a76382b..c46463486 100644 --- a/frontend/src/components/nodes/Nodes.jsx +++ b/frontend/src/components/nodes/Nodes.jsx @@ -2,23 +2,30 @@ import { Row, Col } from "react-bootstrap"; import FlipMove from "react-flip-move"; import LoadingOverlay from "react-loading-overlay"; -import * as NodesApi from "../../libraries/explorer-wamp/nodes"; +import NodesApi from "../../libraries/explorer-wamp/nodes"; import NodeRow from "./NodeRow"; export default class extends React.Component { state = { loading: true, nodes: null }; + constructor(props) { + super(props); + + this._nodesApi = new NodesApi(); + } + componentDidMount() { this.regularFetchInfo(); } + componentWillUnmount() { clearTimeout(this.timer); this.timer = false; } fetchInfo = async () => { - const nodes = await NodesApi.getNodesInfo(); + const nodes = await this._nodesApi.getNodesInfo(); await this.setState({ loading: false, nodes }); }; diff --git a/frontend/src/components/transactions/ActionsList.tsx b/frontend/src/components/transactions/ActionsList.tsx index 3005bf3be..fda998eee 100644 --- a/frontend/src/components/transactions/ActionsList.tsx +++ b/frontend/src/components/transactions/ActionsList.tsx @@ -3,20 +3,25 @@ import * as T from "../../libraries/explorer-wamp/transactions"; import ActionRow, { ViewMode } from "./ActionRow"; export interface Props { - actions: T.Action[]; + actions: (T.Action | keyof T.Action)[]; transaction: T.Transaction; viewMode?: ViewMode; + reversed?: boolean; } -export default ({ actions, transaction, viewMode }: Props) => ( - <> - {actions.map((action, actionIndex) => ( - - ))} - -); +export default ({ actions, transaction, viewMode, reversed }: Props) => { + let actionRows = actions.map((action, actionIndex) => ( + + )); + + if (reversed) { + actionRows.reverse(); + } + + return <>{actionRows}; +}; diff --git a/frontend/src/components/transactions/ReceiptRow.tsx b/frontend/src/components/transactions/ReceiptRow.tsx new file mode 100644 index 000000000..3986a5410 --- /dev/null +++ b/frontend/src/components/transactions/ReceiptRow.tsx @@ -0,0 +1,114 @@ +import React from "react"; +import { Row, Col } from "react-bootstrap"; + +import * as T from "../../libraries/explorer-wamp/transactions"; + +export interface Props { + receipt: T.Receipt; +} + +export interface State {} + +export default class extends React.Component { + render() { + const { receipt } = this.props; + + let statusInfo; + if ("SuccessValue" in (receipt.outcome.status as T.ReceiptSuccessValue)) { + const { SuccessValue } = receipt.outcome.status as T.ReceiptSuccessValue; + if (SuccessValue === null) { + statusInfo = "No result"; + } else if (SuccessValue.length === 0) { + statusInfo = "Empty result"; + } else { + statusInfo = ( + <> + Result: +
{SuccessValue}
+ + ); + } + } else { + if ("Failure" in (receipt.outcome.status as T.ReceiptFailure)) { + const { Failure } = receipt.outcome.status as T.ReceiptFailure; + statusInfo = ( + <> + Failure: +
{JSON.stringify(Failure, null, 2)}
+ + ); + } else { + statusInfo = {receipt.outcome.status}; + } + } + + return ( + + + + + + {statusInfo} + + + + {receipt.outcome.logs.length === 0 ? ( + "No logs" + ) : ( +
{receipt.outcome.logs.join("\n")}
+ )} + +
+ + + + + {`${receipt.id.substr(0, 7)}...`} + + + +
+ + +
+ ); + } +} diff --git a/frontend/src/components/transactions/ReceiptsList.tsx b/frontend/src/components/transactions/ReceiptsList.tsx new file mode 100644 index 000000000..0103c01aa --- /dev/null +++ b/frontend/src/components/transactions/ReceiptsList.tsx @@ -0,0 +1,15 @@ +import * as T from "../../libraries/explorer-wamp/transactions"; + +import ReceiptRow from "./ReceiptRow"; + +export interface Props { + receipts: T.Receipt[]; +} + +export default ({ receipts }: Props) => ( + <> + {receipts.map(receipt => ( + + ))} + +); diff --git a/frontend/src/components/transactions/TransactionDetails.tsx b/frontend/src/components/transactions/TransactionDetails.tsx new file mode 100644 index 000000000..c7e1a7280 --- /dev/null +++ b/frontend/src/components/transactions/TransactionDetails.tsx @@ -0,0 +1,92 @@ +import { Row, Col } from "react-bootstrap"; + +import { Transaction } from "../../libraries/explorer-wamp/transactions"; +import moment from "../../libraries/moment"; + +import AccountLink from "../utils/AccountLink"; +import BlockLink from "../utils/BlockLink"; +import CardCell from "../utils/CardCell"; + +export interface Props { + transaction: Transaction; +} + +export default ({ transaction }: Props) => { + return ( +
+ + + } + className="border-0" + /> + + + } + /> + + + + + + + + + + + + + + + + + {transaction.blockHash} + + } + className="transaction-card-block-hash border-0" + /> + + + +
+ ); +}; diff --git a/frontend/src/components/transactions/Transactions.tsx b/frontend/src/components/transactions/Transactions.tsx index 07a81c76f..e4e875758 100644 --- a/frontend/src/components/transactions/Transactions.tsx +++ b/frontend/src/components/transactions/Transactions.tsx @@ -1,29 +1,47 @@ import React from "react"; -import * as TransactionsApi from "../../libraries/explorer-wamp/transactions"; +import TransactionsApi, * as T from "../../libraries/explorer-wamp/transactions"; import TransactionsList from "./TransactionsList"; export interface Props { accountId?: string; blockHash?: string; + reversed: boolean; + limit: number; } export interface State { - transactions: TransactionsApi.Transaction[] | null; + transactions: T.Transaction[] | null; } export default class extends React.PureComponent { + static defaultProps = { + reversed: false, + limit: 50 + }; + state: State = { transactions: null }; + _transactionsApi: TransactionsApi | null; + + constructor(props: Props) { + super(props); + + // TODO: Design ExplorerApi to handle server-side rendering gracefully. + this._transactionsApi = null; + } + componentDidMount() { this.fetchTransactions(); } - componentDidUpdate() { - this.fetchTransactions(); + componentDidUpdate(prevProps: Props) { + if (this.props !== prevProps) { + this.fetchTransactions(); + } } render() { @@ -31,14 +49,24 @@ export default class extends React.PureComponent { if (transactions === null) { return null; } - return ; + return ( + + ); } fetchTransactions = async () => { - const transactions = await TransactionsApi.getTransactions({ + if (this._transactionsApi === null) { + this._transactionsApi = new TransactionsApi(); + } + const transactions = await this._transactionsApi.getTransactions({ signerId: this.props.accountId, receiverId: this.props.accountId, - blockHash: this.props.blockHash + blockHash: this.props.blockHash, + tail: this.props.reversed, + limit: this.props.limit }); this.setState({ transactions }); }; diff --git a/frontend/src/components/transactions/TransactionsHeader.jsx b/frontend/src/components/transactions/TransactionsHeader.jsx index eb163a281..ecb9502e1 100644 --- a/frontend/src/components/transactions/TransactionsHeader.jsx +++ b/frontend/src/components/transactions/TransactionsHeader.jsx @@ -1,24 +1,10 @@ import { Row, Col } from "react-bootstrap"; -import { DataConsumer } from "../utils/DataProvider"; import Search from "../utils/Search"; export default props => ( - - {ctx => ( - - - {ctx.pagination.start}-{ctx.pagination.stop} - - - {" "} - of {ctx.pagination.total} Total - - - )} - diff --git a/frontend/src/components/transactions/TransactionsList.tsx b/frontend/src/components/transactions/TransactionsList.tsx index 11203a358..81676fc3f 100644 --- a/frontend/src/components/transactions/TransactionsList.tsx +++ b/frontend/src/components/transactions/TransactionsList.tsx @@ -6,19 +6,23 @@ import { ViewMode } from "./ActionRow"; export interface Props { transactions: T.Transaction[]; viewMode?: ViewMode; + reversed?: boolean; } -export default ({ transactions, viewMode }: Props) => { - return ( - <> - {transactions.map(transaction => ( - - ))} - - ); +export default ({ transactions, viewMode, reversed }: Props) => { + let actions = transactions.map(transaction => ( + + )); + + if (reversed) { + actions.reverse(); + } + + return <>{actions}; }; diff --git a/frontend/src/components/transactions/__tests__/ActionsList.test.tsx b/frontend/src/components/transactions/__tests__/ActionsList.test.tsx index 76c82d327..5963eff17 100644 --- a/frontend/src/components/transactions/__tests__/ActionsList.test.tsx +++ b/frontend/src/components/transactions/__tests__/ActionsList.test.tsx @@ -27,4 +27,27 @@ describe("", () => { ) ).toMatchSnapshot(); }); + + it("renders reversed", () => { + expect( + JSON.stringify( + renderer.create( + + ) + ) + ).toEqual( + JSON.stringify( + renderer.create( + + ) + ) + ); + }); }); diff --git a/frontend/src/components/transactions/__tests__/ReceiptRow.test.tsx b/frontend/src/components/transactions/__tests__/ReceiptRow.test.tsx new file mode 100644 index 000000000..cd951848f --- /dev/null +++ b/frontend/src/components/transactions/__tests__/ReceiptRow.test.tsx @@ -0,0 +1,15 @@ +import renderer from "react-test-renderer"; + +import ReceiptRow from "../ReceiptRow"; + +import { TRANSACTIONS } from "./common"; + +describe("", () => { + it("renders", () => { + expect( + renderer.create( + + ) + ).toMatchSnapshot(); + }); +}); diff --git a/frontend/src/components/transactions/__tests__/ReceiptsList.test.tsx b/frontend/src/components/transactions/__tests__/ReceiptsList.test.tsx new file mode 100644 index 000000000..a4a701d33 --- /dev/null +++ b/frontend/src/components/transactions/__tests__/ReceiptsList.test.tsx @@ -0,0 +1,15 @@ +import renderer from "react-test-renderer"; + +import ReceiptsList from "../ReceiptsList"; + +import { TRANSACTIONS } from "./common"; + +describe("", () => { + it("renders", () => { + expect( + renderer.create( + + ) + ).toMatchSnapshot(); + }); +}); diff --git a/frontend/src/components/transactions/__tests__/TransactionDetails.test.tsx b/frontend/src/components/transactions/__tests__/TransactionDetails.test.tsx new file mode 100644 index 000000000..98c79510f --- /dev/null +++ b/frontend/src/components/transactions/__tests__/TransactionDetails.test.tsx @@ -0,0 +1,13 @@ +import renderer from "react-test-renderer"; + +import TransactionDetails from "../TransactionDetails"; + +import { TRANSACTIONS } from "./common"; + +describe("", () => { + it("renders", () => { + expect( + renderer.create() + ).toMatchSnapshot(); + }); +}); diff --git a/frontend/src/components/transactions/__tests__/TransactionsList.test.tsx b/frontend/src/components/transactions/__tests__/TransactionsList.test.tsx index 9cb53f61d..16d76ba25 100644 --- a/frontend/src/components/transactions/__tests__/TransactionsList.test.tsx +++ b/frontend/src/components/transactions/__tests__/TransactionsList.test.tsx @@ -10,4 +10,23 @@ describe("", () => { renderer.create() ).toMatchSnapshot(); }); + + it("renders reversed", () => { + const reversedTransactions = TRANSACTIONS.map(transaction => { + return { ...transaction, actions: [...transaction.actions].reverse() }; + }).reverse(); + expect( + JSON.stringify( + renderer.create( + + ) + ) + ).toEqual( + JSON.stringify( + renderer.create( + + ) + ) + ); + }); }); diff --git a/frontend/src/components/transactions/__tests__/__snapshots__/ActionsList.test.tsx.snap b/frontend/src/components/transactions/__tests__/__snapshots__/ActionsList.test.tsx.snap index 6fd341e68..026714c18 100644 --- a/frontend/src/components/transactions/__tests__/__snapshots__/ActionsList.test.tsx.snap +++ b/frontend/src/components/transactions/__tests__/__snapshots__/ActionsList.test.tsx.snap @@ -1,5 +1,655 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` renders compact 1`] = `null`; +exports[` renders compact 1`] = ` +Array [ +
+
+
+ + + +
+
+
+
+
+
+
+ New account created: + + @receiver.test + +
+
+
+ +
+
+
+ +
+
+ + Completed + + + + 1s ago + +
+
+
+
+
+
, +
+
+
+ + + +
+
+
+
+
+
+
+ Transferred 10.00000 Ⓝ to + + @receiver.test + +
+
+
+ +
+
+
+ +
+
+ + Completed + + + + 1s ago + +
+
+
+
+
+
, +
+
+
+ + + +
+
+
+
+
+
+
+ New key added for + + @receiver.test + + : ed25519:8LXEySy... +
+
+
+ +
+
+
+ +
+
+ + Completed + + + + 1s ago + +
+
+
+
+
+
, +] +`; -exports[` renders sparsely by default 1`] = `null`; +exports[` renders sparsely by default 1`] = ` +Array [ +
+
+
+ + + +
+ +
+
+
+
+
+
+ New account created: + + @receiver.test + +
+
+
+ +
+
+
+ +
+
+ + Completed + + + + 1s ago + +
+
+
+
+
+
, +
+
+
+ + + +
+ +
+
+
+
+
+
+ Transferred 10.00000 Ⓝ to + + @receiver.test + +
+
+
+ +
+
+
+ +
+
+ + Completed + + + + 1s ago + +
+
+
+
+
+
, +
+
+
+ + + +
+ +
+
+
+
+
+
+ New key added for + + @receiver.test + + : ed25519:8LXEySy... +
+
+
+ +
+
+
+ +
+
+ + Completed + + + + 1s ago + +
+
+
+
+
+
, +] +`; diff --git a/frontend/src/components/transactions/__tests__/__snapshots__/ReceiptRow.test.tsx.snap b/frontend/src/components/transactions/__tests__/__snapshots__/ReceiptRow.test.tsx.snap new file mode 100644 index 000000000..9bb23f623 --- /dev/null +++ b/frontend/src/components/transactions/__tests__/__snapshots__/ReceiptRow.test.tsx.snap @@ -0,0 +1,51 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders 1`] = ` +
+
+
+
+
+
+ No result +
+
+
+
+ No logs +
+
+
+
+
+
+ 9uZxS2c... +
+
+
+
+
+
+`; diff --git a/frontend/src/components/transactions/__tests__/__snapshots__/ReceiptsList.test.tsx.snap b/frontend/src/components/transactions/__tests__/__snapshots__/ReceiptsList.test.tsx.snap new file mode 100644 index 000000000..dff3cbe17 --- /dev/null +++ b/frontend/src/components/transactions/__tests__/__snapshots__/ReceiptsList.test.tsx.snap @@ -0,0 +1,151 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders 1`] = ` +Array [ +
+
+
+
+
+
+ No result +
+
+
+
+ No logs +
+
+
+
+
+
+ 9uZxS2c... +
+
+
+
+
+
, +
+
+
+
+
+
+ Empty result +
+
+
+
+
+                LOG: Counter is now: 1
+              
+
+
+
+
+
+
+ A8HaLh5... +
+
+
+
+
+
, +
+
+
+
+
+
+ Empty result +
+
+
+
+ No logs +
+
+
+
+
+
+ A5oSQ6z... +
+
+
+
+
+
, +] +`; diff --git a/frontend/src/components/transactions/__tests__/__snapshots__/TransactionDetails.test.tsx.snap b/frontend/src/components/transactions/__tests__/__snapshots__/TransactionDetails.test.tsx.snap new file mode 100644 index 000000000..32c84e81c --- /dev/null +++ b/frontend/src/components/transactions/__tests__/__snapshots__/TransactionDetails.test.tsx.snap @@ -0,0 +1,209 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders 1`] = ` +
+
+
+
+
+
+
+ + Signed by +
+ +
+
+
+
+
+
+
+
+
+ + Receiver +
+ +
+
+
+
+
+
+
+
+
+ + Status +
+
+ Completed +
+
+
+
+
+
+
+
+
+
+
+
+ Created +
+
+ February 01, 2019 at 12:00:00am +
+
+
+
+
+
+
+
+
+
+ Hash +
+
+ BvJeW6gnFjkCBKCsRNEBrRLDQCFZNxLAi6uXzmLaVrrj +
+
+
+
+
+
+
+
+ +
+
+
+`; diff --git a/frontend/src/components/transactions/__tests__/__snapshots__/TransactionsList.test.tsx.snap b/frontend/src/components/transactions/__tests__/__snapshots__/TransactionsList.test.tsx.snap index db418f2b8..38f1a9e06 100644 --- a/frontend/src/components/transactions/__tests__/__snapshots__/TransactionsList.test.tsx.snap +++ b/frontend/src/components/transactions/__tests__/__snapshots__/TransactionsList.test.tsx.snap @@ -1,3 +1,443 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` renders 1`] = `null`; +exports[` renders 1`] = ` +Array [ +
+
+
+ + + +
+ +
+
+
+
+
+
+ New account created: + + @receiver.test + +
+
+
+ +
+
+
+ +
+
+ + Completed + + + + 1s ago + +
+
+
+
+
+
, +
+
+
+ + + +
+ +
+
+
+
+
+
+ Transferred 10.00000 Ⓝ to + + @receiver.test + +
+
+
+ +
+
+
+ +
+
+ + Completed + + + + 1s ago + +
+
+
+
+
+
, +
+
+
+ + + +
+ +
+
+
+
+
+
+ New key added for + + @receiver.test + + : ed25519:8LXEySy... +
+
+
+ +
+
+
+ +
+
+ + Completed + + + + 1s ago + +
+
+
+
+
+
, +
+
+
+ + + +
+ +
+
+
+
+
+
+ Called method in contract: + + @receiver2.test + +
+
+
+ +
+
+
+ +
+
+ + Completed + + + + 1s ago + +
+
+
+
+
+
, +] +`; diff --git a/frontend/src/components/transactions/__tests__/common.tsx b/frontend/src/components/transactions/__tests__/common.tsx index 0b03c3547..8737ad2b3 100644 --- a/frontend/src/components/transactions/__tests__/common.tsx +++ b/frontend/src/components/transactions/__tests__/common.tsx @@ -1,4 +1,6 @@ -export const TRANSACTIONS = [ +import * as T from "../../../libraries/explorer-wamp/transactions"; + +export const TRANSACTIONS: T.Transaction[] = [ { hash: "BvJeW6gnFjkCBKCsRNEBrRLDQCFZNxLAi6uXzmLaVrrj", signerId: "signer.test", @@ -6,6 +8,72 @@ export const TRANSACTIONS = [ status: "Completed", blockHash: "BvJeW6gnFjkCBKCsRNEBrRLDQCFZNxLAi6uXzmLaVrrj", blockTimestamp: +new Date(2019, 1, 1), - actions: [] + actions: [ + "CreateAccount" as keyof T.Action, + { + Transfer: { + deposit: "10000000000000000000" + } as T.Transfer + } as T.Action, + { + AddKey: { + access_key: { + nonce: 0, + permission: "FullAccess" + }, + public_key: "ed25519:8LXEySyBYewiTTLxjfF1TKDsxxxxxxxxxxxxxxxxxx" + } as T.AddKey + } as T.Action + ], + receipts: [ + { + id: "9uZxS2cuZv7yphcidRiwNqDayMxcVRE1zHkAmwrHr1vs", + outcome: { + logs: [], + receipt_ids: ["A8HaLh5pzaeuiq4VVnmgghT6RzCRuiNftkJCZmVQvN3v"], + status: { SuccessValue: null }, + gas_burnt: 0 + } + }, + { + id: "A8HaLh5pzaeuiq4VVnmgghT6RzCRuiNftkJCZmVQvN3v", + outcome: { + logs: ["LOG: Counter is now: 1"], + receipt_ids: ["A5oSQ6z71zWi3X1KFy9xhNzyjj8bQx4wwboWUMnK3dgp"], + status: { SuccessValue: "" }, + gas_burnt: 0 + } + }, + { + id: "A5oSQ6z71zWi3X1KFy9xhNzyjj8bQx4wwboWUMnK3dgp", + outcome: { + logs: [], + receipt_ids: [], + status: { SuccessValue: "" }, + gas_burnt: 0 + } + } + ] + }, + + { + hash: "222eW6gnFjkCBKCsRNEBrRLDQCFZNxLAi6uXzmLaVrrj", + signerId: "signer2.test", + receiverId: "receiver2.test", + status: "Completed", + blockHash: "222BBBgnFjkCBKCsRNEBrRLDQCFZNxLAi6uXzmLaVrrj", + blockTimestamp: +new Date(2019, 1, 1), + actions: [ + { + FunctionCall: { + result: "", + args: "eyJ0ZXh0Ijoid2hlbiBpY28/In0=", + deposit: "0", + gas: 2000000, + method_name: "addMessage" + } as T.FunctionCall + } as T.Action + ], + receipts: [] } ]; diff --git a/frontend/src/components/utils/DataProvider.jsx b/frontend/src/components/utils/DataProvider.jsx deleted file mode 100644 index 5d0902bb3..000000000 --- a/frontend/src/components/utils/DataProvider.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import { useState } from "react"; - -const DataContext = React.createContext(); - -const networks = ["Testnet One"]; - -export default props => { - const [network, setNetwork] = useState(networks[0]); - - return ( - - {props.children} - - ); -}; - -const DataConsumer = DataContext.Consumer; - -export { DataConsumer, DataContext }; diff --git a/frontend/src/components/utils/DataProvider.tsx b/frontend/src/components/utils/DataProvider.tsx new file mode 100644 index 000000000..c22135e90 --- /dev/null +++ b/frontend/src/components/utils/DataProvider.tsx @@ -0,0 +1,26 @@ +import { createContext } from "react"; + +const DataContext = createContext({}); + +export interface Props { + currentNearNetwork: any; + nearNetworks: any; + children: React.ReactNode; +} + +export default (props: Props) => { + return ( + + {props.children} + + ); +}; + +const DataConsumer = DataContext.Consumer; + +export { DataConsumer, DataContext }; diff --git a/frontend/src/components/utils/HeaderDropdownNav.jsx b/frontend/src/components/utils/HeaderDropdownNav.jsx index 49144cd95..7ba73be19 100644 --- a/frontend/src/components/utils/HeaderDropdownNav.jsx +++ b/frontend/src/components/utils/HeaderDropdownNav.jsx @@ -2,9 +2,9 @@ import { Dropdown } from "react-bootstrap"; import { DataConsumer } from "./DataProvider"; -const HeaderDropdownItem = props => ( - - {props.title} +const HeaderDropdownItem = ({ link, title }) => ( + + {title} ); @@ -14,16 +14,18 @@ const HeaderDropdownNav = () => ( - {context.network} + + {context.currentNearNetwork.name} + - {context.networks.map((network, index) => { + {context.nearNetworks.map(network => { return ( context.updateNetwork(index)} + key={network.name} + title={network.name} + link={network.explorerLink} /> ); })} diff --git a/frontend/src/libraries/explorer-wamp/accounts.ts b/frontend/src/libraries/explorer-wamp/accounts.ts index f36b8dd54..af2de7ac8 100644 --- a/frontend/src/libraries/explorer-wamp/accounts.ts +++ b/frontend/src/libraries/explorer-wamp/accounts.ts @@ -1,4 +1,4 @@ -import { call } from "."; +import { ExplorerApi } from "."; interface AccountId { id: string; @@ -11,41 +11,43 @@ interface AccountStats { interface AccountInfo { amount: string; - staked: string; + locked: string; storageUsage: number; storagePaidAt: number; } export type Account = AccountId & AccountStats & AccountInfo; -export async function getAccountInfo(id: string): Promise { - try { - const [accountInfo, accountStats] = await Promise.all([ - call(".nearcore-query", [`account/${id}`, ""]), - call(".select", [ - `SELECT outTransactionsCount.outTransactionsCount, inTransactionsCount.inTransactionsCount FROM +export default class AccountApi extends ExplorerApi { + async getAccountInfo(id: string): Promise { + try { + const [accountInfo, accountStats] = await Promise.all([ + this.call("nearcore-query", [`account/${id}`, ""]), + this.call("select", [ + `SELECT outTransactionsCount.outTransactionsCount, inTransactionsCount.inTransactionsCount FROM (SELECT COUNT(transactions.hash) as outTransactionsCount FROM transactions WHERE signer_id = :id) as outTransactionsCount, (SELECT COUNT(transactions.hash) as inTransactionsCount FROM transactions WHERE receiver_id = :id) as inTransactionsCount `, - { - id - } - ]) - ]); + { + id + } + ]) + ]); - return { - id, - amount: accountInfo.amount, - staked: accountInfo.staked, - storageUsage: accountInfo.storage_usage, - storagePaidAt: accountInfo.storage_paid_at, - ...accountStats[0] - }; - } catch (error) { - console.error("Accounts.getAccountInfo failed to fetch data due to:"); - console.error(error); - throw error; + return { + id, + amount: accountInfo.amount, + locked: accountInfo.locked, + storageUsage: accountInfo.storage_usage, + storagePaidAt: accountInfo.storage_paid_at, + ...accountStats[0] + }; + } catch (error) { + console.error("Accounts.getAccountInfo failed to fetch data due to:"); + console.error(error); + throw error; + } } } diff --git a/frontend/src/libraries/explorer-wamp/blocks.js b/frontend/src/libraries/explorer-wamp/blocks.js index d6b431e0b..935acb650 100644 --- a/frontend/src/libraries/explorer-wamp/blocks.js +++ b/frontend/src/libraries/explorer-wamp/blocks.js @@ -1,110 +1,114 @@ -import { call } from "."; +import { ExplorerApi } from "."; -export async function searchBlocks(keyword, height = -1, limit = 15) { - try { - return await call(".select", [ - `SELECT blocks.*, COUNT(transactions.hash) as transactionsCount - FROM ( - SELECT blocks.hash, blocks.height, blocks.timestamp, blocks.prev_hash as prevHash FROM blocks - WHERE blocks.height LIKE :keyword AND blocks.height < :height - ) as blocks - LEFT JOIN transactions ON transactions.block_hash = blocks.hash - GROUP BY blocks.hash - ORDER BY blocks.height DESC`, - { - keyword: `${keyword}%`, - height: height === -1 ? "MAX(blocks.height)" : height, - limit - } - ]); - } catch (error) { - console.error("Blocks.searchBlocks failed to fetch data due to:"); - console.error(error); - throw error; +export default class BlocksApi extends ExplorerApi { + async searchBlocks(keyword, height = -1, limit = 15) { + try { + return await this.call("select", [ + `SELECT blocks.*, COUNT(transactions.hash) as transactionsCount + FROM ( + SELECT blocks.hash, blocks.height, blocks.timestamp, blocks.prev_hash as prevHash FROM blocks + WHERE blocks.height LIKE :keyword AND blocks.height < :height + ) as blocks + LEFT JOIN transactions ON transactions.block_hash = blocks.hash + GROUP BY blocks.hash + ORDER BY blocks.height DESC`, + { + keyword: `${keyword}%`, + height: height === -1 ? "MAX(blocks.height)" : height, + limit + } + ]); + } catch (error) { + console.error("Blocks.searchBlocks failed to fetch data due to:"); + console.error(error); + throw error; + } } -} -export async function getTotal() { - try { - const _ = await call(".select", [ - `SELECT COUNT(blocks.hash) AS total FROM blocks` - ]); - return _[0].total; - } catch (error) { - console.error("Blocks.getTotal failed to fetch data due to:"); - console.error(error); - throw error; + async getTotal() { + try { + return await this.call("select", [ + `SELECT COUNT(blocks.hash) AS total FROM blocks` + ]).then(it => it[0].total); + } catch (error) { + console.error("Blocks.getTotal failed to fetch data due to:"); + console.error(error); + throw error; + } } -} -export async function getLatestBlocksInfo(limit = 15) { - try { - return await call(".select", [ - `SELECT blocks.*, COUNT(transactions.hash) as transactionsCount - FROM ( - SELECT blocks.hash, blocks.height, blocks.timestamp, blocks.prev_hash as prevHash FROM blocks - ORDER BY blocks.height DESC - LIMIT :limit - ) as blocks - LEFT JOIN transactions ON transactions.block_hash = blocks.hash - GROUP BY blocks.hash - ORDER BY blocks.height DESC`, - { - limit - } - ]); - } catch (error) { - console.error("Blocks.getBlocksInfo[] failed to fetch data due to:"); - console.error(error); - throw error; + async getLatestBlocksInfo(limit = 15) { + try { + return await this.call("select", [ + `SELECT blocks.*, COUNT(transactions.hash) as transactionsCount + FROM ( + SELECT blocks.hash, blocks.height, blocks.timestamp, blocks.prev_hash as prevHash FROM blocks + ORDER BY blocks.height DESC + LIMIT :limit + ) as blocks + LEFT JOIN transactions ON transactions.block_hash = blocks.hash + GROUP BY blocks.hash + ORDER BY blocks.height DESC`, + { + limit + } + ]); + } catch (error) { + console.error("Blocks.getBlocksInfo[] failed to fetch data due to:"); + console.error(error); + throw error; + } } -} -export async function getBlockInfo(hash) { - try { - const block = await call(".select", [ - `SELECT blocks.*, COUNT(transactions.hash) as transactionsCount - FROM ( - SELECT blocks.hash, blocks.height, blocks.timestamp, blocks.prev_hash as prevHash - FROM blocks - WHERE blocks.hash = :hash - ) as blocks - LEFT JOIN transactions ON transactions.block_hash = blocks.hash`, - { - hash - } - ]); + async getBlockInfo(hash) { + try { + const block = await this.call("select", [ + `SELECT blocks.*, COUNT(transactions.hash) as transactionsCount + FROM ( + SELECT blocks.hash, blocks.height, blocks.timestamp, blocks.prev_hash as prevHash + FROM blocks + WHERE blocks.hash = :hash + ) as blocks + LEFT JOIN transactions ON transactions.block_hash = blocks.hash`, + { + hash + } + ]).then(it => (it[0].hash !== null ? it[0] : null)); - return block[0]; - } catch (error) { - console.error("Blocks.getBlockInfo failed to fetch data due to:"); - console.error(error); - throw error; + if (block === null) { + throw new Error("block not found"); + } + return block; + } catch (error) { + console.error("Blocks.getBlockInfo failed to fetch data due to:"); + console.error(error); + throw error; + } } -} -export async function getPreviousBlocks(lastBlockHeight, limit = 15) { - try { - return await call(".select", [ - `SELECT blocks.*, COUNT(transactions.hash) as transactionsCount - FROM ( - SELECT blocks.hash, blocks.height, blocks.timestamp, blocks.prev_hash as prevHash - FROM blocks - WHERE blocks.height < :height - ORDER BY blocks.height DESC - LIMIT :limit - ) as blocks - LEFT JOIN transactions ON transactions.block_hash = blocks.hash - GROUP BY blocks.hash - ORDER BY blocks.height DESC`, - { - height: lastBlockHeight, - limit - } - ]); - } catch (error) { - console.error("Blocks.getPreviousBlocks failed to fetch data due to:"); - console.error(error); - throw error; + async getPreviousBlocks(lastBlockHeight, limit = 15) { + try { + return await this.call("select", [ + `SELECT blocks.*, COUNT(transactions.hash) as transactionsCount + FROM ( + SELECT blocks.hash, blocks.height, blocks.timestamp, blocks.prev_hash as prevHash + FROM blocks + WHERE blocks.height < :height + ORDER BY blocks.height DESC + LIMIT :limit + ) as blocks + LEFT JOIN transactions ON transactions.block_hash = blocks.hash + GROUP BY blocks.hash + ORDER BY blocks.height DESC`, + { + height: lastBlockHeight, + limit + } + ]); + } catch (error) { + console.error("Blocks.getPreviousBlocks failed to fetch data due to:"); + console.error(error); + throw error; + } } } diff --git a/frontend/src/libraries/explorer-wamp/details.js b/frontend/src/libraries/explorer-wamp/details.js index 253997ae1..f2df37781 100644 --- a/frontend/src/libraries/explorer-wamp/details.js +++ b/frontend/src/libraries/explorer-wamp/details.js @@ -1,34 +1,35 @@ -import { call } from "."; +import { ExplorerApi } from "."; -export async function getDetails() { - try { - const details = await call(".select", [ - `SELECT - total_accounts.accountsCount, - nodes.totalNodesCount, - online_nodes.onlineNodesCount, - transactions.lastDayTxCount, - last_block.lastBlockHeight, - ((transactions_per_second.tx_last_10_seconds + 9) / 10) as transactionsPerSecond - FROM - (SELECT COUNT(*) as totalNodesCount FROM nodes) as nodes, - (SELECT COUNT(*) as onlineNodesCount FROM nodes WHERE last_seen > (strftime('%s','now') - 60) * 1000) as online_nodes, - ( - SELECT COUNT(*) as lastDayTxCount FROM transactions - LEFT JOIN blocks ON blocks.hash = transactions.block_hash - WHERE blocks.timestamp > (strftime('%s','now') - 60 * 60 * 24) * 1000 - ) as transactions, - (SELECT COUNT(transactions.hash) as tx_last_10_seconds FROM transactions - LEFT JOIN blocks ON blocks.hash = transactions.block_hash - WHERE blocks.timestamp > (strftime('%s','now') - 10) * 1000 - ) as transactions_per_second, - (SELECT height as lastBlockHeight FROM blocks ORDER BY height DESC LIMIT 1) as last_block, - (SELECT COUNT(DISTINCT signer_id) as accountsCount FROM transactions) as total_accounts` - ]); - return details[0]; - } catch (error) { - console.error("Details.getDetails failed to fetch data due to:"); - console.error(error); - throw error; +export default class DetailsApi extends ExplorerApi { + async getDetails() { + try { + return await this.call("select", [ + `SELECT + total_accounts.accountsCount, + nodes.totalNodesCount, + online_nodes.onlineNodesCount, + transactions.lastDayTxCount, + last_block.lastBlockHeight, + ((transactions_per_second.tx_last_10_seconds + 9) / 10) as transactionsPerSecond + FROM + (SELECT COUNT(*) as totalNodesCount FROM nodes) as nodes, + (SELECT COUNT(*) as onlineNodesCount FROM nodes WHERE last_seen > (strftime('%s','now') - 60) * 1000) as online_nodes, + ( + SELECT COUNT(*) as lastDayTxCount FROM transactions + LEFT JOIN blocks ON blocks.hash = transactions.block_hash + WHERE blocks.timestamp > (strftime('%s','now') - 60 * 60 * 24) * 1000 + ) as transactions, + (SELECT COUNT(transactions.hash) as tx_last_10_seconds FROM transactions + LEFT JOIN blocks ON blocks.hash = transactions.block_hash + WHERE blocks.timestamp > (strftime('%s','now') - 10) * 1000 + ) as transactions_per_second, + (SELECT height as lastBlockHeight FROM blocks ORDER BY height DESC LIMIT 1) as last_block, + (SELECT COUNT(DISTINCT signer_id) as accountsCount FROM transactions) as total_accounts` + ]).then(it => it[0]); + } catch (error) { + console.error("Details.getDetails failed to fetch data due to:"); + console.error(error); + throw error; + } } } diff --git a/frontend/src/libraries/explorer-wamp/index.ts b/frontend/src/libraries/explorer-wamp/index.ts index f42069d52..b49b6a907 100644 --- a/frontend/src/libraries/explorer-wamp/index.ts +++ b/frontend/src/libraries/explorer-wamp/index.ts @@ -7,95 +7,118 @@ interface IPromisePair { reject: (value?: string) => void; } -const awaitingOnSession: Array = []; +export class ExplorerApi { + static awaitingOnSession: Array = []; -const subscriptions: Record< - string, - [autobahn.SubscribeHandler, autobahn.ISubscribeOptions | undefined] -> = {}; + static subscriptions: Record< + string, + [autobahn.SubscribeHandler, autobahn.ISubscribeOptions | undefined] + > = {}; -let wampNearExplorerUrl: string; + static wamp: autobahn.Connection; -if (typeof window === "undefined") { - const { serverRuntimeConfig } = getConfig(); - wampNearExplorerUrl = serverRuntimeConfig.wampNearExplorerUrl; -} else { - const { publicRuntimeConfig } = getConfig(); - wampNearExplorerUrl = publicRuntimeConfig.wampNearExplorerUrl; -} + apiPrefix: string; -const wamp = new autobahn.Connection({ - url: wampNearExplorerUrl, - realm: "near-explorer", - retry_if_unreachable: true, - max_retries: Number.MAX_SAFE_INTEGER, - max_retry_delay: 10 -}); - -// Establish and handle concurrent requests to establish WAMP connection. -function getWampSession(): Promise { - return new Promise( - ( - resolve: (value?: autobahn.Session) => void, - reject: (value?: string) => void - ) => { - if (wamp.transport.info.type === "websocket") { - // The connection is open/opening - if (wamp.session && wamp.session.isOpen) { - // Resolve the established session as it is ready - resolve(wamp.session); - } else { - // Push the promise resolvers on a queue - awaitingOnSession.push({ resolve, reject }); - } + constructor(apiPrefixSource?: any) { + const { publicRuntimeConfig, serverRuntimeConfig } = getConfig(); + + if (ExplorerApi.wamp === undefined) { + let wampNearExplorerUrl: string; + if (typeof window === "undefined") { + wampNearExplorerUrl = serverRuntimeConfig.wampNearExplorerUrl; } else { - // Establish new session - awaitingOnSession.push({ resolve, reject }); - - wamp.onopen = session => { - Object.entries(subscriptions).forEach(([topic, [handler, options]]) => - session.subscribe(topic, handler, options) - ); - while (awaitingOnSession.length > 0) { - awaitingOnSession.pop()!.resolve(session); - } - }; + wampNearExplorerUrl = publicRuntimeConfig.wampNearExplorerUrl; + } - wamp.onclose = reason => { - while (awaitingOnSession.length > 0) { - awaitingOnSession.pop()!.reject(reason); + ExplorerApi.wamp = new autobahn.Connection({ + url: wampNearExplorerUrl, + realm: "near-explorer", + retry_if_unreachable: true, + max_retries: Number.MAX_SAFE_INTEGER, + max_retry_delay: 10 + }); + } + + if (apiPrefixSource === undefined) { + this.apiPrefix = location.host; + } else if (typeof apiPrefixSource === "string") { + this.apiPrefix = apiPrefixSource; + } else if ("socket" in apiPrefixSource) { + this.apiPrefix = apiPrefixSource.headers.host; + } else { + throw Error( + `Unknown apiPrefixSource ${apiPrefixSource} (of type ${typeof apiPrefixSource})` + ); + } + + const { nearNetworkAliases } = publicRuntimeConfig; + if (this.apiPrefix in nearNetworkAliases) { + this.apiPrefix = nearNetworkAliases[this.apiPrefix].name; + } + } + + // Establish and handle concurrent requests to establish WAMP connection. + static getWampSession(): Promise { + return new Promise( + ( + resolve: (value?: autobahn.Session) => void, + reject: (value?: string) => void + ) => { + if (ExplorerApi.wamp.transport.info.type === "websocket") { + // The connection is open/opening + if (ExplorerApi.wamp.session && ExplorerApi.wamp.session.isOpen) { + // Resolve the established session as it is ready + resolve(ExplorerApi.wamp.session); + } else { + // Push the promise resolvers on a queue + ExplorerApi.awaitingOnSession.push({ resolve, reject }); } - return false; - }; + } else { + // Establish new session + ExplorerApi.awaitingOnSession.push({ resolve, reject }); + + ExplorerApi.wamp.onopen = session => { + Object.entries(ExplorerApi.subscriptions).forEach( + ([topic, [handler, options]]) => + session.subscribe(topic, handler, options) + ); + while (ExplorerApi.awaitingOnSession.length > 0) { + ExplorerApi.awaitingOnSession.pop()!.resolve(session); + } + }; + + ExplorerApi.wamp.onclose = reason => { + while (ExplorerApi.awaitingOnSession.length > 0) { + ExplorerApi.awaitingOnSession.pop()!.reject(reason); + } + return false; + }; - wamp.open(); + ExplorerApi.wamp.open(); + } } - } - ); -} + ); + } -export async function subscribe( - topic: string, - handler: autobahn.SubscribeHandler, - options?: autobahn.ISubscribeOptions -): Promise { - if (topic[0] === ".") { - topic = "com.nearprotocol.explorer" + topic; + async subscribe( + topic: string, + handler: autobahn.SubscribeHandler, + options?: autobahn.ISubscribeOptions + ): Promise { + topic = `com.nearprotocol.${this.apiPrefix}.explorer.${topic}`; + ExplorerApi.subscriptions[topic] = [handler, options]; + const session = await ExplorerApi.getWampSession(); + return await session.subscribe(topic, handler, options); } - subscriptions[topic] = [handler, options]; - const session = await getWampSession(); - return await session.subscribe(topic, handler, options); -} -export async function call( - procedure: string, - args?: any[] | any, - kwargs?: any, - options?: autobahn.ICallOptions -): Promise { - if (procedure[0] === ".") { - procedure = "com.nearprotocol.explorer" + procedure; + async call( + procedure: string, + args?: any[] | any, + kwargs?: any, + options?: autobahn.ICallOptions + ): Promise { + procedure = `com.nearprotocol.${this.apiPrefix}.explorer.${procedure}`; + const session = await ExplorerApi.getWampSession(); + return (await session.call(procedure, args, kwargs, options)) as T; } - const session = await getWampSession(); - return (await session.call(procedure, args, kwargs, options)) as T; } diff --git a/frontend/src/libraries/explorer-wamp/nodes.js b/frontend/src/libraries/explorer-wamp/nodes.js index 8e71b144a..de92055f2 100644 --- a/frontend/src/libraries/explorer-wamp/nodes.js +++ b/frontend/src/libraries/explorer-wamp/nodes.js @@ -1,15 +1,17 @@ -import { call } from "."; +import { ExplorerApi } from "."; -export async function getNodesInfo() { - try { - return await call(".select", [ - `SELECT ip_address as ipAddress, moniker, account_id as accountId, node_id as nodeId, last_seen as lastSeen, last_height as lastHeight - FROM nodes - ORDER BY lastSeen DESC` - ]); - } catch (error) { - console.error("Nodes.getNodesInfo[] failed to fetch data due to:"); - console.error(error); - throw error; +export default class NodesApi extends ExplorerApi { + async getNodesInfo() { + try { + return await this.call("select", [ + `SELECT ip_address as ipAddress, moniker, account_id as accountId, node_id as nodeId, last_seen as lastSeen, last_height as lastHeight + FROM nodes + ORDER BY lastSeen DESC` + ]); + } catch (error) { + console.error("Nodes.getNodesInfo[] failed to fetch data due to:"); + console.error(error); + throw error; + } } } diff --git a/frontend/src/libraries/explorer-wamp/transactions.ts b/frontend/src/libraries/explorer-wamp/transactions.ts index 21b1e6bbf..649ee7b86 100644 --- a/frontend/src/libraries/explorer-wamp/transactions.ts +++ b/frontend/src/libraries/explorer-wamp/transactions.ts @@ -1,4 +1,4 @@ -import { call } from "."; +import { ExplorerApi } from "."; export interface TransactionInfo { hash: string; @@ -15,7 +15,12 @@ export interface DeleteAccount {} export interface DeployContract {} -export interface FunctionCall {} +export interface FunctionCall { + args: string; + deposit: string; + gas: number; + method_name: string; +} export interface Transfer { deposit: string; @@ -51,73 +56,130 @@ interface StringActions { } export interface Actions { - actions: Action[]; + actions: (Action | keyof Action)[]; +} + +export interface ReceiptSuccessValue { + SuccessValue: string | null; +} + +export interface ReceiptFailure { + Failure: any; +} + +export type ReceiptStatus = ReceiptSuccessValue | ReceiptFailure | string; + +export interface ReceiptOutcome { + logs: string[]; + receipt_ids: string[]; + status: ReceiptStatus; + gas_burnt: number; +} + +export interface Receipt { + id: string; + outcome: ReceiptOutcome; } -export type Transaction = TransactionInfo & Actions; +export interface Receipts { + receipts?: Receipt[]; +} + +export type Transaction = TransactionInfo & Actions & Receipts; export interface FilterArgs { signerId?: string; receiverId?: string; transactionHash?: string; blockHash?: string; - limit?: number; + tail?: boolean; + limit: number; } -export async function getTransactions( - filters: FilterArgs -): Promise { - const { signerId, receiverId, transactionHash, blockHash } = filters; - const whereClause = []; - if (signerId) { - whereClause.push(`transactions.signer_id = :signerId`); - } - if (receiverId) { - whereClause.push(`transactions.receiver_id = :receiverId`); - } - if (transactionHash) { - whereClause.push(`transactions.hash = :transactionHash`); - } - if (blockHash) { - whereClause.push(`transactions.block_hash = :blockHash`); - } - if (!filters.limit) { - filters.limit = 10; +export default class TransactionsApi extends ExplorerApi { + async getTransactions(filters: FilterArgs): Promise { + const { signerId, receiverId, transactionHash, blockHash } = filters; + const whereClause = []; + if (signerId) { + whereClause.push(`transactions.signer_id = :signerId`); + } + if (receiverId) { + whereClause.push(`transactions.receiver_id = :receiverId`); + } + if (transactionHash) { + whereClause.push(`transactions.hash = :transactionHash`); + } + if (blockHash) { + whereClause.push(`transactions.block_hash = :blockHash`); + } + try { + const transactions = await this.call< + (TransactionInfo & (StringActions | Actions))[] + >("select", [ + `SELECT transactions.hash, transactions.signer_id as signerId, transactions.receiver_id as receiverId, transactions.actions, transactions.block_hash as blockHash, blocks.timestamp as blockTimestamp + FROM transactions + LEFT JOIN blocks ON blocks.hash = transactions.block_hash + ${whereClause.length > 0 ? `WHERE ${whereClause.join(" OR ")}` : ""} + ORDER BY blocks.height ${filters.tail ? "DESC" : ""} + LIMIT :limit`, + filters + ]); + if (filters.tail) { + transactions.reverse(); + } + transactions.forEach(transaction => { + transaction.status = "Completed"; + try { + transaction.actions = JSON.parse(transaction.actions as string); + } catch {} + }); + return transactions as Transaction[]; + } catch (error) { + console.error( + "Transactions.getTransactionsInfo failed to fetch data due to:" + ); + console.error(error); + throw error; + } } - try { - const transactions = await call< - (TransactionInfo & (StringActions | Actions))[] - >(".select", [ - `SELECT transactions.hash, transactions.signer_id as signerId, transactions.receiver_id as receiverId, transactions.actions, transactions.block_hash as blockHash, blocks.timestamp as blockTimestamp - FROM transactions - LEFT JOIN blocks ON blocks.hash = transactions.block_hash - ${whereClause.length > 0 ? `WHERE ${whereClause.join(" OR ")}` : ""} - ORDER BY blocks.height DESC - LIMIT :limit`, - filters - ]); - transactions.forEach(transaction => { - transaction.status = "Completed"; - try { - transaction.actions = JSON.parse(transaction.actions as string); - } catch {} - }); - return transactions as Transaction[]; - } catch (error) { - console.error( - "Transactions.getTransactionsInfo failed to fetch data due to:" - ); - console.error(error); - throw error; - } -} -export async function getLatestTransactionsInfo(): Promise { - return getTransactions({}); -} + async getLatestTransactionsInfo(): Promise { + return this.getTransactions({ tail: true, limit: 10 }); + } -export async function getTransactionInfo( - transactionHash: string -): Promise { - return (await getTransactions({ transactionHash, limit: 1 }))[0] || null; + async getTransactionInfo( + transactionHash: string + ): Promise { + try { + let transactionInfo = await this.getTransactions({ + transactionHash, + limit: 1 + }).then(it => it[0] || null); + + if (transactionInfo === null) { + transactionInfo = { + status: "Not started", + hash: transactionHash, + signerId: "", + receiverId: "", + blockHash: "", + blockTimestamp: 0, + actions: [] + }; + } else { + const transactionExtraInfo = await this.call("nearcore-tx", [ + transactionHash, + transactionInfo.signerId + ]); + transactionInfo.receipts = transactionExtraInfo.receipts as Receipt[]; + } + return transactionInfo; + } catch (error) { + console.error( + "Transactions.getTransactionInfo failed to fetch data due to:" + ); + console.error(error); + throw error; + } + } } diff --git a/frontend/src/pages/_app.jsx b/frontend/src/pages/_app.jsx index 0d7f2087c..f216c2c63 100644 --- a/frontend/src/pages/_app.jsx +++ b/frontend/src/pages/_app.jsx @@ -10,6 +10,10 @@ import DataProvider from "../components/utils/DataProvider"; import "bootstrap/dist/css/bootstrap.min.css"; +const { + publicRuntimeConfig: { nearNetworks, nearNetworkAliases, googleAnalytics } +} = getConfig(); + export default class extends App { static async getInitialProps(appContext) { // WARNING: Do not remove this getInitialProps implementation as it @@ -22,14 +26,21 @@ export default class extends App { // > `` with `getInitialProps`. // // https://github.com/zeit/next.js#runtime-configuration - return { ...(await App.getInitialProps(appContext)) }; + + let currentNearNetwork; + if (typeof window === "undefined") { + currentNearNetwork = nearNetworkAliases[appContext.ctx.req.headers.host]; + } else { + currentNearNetwork = nearNetworkAliases[window.location.host]; + } + return { + currentNearNetwork, + ...(await App.getInitialProps({ ...appContext, currentNearNetwork })) + }; } render() { const { Component, pageProps } = this.props; - const { - publicRuntimeConfig: { googleAnalytics } - } = getConfig(); return ( <> @@ -40,7 +51,10 @@ export default class extends App { href="/static/favicon.ico" /> - +
diff --git a/frontend/src/pages/accounts/[id].jsx b/frontend/src/pages/accounts/[id].jsx index 6a9efc2a5..e88ce30bc 100644 --- a/frontend/src/pages/accounts/[id].jsx +++ b/frontend/src/pages/accounts/[id].jsx @@ -4,16 +4,16 @@ import React from "react"; import TransactionIcon from "../../../public/static/images/icon-t-transactions.svg"; -import * as AccountApi from "../../libraries/explorer-wamp/accounts"; +import AccountsApi from "../../libraries/explorer-wamp/accounts"; import AccountDetails from "../../components/accounts/AccountDetails"; import Transactions from "../../components/transactions/Transactions"; import Content from "../../components/utils/Content"; export default class extends React.Component { - static async getInitialProps({ query: { id } }) { + static async getInitialProps({ req, query: { id } }) { try { - return await AccountApi.getAccountInfo(id); + return await new AccountsApi(req).getAccountInfo(id); } catch (err) { return { id, err }; } @@ -37,7 +37,7 @@ export default class extends React.Component { icon={} title={

Transactions

} > - + ); diff --git a/frontend/src/pages/api/nodes.js b/frontend/src/pages/api/nodes.js index fb3419504..ef9b21e21 100644 --- a/frontend/src/pages/api/nodes.js +++ b/frontend/src/pages/api/nodes.js @@ -1,8 +1,8 @@ -import { call } from "../../libraries/explorer-wamp"; +import { ExplorerApi } from "../../libraries/explorer-wamp"; export default async function(req, res) { try { - await call(".node-telemetry", [ + await new ExplorerApi(req).call("node-telemetry", [ { ...req.body, ip_address: req.headers["x-forwarded-for"] || req.socket.remoteAddress diff --git a/frontend/src/pages/blocks/[hash].jsx b/frontend/src/pages/blocks/[hash].jsx index 5b0e939e6..3a70df87c 100644 --- a/frontend/src/pages/blocks/[hash].jsx +++ b/frontend/src/pages/blocks/[hash].jsx @@ -4,18 +4,18 @@ import React from "react"; import TransactionIcon from "../../../public/static/images/icon-t-transactions.svg"; -import * as BlockApi from "../../libraries/explorer-wamp/blocks"; +import BlocksApi from "../../libraries/explorer-wamp/blocks"; import BlockDetails from "../../components/blocks/BlockDetails"; import Transactions from "../../components/transactions/Transactions"; import Content from "../../components/utils/Content"; export default class extends React.Component { - static async getInitialProps({ query: { hash } }) { + static async getInitialProps({ req, query: { hash } }) { try { - return await BlockApi.getBlockInfo(hash); + return await new BlocksApi(req).getBlockInfo(hash); } catch (err) { - return {}; + return { hash, err }; } } @@ -26,18 +26,30 @@ export default class extends React.Component { Near Explorer | Block {`Block #${this.props.height}`}} + title={ +

{`Block ${ + this.props.height + ? `#${this.props.height}` + : `${this.props.hash.substring(0, 7)}...` + }`}

+ } border={false} > - -
- } - title={

Transactions

} - > - + {this.props.err ? ( + `Information is not available at the moment. Please, check if the block hash is correct or try later.` + ) : ( + + )}
+ {!this.props.err ? ( + } + title={

Transactions

} + > + +
+ ) : null} ); } diff --git a/frontend/src/pages/index.jsx b/frontend/src/pages/index.jsx index 983b74a89..7bc07cd17 100644 --- a/frontend/src/pages/index.jsx +++ b/frontend/src/pages/index.jsx @@ -3,9 +3,9 @@ import Head from "next/head"; import { useEffect, useContext } from "react"; import { Row, Col } from "react-bootstrap"; -import * as BlocksApi from "../libraries/explorer-wamp/blocks"; -import * as DetailsApi from "../libraries/explorer-wamp/details"; -import * as TransactionsApi from "../libraries/explorer-wamp/transactions"; +import BlocksApi from "../libraries/explorer-wamp/blocks"; +import DetailsApi from "../libraries/explorer-wamp/details"; +import TransactionsApi from "../libraries/explorer-wamp/transactions"; import DashboardHeader from "../components/dashboard/DashboardHeader"; import DashboardTransactions from "../components/dashboard/DashboardTransactions"; @@ -13,11 +13,13 @@ import DashboardBlocks from "../components/dashboard/DashboardBlocks"; import Content from "../components/utils/Content"; export default class extends React.Component { - static async getInitialProps() { + static async getInitialProps({ req }) { const ignoreErr = promise => promise.catch(() => null); - const details = ignoreErr(DetailsApi.getDetails()); - const blocks = ignoreErr(BlocksApi.getLatestBlocksInfo()); - const transactions = ignoreErr(TransactionsApi.getLatestTransactionsInfo()); + const details = ignoreErr(new DetailsApi(req).getDetails()); + const blocks = ignoreErr(new BlocksApi(req).getLatestBlocksInfo()); + const transactions = ignoreErr( + new TransactionsApi(req).getLatestTransactionsInfo() + ); return { details: await details, blocks: await blocks, diff --git a/frontend/src/pages/transactions/[hash].jsx b/frontend/src/pages/transactions/[hash].jsx index a18abb063..979b7fba6 100644 --- a/frontend/src/pages/transactions/[hash].jsx +++ b/frontend/src/pages/transactions/[hash].jsx @@ -1,16 +1,67 @@ import Head from "next/head"; +import React from "react"; + +import TransactionIcon from "../../../public/static/images/icon-t-transactions.svg"; + +import TransactionsApi from "../../libraries/explorer-wamp/transactions"; + +import ActionsList from "../../components/transactions/ActionsList"; +import ReceiptsList from "../../components/transactions/ReceiptsList"; +import TransactionDetails from "../../components/transactions/TransactionDetails"; +import Content from "../../components/utils/Content"; + export default class extends React.Component { - static async getInitialProps({ query: { hash } }) { - return { hash }; + static async getInitialProps({ req, query: { hash } }) { + try { + return await new TransactionsApi(req).getTransactionInfo(hash); + } catch (err) { + return { hash, err }; + } } render() { + const { hash } = this.props; return ( <> - Near Explorer | Transactions + Near Explorer | Transaction + {`Transaction: ${hash.substring(0, 7)}...${hash.substring( + hash.length - 4 + )}`} + } + border={false} + > + {this.props.err ? ( + `Information is not available at the moment. Please, check if the transaction hash is correct or try later.` + ) : ( + + )} + + {this.props.actions && ( + } + title={

Actions

} + > + +
+ )} + {this.props.receipts && ( + } + title={

Receipts

} + > + +
+ )} ); } diff --git a/frontend/src/pages/transactions/index.jsx b/frontend/src/pages/transactions/index.jsx index 83a8a301d..6864783a7 100644 --- a/frontend/src/pages/transactions/index.jsx +++ b/frontend/src/pages/transactions/index.jsx @@ -11,7 +11,7 @@ export default class extends React.Component { Near Explorer | Transactions Transactions}> - + );