From dee55b06afc4beb2b050329b0e5971f682ba50e9 Mon Sep 17 00:00:00 2001 From: Dmitry Shuranov Date: Tue, 28 Mar 2023 10:46:35 +0300 Subject: [PATCH 1/9] transactions/all: validation allows txs 18 --- src/services/transactions/all/repo/schema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/transactions/all/repo/schema.ts b/src/services/transactions/all/repo/schema.ts index de9fa1b6..3e6c4fdb 100644 --- a/src/services/transactions/all/repo/schema.ts +++ b/src/services/transactions/all/repo/schema.ts @@ -2,7 +2,7 @@ import { Joi } from '../../../../utils/validation'; export const result = Joi.object().keys({ uid: Joi.object().bignumber().required(), - tx_type: Joi.number().min(1).max(17).required(), + tx_type: Joi.number().min(1).max(18).required(), time_stamp: Joi.date().required(), id: Joi.string().base58().required(), }); From 866a690f949d63f49ddfc0c5053938a12d5979f0 Mon Sep 17 00:00:00 2001 From: Dmitry Shuranov Date: Tue, 4 Apr 2023 18:29:56 +0300 Subject: [PATCH 2/9] ethereum transactions basic support --- package-lock.json | 1231 +---------------- src/http/transactions/index.ts | 154 ++- .../_common/createResolver/types.d.ts | 66 +- src/services/index.ts | 9 + .../_common/commonFieldsSchemas.ts | 35 +- src/services/transactions/all/index.ts | 159 +-- .../transactions/ethereumLike/index.ts | 12 + .../transactions/ethereumLike/repo/index.ts | 65 + .../transactions/ethereumLike/repo/schema.ts | 8 + .../ethereumLike/repo/sql/filters.js | 42 + .../ethereumLike/repo/sql/index.js | 17 + .../ethereumLike/repo/sql/query.js | 24 + .../ethereumLike/repo/transformTxInfo.ts | 25 + .../transactions/ethereumLike/repo/types.ts | 41 + .../transactions/ethereumLike/types.ts | 30 + .../updateAssetInfo/repo/index.ts | 2 +- .../updateAssetInfo/repo/schema.ts | 10 - .../updateAssetInfo/transformTxInfo.ts | 12 - src/utils/db/knex/lib.js | 20 +- 19 files changed, 524 insertions(+), 1438 deletions(-) create mode 100644 src/services/transactions/ethereumLike/index.ts create mode 100644 src/services/transactions/ethereumLike/repo/index.ts create mode 100644 src/services/transactions/ethereumLike/repo/schema.ts create mode 100644 src/services/transactions/ethereumLike/repo/sql/filters.js create mode 100644 src/services/transactions/ethereumLike/repo/sql/index.js create mode 100644 src/services/transactions/ethereumLike/repo/sql/query.js create mode 100644 src/services/transactions/ethereumLike/repo/transformTxInfo.ts create mode 100644 src/services/transactions/ethereumLike/repo/types.ts create mode 100644 src/services/transactions/ethereumLike/types.ts delete mode 100644 src/services/transactions/updateAssetInfo/transformTxInfo.ts diff --git a/package-lock.json b/package-lock.json index 8c12cca2..ee90c14b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -721,12 +721,6 @@ "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", "dev": true }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, "accepts": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", @@ -776,15 +770,6 @@ "uri-js": "^4.2.2" } }, - "ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", - "dev": true, - "requires": { - "string-width": "^2.0.0" - } - }, "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", @@ -1147,12 +1132,6 @@ } } }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", @@ -1318,12 +1297,6 @@ "tweetnacl": "^0.14.3" } }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, "bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", @@ -1337,21 +1310,6 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, - "boxen": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", - "dev": true, - "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1491,12 +1449,6 @@ "rsvp": "^4.8.4" } }, - "capture-stack-trace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", - "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", - "dev": true - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1527,40 +1479,6 @@ "cowsay": "^1.1.9" } }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - } - } - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -1582,12 +1500,6 @@ } } }, - "cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", - "dev": true - }, "cli-color": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", @@ -1758,20 +1670,6 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "configstore": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", - "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", - "dev": true, - "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -1831,50 +1729,6 @@ "strip-eof": "^1.0.0" } }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "dev": true, - "requires": { - "capture-stack-trace": "^1.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "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" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } - }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", - "dev": true - }, "cssom": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", @@ -1957,12 +1811,6 @@ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -2101,21 +1949,6 @@ "webidl-conversions": "^4.0.2" } }, - "dot-prop": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -2448,21 +2281,6 @@ "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==", "dev": true }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.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" - } - }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -2790,614 +2608,66 @@ "write": "1.0.3" } }, - "flatted": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", - "dev": true - }, - "folktale": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/folktale/-/folktale-2.3.2.tgz", - "integrity": "sha512-+8GbtQBwEqutP0v3uajDDoN64K2ehmHd0cjlghhxh0WpcfPzAIjPA03e1VvHlxL02FVGR0A6lwXsNQKn3H1RNQ==" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "requires": { - "for-in": "^1.0.1" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true - } - } - }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "dev": true + }, + "folktale": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/folktale/-/folktale-2.3.2.tgz", + "integrity": "sha512-+8GbtQBwEqutP0v3uajDDoN64K2ehmHd0cjlghhxh0WpcfPzAIjPA03e1VvHlxL02FVGR0A6lwXsNQKn3H1RNQ==" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -3421,12 +2691,6 @@ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=" }, - "get-stream": { - "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -3460,36 +2724,6 @@ "path-is-absolute": "^1.0.0" } }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", - "dev": true, - "requires": { - "ini": "^1.3.4" - } - }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", @@ -3518,25 +2752,6 @@ "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", "dev": true }, - "got": { - "version": "6.7.1", - "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", - "dev": true, - "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - } - }, "graceful-fs": { "version": "4.1.11", "resolved": "http://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", @@ -3715,12 +2930,6 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", - "dev": true - }, "import-fresh": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", @@ -3731,12 +2940,6 @@ "resolve-from": "^4.0.0" } }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true - }, "import-local": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", @@ -3870,15 +3073,6 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -3890,15 +3084,6 @@ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "dev": true }, - "is-ci": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz", - "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", - "dev": true, - "requires": { - "ci-info": "^1.0.0" - } - }, "is-data-descriptor": { "version": "0.1.4", "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -3964,22 +3149,6 @@ "is-extglob": "^2.1.1" } }, - "is-installed-globally": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", - "dev": true, - "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" - } - }, - "is-npm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", - "dev": true - }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -3988,21 +3157,6 @@ "kind-of": "^3.0.2" } }, - "is-obj": { - "version": "1.0.1", - "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -4017,12 +3171,6 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", - "dev": true - }, "is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", @@ -4040,12 +3188,6 @@ "is-unc-path": "^1.0.0" } }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true - }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -5148,15 +4290,6 @@ "colornames": "0.0.2" } }, - "latest-version": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", - "dev": true, - "requires": { - "package-json": "^4.0.0" - } - }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -5263,12 +4396,6 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true - }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -5619,50 +4746,6 @@ "which": "^1.3.0" } }, - "nodemon": { - "version": "1.18.9", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.18.9.tgz", - "integrity": "sha512-oj/eEVTEI47pzYAjGkpcNw0xYwTl4XSTUQv2NPQI6PpN3b75PhpuYk3Vb3U80xHCyM2Jm+1j68ULHXl4OR3Afw==", - "dev": true, - "requires": { - "chokidar": "^2.0.4", - "debug": "^3.1.0", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", - "pstree.remy": "^1.1.6", - "semver": "^5.5.0", - "supports-color": "^5.2.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.2", - "update-notifier": "^2.5.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -5983,18 +5066,6 @@ "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", "dev": true }, - "package-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", - "dev": true, - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - } - }, "packet-reader": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", @@ -6050,12 +5121,6 @@ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -6306,12 +5371,6 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, "pretty-format": { "version": "24.5.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.5.0.tgz", @@ -6354,24 +5413,12 @@ "sisteransi": "^1.0.0" } }, - "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.31", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", "dev": true }, - "pstree.remy": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.6.tgz", - "integrity": "sha512-NdF35+QsqD7EgNEI5mkI/X+UwaxVEbQaz9f4IooEmMUv6ZPmlTQYGjBPJGgrlzNdjSvIy4MWMg6Q6vCgBO2K+w==", - "dev": true - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -6413,18 +5460,6 @@ "unpipe": "1.0.0" } }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, "react-is": { "version": "16.8.4", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.4.tgz", @@ -6467,17 +5502,6 @@ "util-deprecate": "~1.0.1" } }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, "realpath-native": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", @@ -6515,25 +5539,6 @@ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, - "registry-auth-token": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", - "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", - "dev": true, - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", - "dev": true, - "requires": { - "rc": "^1.0.1" - } - }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -6840,15 +5845,6 @@ "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true }, - "semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", - "dev": true, - "requires": { - "semver": "^5.0.3" - } - }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -7299,15 +6295,6 @@ "resolved": "https://registry.npmjs.org/tarn/-/tarn-1.1.5.tgz", "integrity": "sha512-PMtJ3HCLAZeedWjJPgGnCvcphbCOMbtZpjKgLq3qM5Qq9aQud+XHrL0WlrlgnTyS8U+jrjGbEXprFcQrxPy52g==" }, - "term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "dev": true, - "requires": { - "execa": "^0.7.0" - } - }, "test-exclude": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.1.0.tgz", @@ -7350,12 +6337,6 @@ "os-homedir": "^1.0.0" } }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true - }, "timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", @@ -7423,15 +6404,6 @@ "hoek": "5.x.x" } }, - "touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "requires": { - "nopt": "~1.0.10" - } - }, "tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", @@ -7606,15 +6578,6 @@ "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" }, - "undefsafe": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", - "integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=", - "dev": true, - "requires": { - "debug": "^2.2.0" - } - }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -7626,15 +6589,6 @@ "set-value": "^2.0.1" } }, - "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", - "dev": true, - "requires": { - "crypto-random-string": "^1.0.0" - } - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -7676,36 +6630,6 @@ } } }, - "unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", - "dev": true - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "update-notifier": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", - "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", - "dev": true, - "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -7725,15 +6649,6 @@ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "requires": { - "prepend-http": "^1.0.1" - } - }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -7869,15 +6784,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", - "dev": true, - "requires": { - "string-width": "^2.1.1" - } - }, "winston": { "version": "3.0.0-rc4", "resolved": "http://registry.npmjs.org/winston/-/winston-3.0.0-rc4.tgz", @@ -7960,17 +6866,6 @@ "mkdirp": "^0.5.1" } }, - "write-file-atomic": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", - "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, "ws": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", @@ -7980,12 +6875,6 @@ "async-limiter": "~1.0.0" } }, - "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", - "dev": true - }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", diff --git a/src/http/transactions/index.ts b/src/http/transactions/index.ts index fb5c7331..58da626d 100644 --- a/src/http/transactions/index.ts +++ b/src/http/transactions/index.ts @@ -2,11 +2,7 @@ import * as Router from 'koa-router'; import { ServiceMesh } from '../../services'; import commonFilters from '../_common/filters/filters'; import { Parser } from '../_common/filters/types'; -import { - createTransactionHttpHandlers, - parseGet, - parseMgetOrSearch, -} from './_common'; +import { createTransactionHttpHandlers, parseGet, parseMgetOrSearch } from './_common'; import { parseDataMgetOrSearch } from './parseDataMgetOrSearch'; const createParseRequest = ( @@ -22,81 +18,82 @@ export default (txsServices: ServiceMesh['transactions']) => { const all = createTransactionHttpHandlers( new Router(), '/transactions/all', - txsServices['all'], + txsServices.all, createParseRequest() ); - const alias = createTransactionHttpHandlers( + const genesis = createTransactionHttpHandlers( new Router(), - '/transactions/alias', - txsServices['alias'], - createParseRequest() + '/transactions/genesis', + txsServices.genesis, + createParseRequest({ + recipient: commonFilters.query, + }) ); - const burn = createTransactionHttpHandlers( + const payment = createTransactionHttpHandlers( new Router(), - '/transactions/burn', - txsServices['burn'], + '/transactions/payment', + txsServices.payment, createParseRequest({ - assetId: commonFilters.query, + recipient: commonFilters.query, }) ); - const data = createTransactionHttpHandlers( + const issue = createTransactionHttpHandlers( new Router(), - '/transactions/data', - txsServices['data'], - { - get: parseGet, - mgetOrSearch: parseDataMgetOrSearch, - } + '/transactions/issue', + txsServices.issue, + createParseRequest({ + assetId: commonFilters.query, + script: commonFilters.query, + }) ); - const exchange = createTransactionHttpHandlers( + const transfer = createTransactionHttpHandlers( new Router(), - '/transactions/exchange', - txsServices['exchange'], + '/transactions/transfer', + txsServices.transfer, createParseRequest({ - amountAsset: commonFilters.query, - matcher: commonFilters.query, - orderId: commonFilters.query, - priceAsset: commonFilters.query, + assetId: commonFilters.query, + recipient: commonFilters.query, }) ); - const genesis = createTransactionHttpHandlers( + const reissue = createTransactionHttpHandlers( new Router(), - '/transactions/genesis', - txsServices['genesis'], + '/transactions/reissue', + txsServices.reissue, createParseRequest({ - recipient: commonFilters.query, + assetId: commonFilters.query, }) ); - const invokeScript = createTransactionHttpHandlers( + const burn = createTransactionHttpHandlers( new Router(), - '/transactions/invoke-script', - txsServices['invokeScript'], + '/transactions/burn', + txsServices.burn, createParseRequest({ - dapp: commonFilters.query, - function: commonFilters.query, + assetId: commonFilters.query, }) ); - const issue = createTransactionHttpHandlers( + const exchange = createTransactionHttpHandlers( new Router(), - '/transactions/issue', - txsServices['issue'], + '/transactions/exchange', + txsServices.exchange, createParseRequest({ - assetId: commonFilters.query, - script: commonFilters.query, + amountAsset: commonFilters.query, + matcher: commonFilters.query, + orderId: commonFilters.query, + priceAsset: commonFilters.query, }) ); const lease = createTransactionHttpHandlers( new Router(), '/transactions/lease', - txsServices['lease'], + txsServices.lease, createParseRequest({ recipient: commonFilters.query, }) @@ -105,35 +102,52 @@ export default (txsServices: ServiceMesh['transactions']) => { const leaseCancel = createTransactionHttpHandlers( new Router(), '/transactions/lease-cancel', - txsServices['leaseCancel'], + txsServices.leaseCancel, createParseRequest({ recipient: commonFilters.query, }) ); + const alias = createTransactionHttpHandlers( + new Router(), + '/transactions/alias', + txsServices.alias, + createParseRequest() + ); + const massTransfer = createTransactionHttpHandlers( new Router(), '/transactions/mass-transfer', - txsServices['massTransfer'], + txsServices.massTransfer, createParseRequest({ assetId: commonFilters.query, recipient: commonFilters.query, }) ); - const payment = createTransactionHttpHandlers( + const data = createTransactionHttpHandlers( new Router(), - '/transactions/payment', - txsServices['payment'], + '/transactions/data', + txsServices.data, + { + get: parseGet, + mgetOrSearch: parseDataMgetOrSearch, + } + ); + + const setScript = createTransactionHttpHandlers( + new Router(), + '/transactions/set-script', + txsServices.setScript, createParseRequest({ - recipient: commonFilters.query, + script: commonFilters.query, }) ); - const reissue = createTransactionHttpHandlers( + const sponsorship = createTransactionHttpHandlers( new Router(), - '/transactions/reissue', - txsServices['reissue'], + '/transactions/sponsorship', + txsServices.sponsorship, createParseRequest({ assetId: commonFilters.query, }) @@ -142,49 +156,42 @@ export default (txsServices: ServiceMesh['transactions']) => { const setAssetScript = createTransactionHttpHandlers( new Router(), '/transactions/set-asset-script', - txsServices['setAssetScript'], + txsServices.setAssetScript, createParseRequest({ assetId: commonFilters.query, script: commonFilters.query, }) ); - const setScript = createTransactionHttpHandlers( + const invokeScript = createTransactionHttpHandlers( new Router(), - '/transactions/set-script', - txsServices['setScript'], + '/transactions/invoke-script', + txsServices.invokeScript, createParseRequest({ - script: commonFilters.query, + dapp: commonFilters.query, + function: commonFilters.query, }) ); - const sponsorship = createTransactionHttpHandlers( + const updateAssetInfo = createTransactionHttpHandlers( new Router(), - '/transactions/sponsorship', - txsServices['sponsorship'], + '/transactions/update-asset-info', + txsServices.updateAssetInfo, createParseRequest({ assetId: commonFilters.query, }) ); - const transfer = createTransactionHttpHandlers( + const ethereumLike = createTransactionHttpHandlers( new Router(), - '/transactions/transfer', - txsServices['transfer'], + '/transactions/ethereum-like', + txsServices['ethereumLike'], createParseRequest({ - assetId: commonFilters.query, - recipient: commonFilters.query, + type: commonFilters.query, + function: commonFilters.query, }) ); - const updateAssetInfo = createTransactionHttpHandlers( - new Router(), - '/transactions/update-asset-info', - txsServices['updateAssetInfo'], - createParseRequest({ - assetId: commonFilters.query, - }) - ); return subrouter.use( alias.routes(), all.routes(), @@ -204,5 +211,6 @@ export default (txsServices: ServiceMesh['transactions']) => { sponsorship.routes(), transfer.routes(), updateAssetInfo.routes(), + ethereumLike.routes() ); }; diff --git a/src/services/_common/createResolver/types.d.ts b/src/services/_common/createResolver/types.d.ts index cd1b238f..b63f6ae6 100644 --- a/src/services/_common/createResolver/types.d.ts +++ b/src/services/_common/createResolver/types.d.ts @@ -1,12 +1,7 @@ import { Task } from 'folktale/concurrency/task'; import { Result } from 'folktale/result'; import { Maybe } from 'folktale/maybe'; -import { - ValidationError, - ResolverError, - DbError, - Timeout, -} from '../../../errorHandling'; +import { ValidationError, ResolverError, DbError, Timeout } from '../../../errorHandling'; import { SearchedItems } from '../../../types'; @@ -15,46 +10,20 @@ export type EmitEvent = (name: string) => (object: A) => void; export type ValidateSync = (value: Value) => Result; export type ValidateAsync = (value: Value) => Task; -type CommonResolverDependencies< - ReqRaw, - ReqTransformed, - ResRaw, - ResTransformed - > = { - transformInput: (r: ReqRaw) => Result; - validateResult: ValidateSync; - emitEvent: EmitEvent; - }; +type CommonResolverDependencies = { + transformInput: (r: ReqRaw) => Result; + validateResult: ValidateSync; + emitEvent: EmitEvent; +}; -export type GetResolverDependencies< - ReqRaw, - ReqTransformed, - ResRaw, - ResTransformed - > = CommonResolverDependencies< - ReqRaw, - ReqTransformed, - ResRaw, - ResTransformed - > & { +export type GetResolverDependencies = + CommonResolverDependencies & { getData: (r: ReqTransformed) => Task>; - transformResult: ( - result: Maybe, - request: ReqRaw - ) => Maybe; + transformResult: (result: Maybe, request: ReqRaw) => Maybe; }; -export type MgetResolverDependencies< - ReqRaw, - ReqTransformed, - ResRaw, - ResTransformed - > = CommonResolverDependencies< - ReqRaw, - ReqTransformed, - ResRaw, - ResTransformed - > & { +export type MgetResolverDependencies = + CommonResolverDependencies & { getData: (r: ReqTransformed) => Task[]>; transformResult: ( result: Maybe[], @@ -62,17 +31,8 @@ export type MgetResolverDependencies< ) => Maybe[]; }; -export type SearchResolverDependencies< - ReqRaw, - ReqTransformed, - ResRaw, - ResTransformed - > = CommonResolverDependencies< - ReqRaw, - ReqTransformed, - ResRaw, - ResTransformed - > & { +export type SearchResolverDependencies = + CommonResolverDependencies & { getData: (r: ReqTransformed) => Task; transformResult: ( results: ResRaw[], diff --git a/src/services/index.ts b/src/services/index.ts index 97a9c6b4..a92bfda5 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -83,6 +83,10 @@ import createTransferTxsRepo from './transactions/transfer/repo'; import createUpdateAssetInfoTxsService from './transactions/updateAssetInfo'; import { UpdateAssetInfoTxsService } from './transactions/updateAssetInfo/types'; import createUpdateAssetInfoTxsRepo from './transactions/updateAssetInfo/repo'; +// ethereum-like txs +import createEthereumLikeTxsService from './transactions/ethereumLike'; +import { EthereumLikeTxsService } from './transactions/ethereumLike/types'; +import createEthereumLikeTxsRepo from './transactions/ethereumLike/repo'; import createRateService, { RateCacheImpl, RatesMgetService } from './rates'; import { RateCache } from './rates/repo'; @@ -149,6 +153,7 @@ export type ServiceMesh = { sponsorship: SponsorshipTxsService; transfer: TransferTxsService; updateAssetInfo: UpdateAssetInfoTxsService; + ethereumLike: EthereumLikeTxsService; }; }; @@ -251,6 +256,8 @@ export default ({ updateAssetInfoRepo, assets ); + const ethereumLikeRepo = createEthereumLikeTxsRepo(commonDeps); + const ethereumLikeTxs = createEthereumLikeTxsService(ethereumLikeRepo, assets); const rateRepo = new RemoteRateRepo(commonDeps.drivers.pg); @@ -299,6 +306,7 @@ export default ({ 15: setAssetScriptTxs, 16: invokeScriptTxs, 17: updateAssetInfoTxs, + 18: ethereumLikeTxs, }); return { @@ -325,6 +333,7 @@ export default ({ setAssetScript: setAssetScriptTxs, invokeScript: invokeScriptTxs, updateAssetInfo: updateAssetInfoTxs, + ethereumLike: ethereumLikeTxs, }, matchers: { rates, diff --git a/src/services/transactions/_common/commonFieldsSchemas.ts b/src/services/transactions/_common/commonFieldsSchemas.ts index 0a6ee81b..0a9c6006 100644 --- a/src/services/transactions/_common/commonFieldsSchemas.ts +++ b/src/services/transactions/_common/commonFieldsSchemas.ts @@ -1,35 +1,16 @@ import { Joi } from '../../../utils/validation'; export default { - uid: Joi.object() - .bignumber() - .required(), - id: Joi.string() - .base58() - .required(), + uid: Joi.object().bignumber().required(), + id: Joi.string().base58().required(), height: Joi.number().required(), - tx_type: Joi.number() - .min(1) - .max(17) - .required(), - tx_version: Joi.number() - .required() - .allow(null), - fee: Joi.object() - .bignumber() - .required(), + tx_type: Joi.number().min(1).max(18).required(), + tx_version: Joi.number().required().allow(null), + fee: Joi.object().bignumber().required(), time_stamp: Joi.date().required(), - signature: Joi.string() - .base58() - .required() - .allow(null), + signature: Joi.string().base58().required().allow(null), proofs: Joi.array().required(), status: Joi.string().required(), - - sender: Joi.string() - .base58() - .required(), - sender_public_key: Joi.string() - .base58() - .required(), + sender: Joi.string().base58().required(), + sender_public_key: Joi.string().base58().required(), }; diff --git a/src/services/transactions/all/index.ts b/src/services/transactions/all/index.ts index ff4a5102..390d7ff7 100644 --- a/src/services/transactions/all/index.ts +++ b/src/services/transactions/all/index.ts @@ -29,6 +29,7 @@ import { SponsorshipTxsService } from '../sponsorship/types'; import { SetAssetScriptTxsService } from '../setAssetScript/types'; import { InvokeScriptTxsService } from '../invokeScript/types'; import { UpdateAssetInfoTxsService } from '../updateAssetInfo/types'; +import { EthereumLikeTxsService } from '../ethereumLike/types'; import { AllTxsRepo, AllTxsGetRequest, @@ -56,6 +57,7 @@ type AllTxsServiceDep = { 15: SetAssetScriptTxsService; 16: InvokeScriptTxsService; 17: UpdateAssetInfoTxsService; + 18: EthereumLikeTxsService; }; export type AllTxsServiceGetRequest = ServiceGetRequest; @@ -63,14 +65,8 @@ export type AllTxsServiceMgetRequest = ServiceMgetRequest; export type AllTxsServiceSearchRequest = AllTxsSearchRequest; export type AllTxsService = { - get: Service< - AllTxsServiceGetRequest & WithMoneyFormat, - Maybe - >; - mget: Service< - AllTxsServiceMgetRequest & WithMoneyFormat, - Maybe[] - >; + get: Service>; + mget: Service[]>; search: Service< AllTxsServiceSearchRequest & WithMoneyFormat, SearchedItems @@ -81,83 +77,80 @@ export type AllTxsService = { // request by (id, timestamp) instead of just id // to ensure correct tx response even if // id is duplicated (happens in payment, alias txs) -export default (repo: AllTxsRepo) => ( - txsServices: AllTxsServiceDep -): AllTxsService => ({ - get: (req) => - repo - .get(req.id) //Task tx - .chain((m) => - m.matchWith({ - Just: ({ value }) => { - return txsServices[value.type as keyof AllTxsServiceDep].get({ - id: value.id, - moneyFormat: req.moneyFormat, - }); - }, - Nothing: () => taskOf(emptyOf()), - }) - ), +export default (repo: AllTxsRepo) => + (txsServices: AllTxsServiceDep): AllTxsService => ({ + get: (req) => + repo + .get(req.id) //Task tx + .chain((m) => + m.matchWith({ + Just: ({ value }) => { + return txsServices[value.type as keyof AllTxsServiceDep].get({ + id: value.id, + moneyFormat: req.moneyFormat, + }); + }, + Nothing: () => taskOf(emptyOf()), + }) + ), - mget: (req) => - repo - .mget(req.ids) // Task tx[]. tx can have data: null - .chain((txsList: Maybe[]) => - waitAll( - txsList.map((m) => - m.matchWith({ - Just: ({ value }) => { - return txsServices[value.type as keyof AllTxsServiceDep].get({ - id: value.id, + mget: (req) => + repo + .mget(req.ids) // Task tx[]. tx can have data: null + .chain((txsList: Maybe[]) => + waitAll( + txsList.map((m) => + m.matchWith({ + Just: ({ value }) => { + return txsServices[value.type as keyof AllTxsServiceDep].get({ + id: value.id, + moneyFormat: req.moneyFormat, + }); + }, + Nothing: () => taskOf(emptyOf()), + }) + ) + ) + ), + + search: (req) => + repo.search(req).chain((txsList: SearchedItems) => + waitAll[]>( + pipe< + CommonTransactionInfo[], + Record, + [string, CommonTransactionInfo[]][], + Task[]>[] + >( + groupBy((t) => String(t.type)), + toPairs, + (tuples) => + tuples.map(([type, txs]) => { + return txsServices[type as unknown as keyof AllTxsServiceDep].mget({ + ids: txs.map((t) => t.id), moneyFormat: req.moneyFormat, }); - }, - Nothing: () => taskOf(emptyOf()), - }) - ) + }) + )(txsList.items) ) + .map((mss) => flatten>(mss)) + .map(collect((m) => m.getOrElse(undefined))) + .map((txs) => { + const s = indexBy( + (tx) => `${tx.id}:${tx.timestamp.valueOf()}`, + txsList.items + ); + return sort((a, b) => { + const aTxUid = s[`${a.id}:${a.timestamp.valueOf()}`]['txUid']; + const bTxUid = s[`${b.id}:${b.timestamp.valueOf()}`]['txUid']; + return req.sort === SortOrder.Ascending + ? aTxUid.minus(bTxUid).toNumber() + : bTxUid.minus(aTxUid).toNumber(); + }, txs); + }) + .map((txs) => ({ + ...txsList, + items: txs, + })) ), - - search: (req) => - repo.search(req).chain((txsList: SearchedItems) => - waitAll[]>( - pipe< - CommonTransactionInfo[], - Record, - [string, CommonTransactionInfo[]][], - Task[]>[] - >( - groupBy((t) => String(t.type)), - toPairs, - (tuples) => - tuples.map(([type, txs]) => { - return txsServices[ - (type as unknown) as keyof AllTxsServiceDep - ].mget({ - ids: txs.map((t) => t.id), - moneyFormat: req.moneyFormat, - }); - }) - )(txsList.items) - ) - .map((mss) => flatten>(mss)) - .map(collect((m) => m.getOrElse(undefined))) - .map((txs) => { - const s = indexBy( - (tx) => `${tx.id}:${tx.timestamp.valueOf()}`, - txsList.items - ); - return sort((a, b) => { - const aTxUid = s[`${a.id}:${a.timestamp.valueOf()}`]['txUid']; - const bTxUid = s[`${b.id}:${b.timestamp.valueOf()}`]['txUid']; - return req.sort === SortOrder.Ascending - ? aTxUid.minus(bTxUid).toNumber() - : bTxUid.minus(aTxUid).toNumber(); - }, txs); - }) - .map((txs) => ({ - ...txsList, - items: txs, - })) - ), -}); + }); diff --git a/src/services/transactions/ethereumLike/index.ts b/src/services/transactions/ethereumLike/index.ts new file mode 100644 index 00000000..f2508d35 --- /dev/null +++ b/src/services/transactions/ethereumLike/index.ts @@ -0,0 +1,12 @@ +import { withDecimalsProcessing } from '../../_common/transformation/withDecimalsProcessing'; +import { modifyFeeDecimals } from '../_common/modifyFeeDecimals'; +import { EthereumLikeTxsRepo } from './repo/types'; +import { AssetsService } from '../../assets'; +import { createService } from '../_common/createService'; +import { EthereumLikeTxsService } from './types'; + +export default ( + repo: EthereumLikeTxsRepo, + assetsService: AssetsService +): EthereumLikeTxsService => + withDecimalsProcessing(modifyFeeDecimals(assetsService), createService(repo)); diff --git a/src/services/transactions/ethereumLike/repo/index.ts b/src/services/transactions/ethereumLike/repo/index.ts new file mode 100644 index 00000000..b8839399 --- /dev/null +++ b/src/services/transactions/ethereumLike/repo/index.ts @@ -0,0 +1,65 @@ +import { propEq } from 'ramda'; + +import { CommonRepoDependencies } from '../../..'; +import { getByIdPreset } from '../../../_common/presets/pg/getById'; +import { mgetByIdsPreset } from '../../../_common/presets/pg/mgetByIds'; +import { searchPreset } from '../../../_common/presets/pg/search'; + +import { Cursor, serialize, deserialize } from '../../_common/cursor'; +import transformTxInfo from './transformTxInfo'; + +import { result as resultSchema } from './schema'; +import * as sql from './sql'; +import { + EthereumLikeTxsRepo, + EthereumLikeTxsSearchRequest, + EthereumLikeTxDbResponse, + EthereumLikeTx, +} from './types'; + +export default ({ + drivers: { pg }, + emitEvent, +}: CommonRepoDependencies): EthereumLikeTxsRepo => { + return { + get: getByIdPreset({ + name: 'transactions.ethereumLike.get', + sql: sql.get, + resultSchema, + transformResult: transformTxInfo, + })({ + pg, + emitEvent, + }), + + mget: mgetByIdsPreset({ + name: 'transactions.ethereumLike.mget', + matchRequestResult: propEq('id'), + sql: sql.mget, + resultSchema, + transformResult: transformTxInfo, + })({ + pg, + emitEvent, + }), + + search: searchPreset< + Cursor, + EthereumLikeTxsSearchRequest, + EthereumLikeTxDbResponse, + EthereumLikeTx + >({ + name: 'transactions.ethereumLike.search', + sql: sql.search, + resultSchema, + transformResult: transformTxInfo, + cursorSerialization: { + serialize, + deserialize, + }, + })({ + pg, + emitEvent, + }), + }; +}; diff --git a/src/services/transactions/ethereumLike/repo/schema.ts b/src/services/transactions/ethereumLike/repo/schema.ts new file mode 100644 index 00000000..95aa2e95 --- /dev/null +++ b/src/services/transactions/ethereumLike/repo/schema.ts @@ -0,0 +1,8 @@ +import { Joi } from '../../../../utils/validation'; +import commonFields from '../../_common/commonFieldsSchemas'; + +export const result = Joi.object().keys({ + ...commonFields, + bytes: Joi.binary().required(), + function_name: Joi.string().required().allow(null), +}); diff --git a/src/services/transactions/ethereumLike/repo/sql/filters.js b/src/services/transactions/ethereumLike/repo/sql/filters.js new file mode 100644 index 00000000..4b01f9a9 --- /dev/null +++ b/src/services/transactions/ethereumLike/repo/sql/filters.js @@ -0,0 +1,42 @@ +const { where, whereNull, whereNotNull } = require('../../../../../utils/db/knex'); + +const { createByTimeStamp, createByBlockTimeStamp } = require('../../../_common/sql'); +const { + id, + ids, + sender, + senders, + sort, + after, + limit, +} = require('../../../_common/sql/filters'); +const commonFiltersOrder = require('../../../_common/sql/filtersOrder'); + +const byTimeStamp = createByTimeStamp('txs_18'); + +const byBlockTimeStamp = createByBlockTimeStamp('txs_18'); + +module.exports = { + filters: { + id, + ids, + sender, + senders, + sort, + after, + limit, + + type: (transferOrInvocation) => + transferOrInvocation === 'transfer' + ? whereNull('function_name') + : whereNotNull('function_name'), + + function: (functionName) => where('function_name', functionName), + + timeStart: byTimeStamp('>='), + timeEnd: byTimeStamp('<='), + blockTimeStart: byBlockTimeStamp('>='), + blockTimeEnd: byBlockTimeStamp('<='), + }, + filtersOrder: [...commonFiltersOrder, 'timeStart', 'timeEnd', 'type', 'function'], +}; diff --git a/src/services/transactions/ethereumLike/repo/sql/index.js b/src/services/transactions/ethereumLike/repo/sql/index.js new file mode 100644 index 00000000..729210ce --- /dev/null +++ b/src/services/transactions/ethereumLike/repo/sql/index.js @@ -0,0 +1,17 @@ +const { createSql } = require('../../../_common/sql'); + +const { select, selectFromFiltered } = require('./query'); +const { filters, filtersOrder } = require('./filters'); + +const queryAfterFilters = { + get: selectFromFiltered, + mget: selectFromFiltered, + search: selectFromFiltered, +}; + +module.exports = createSql({ + query: select, + filters, + filtersOrder, + queryAfterFilters, +}); diff --git a/src/services/transactions/ethereumLike/repo/sql/query.js b/src/services/transactions/ethereumLike/repo/sql/query.js new file mode 100644 index 00000000..10d4ada0 --- /dev/null +++ b/src/services/transactions/ethereumLike/repo/sql/query.js @@ -0,0 +1,24 @@ +const pg = require('knex')({ client: 'pg' }); + +const select = pg({ t: 'txs_18' }); + +const selectFromFiltered = (filtered) => + filtered.column({ + uid: 't.uid', + height: 't.height', + tx_type: 't.tx_type', + id: 't.id', + time_stamp: 't.time_stamp', + signature: 't.signature', + proofs: 't.proofs', + tx_version: 't.tx_version', + fee: 't.fee', + status: 't.status', + sender: 't.sender', + sender_public_key: 't.sender_public_key', + + bytes: 't.payload', // todo rename in DB + function_name: 't.function_name', + }); + +module.exports = { select, selectFromFiltered }; diff --git a/src/services/transactions/ethereumLike/repo/transformTxInfo.ts b/src/services/transactions/ethereumLike/repo/transformTxInfo.ts new file mode 100644 index 00000000..16c6ae0f --- /dev/null +++ b/src/services/transactions/ethereumLike/repo/transformTxInfo.ts @@ -0,0 +1,25 @@ +import { compose, evolve } from 'ramda'; +import { renameKeys } from 'ramda-adjunct'; +import { transformTxInfo } from '../../_common/transformTxInfo'; +import { EthereumLikeTxPayload } from './types'; + +const functionNameToPayload = (functionName: string | null): EthereumLikeTxPayload => + functionName === null + ? { type: 'transfer' } + : { + type: 'invocation', + call: { + function: functionName, + }, + }; + +const bufferToETHHex = (b: Buffer) => '0x' + b.toString('hex'); + +export default compose( + transformTxInfo, + evolve({ + payload: functionNameToPayload, + bytes: bufferToETHHex, + }) as any, + renameKeys({ function_name: 'payload' }) +); diff --git a/src/services/transactions/ethereumLike/repo/types.ts b/src/services/transactions/ethereumLike/repo/types.ts new file mode 100644 index 00000000..0eb08686 --- /dev/null +++ b/src/services/transactions/ethereumLike/repo/types.ts @@ -0,0 +1,41 @@ +import { Repo } from '../../../../types'; +import { WithSortOrder, WithLimit } from '../../../_common'; +import { RequestWithCursor } from '../../../_common/pagination'; +import { CommonFilters, RawTx, Tx } from '../../_common/types'; + +export type EthereumLikeTransfer = 'transfer'; +export type EthereumLikeInvocation = 'invocation'; + +export type EthereumLikeTxDbResponse = RawTx & { + payload: string; + function_name: string | null; +}; + +export type EthereumLikeTxPayload = + | { type: EthereumLikeTransfer } + | { type: EthereumLikeInvocation; call: { function: string } }; + +export type EthereumLikeTx = Tx & { + bytes: string; + payload: EthereumLikeTxPayload; +}; + +export type EthereumLikeTxsGetRequest = string; + +export type EthereumLikeTxsMgetRequest = string[]; + +export type EthereumLikeTxsSearchRequest = RequestWithCursor< + CommonFilters & WithSortOrder & WithLimit, + string +> & + Partial<{ + type: EthereumLikeTransfer | EthereumLikeInvocation; + function: string; + }>; + +export type EthereumLikeTxsRepo = Repo< + EthereumLikeTxsGetRequest, + EthereumLikeTxsMgetRequest, + EthereumLikeTxsSearchRequest, + EthereumLikeTx +>; diff --git a/src/services/transactions/ethereumLike/types.ts b/src/services/transactions/ethereumLike/types.ts new file mode 100644 index 00000000..b96cf7bb --- /dev/null +++ b/src/services/transactions/ethereumLike/types.ts @@ -0,0 +1,30 @@ +import { Maybe } from 'folktale/maybe'; +import { + Service, + SearchedItems, + ServiceGetRequest, + ServiceMgetRequest, +} from '../../../types'; +import { WithMoneyFormat } from '../../types'; +import { + EthereumLikeTxsGetRequest, + EthereumLikeTxsMgetRequest, + EthereumLikeTxsSearchRequest, + EthereumLikeTx, +} from './repo/types'; + +type EthereumLikeTxsServiceGetRequest = ServiceGetRequest; +type EthereumLikeTxsServiceMgetRequest = ServiceMgetRequest; +type EthereumLikeTxsServiceSearchRequest = EthereumLikeTxsSearchRequest; + +export type EthereumLikeTxsService = { + get: Service>; + mget: Service< + EthereumLikeTxsServiceMgetRequest & WithMoneyFormat, + Maybe[] + >; + search: Service< + EthereumLikeTxsServiceSearchRequest & WithMoneyFormat, + SearchedItems + >; +}; diff --git a/src/services/transactions/updateAssetInfo/repo/index.ts b/src/services/transactions/updateAssetInfo/repo/index.ts index 5ee02f5d..0b22527d 100644 --- a/src/services/transactions/updateAssetInfo/repo/index.ts +++ b/src/services/transactions/updateAssetInfo/repo/index.ts @@ -6,7 +6,7 @@ import { mgetByIdsPreset } from '../../../_common/presets/pg/mgetByIds'; import { searchPreset } from '../../../_common/presets/pg/search'; import { Cursor, serialize, deserialize } from '../../_common/cursor'; -import { transformTxInfo } from '../../_common/transformTxInfo'; +import transformTxInfo from './transformTxInfo'; import { result as resultSchema } from './schema'; import * as sql from './sql'; diff --git a/src/services/transactions/updateAssetInfo/repo/schema.ts b/src/services/transactions/updateAssetInfo/repo/schema.ts index dad445ca..c5c29b07 100644 --- a/src/services/transactions/updateAssetInfo/repo/schema.ts +++ b/src/services/transactions/updateAssetInfo/repo/schema.ts @@ -1,16 +1,6 @@ import { Joi } from '../../../../utils/validation'; - -import commonFilters from '../../../_common/presets/pg/search/commonFilterSchemas'; import commonFields from '../../_common/commonFieldsSchemas'; -export const inputSearch = Joi.object() - .keys({ - ...commonFilters, - - assetId: Joi.string().assetId(), - }) - .nand('sender', 'senders'); - export const result = Joi.object().keys({ ...commonFields, diff --git a/src/services/transactions/updateAssetInfo/transformTxInfo.ts b/src/services/transactions/updateAssetInfo/transformTxInfo.ts deleted file mode 100644 index 7fdccbe7..00000000 --- a/src/services/transactions/updateAssetInfo/transformTxInfo.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { compose } from 'ramda'; -import { renameKeys } from 'ramda-adjunct'; - -import { transformTxInfo } from '../_common/transformTxInfo'; - -export default compose( - transformTxInfo, - renameKeys({ - asset_name: 'name', - asset_id: 'assetId', - }) -); diff --git a/src/utils/db/knex/lib.js b/src/utils/db/knex/lib.js index 2274712e..714dd0cf 100644 --- a/src/utils/db/knex/lib.js +++ b/src/utils/db/knex/lib.js @@ -5,21 +5,25 @@ const hasMethod = curryN( (method, x) => (x && x[method] && type(x[method]) === 'Function') || false ); -const createPointfree = method => (...args) => { - const instanceIdx = findIndex(hasMethod(method), args); +const createPointfree = + (method) => + (...args) => { + const instanceIdx = findIndex(hasMethod(method), args); - if (instanceIdx !== -1) { - return args[instanceIdx].clone()[method](...slice(0, instanceIdx, args)); - } else { - return (...args2) => createPointfree(method)(...concat(args, args2)); - } -}; + if (instanceIdx !== -1) { + return args[instanceIdx].clone()[method](...slice(0, instanceIdx, args)); + } else { + return (...args2) => createPointfree(method)(...concat(args, args2)); + } + }; module.exports = { hasMethod, where: createPointfree('where'), whereIn: createPointfree('whereIn'), whereRaw: createPointfree('whereRaw'), + whereNull: createPointfree('whereNull'), + whereNotNull: createPointfree('whereNotNull'), limit: createPointfree('limit'), orWhere: createPointfree('orWhere'), orderBy: createPointfree('orderBy'), From 4b0c51d7b53795f23482da231a08001e33550d40 Mon Sep 17 00:00:00 2001 From: Dmitry Shuranov Date: Tue, 4 Apr 2023 18:32:36 +0300 Subject: [PATCH 3/9] package-lock.json reverted --- package-lock.json | 1133 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1122 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index ee90c14b..8c12cca2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -721,6 +721,12 @@ "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "accepts": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", @@ -770,6 +776,15 @@ "uri-js": "^4.2.2" } }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "requires": { + "string-width": "^2.0.0" + } + }, "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", @@ -1132,6 +1147,12 @@ } } }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", @@ -1297,6 +1318,12 @@ "tweetnacl": "^0.14.3" } }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, "bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", @@ -1310,6 +1337,21 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1449,6 +1491,12 @@ "rsvp": "^4.8.4" } }, + "capture-stack-trace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1479,6 +1527,40 @@ "cowsay": "^1.1.9" } }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } + } + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -1500,6 +1582,12 @@ } } }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, "cli-color": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", @@ -1670,6 +1758,20 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "dev": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -1729,6 +1831,50 @@ "strip-eof": "^1.0.0" } }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "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" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, "cssom": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", @@ -1811,6 +1957,12 @@ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -1949,6 +2101,21 @@ "webidl-conversions": "^4.0.2" } }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -2281,6 +2448,21 @@ "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==", "dev": true }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.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" + } + }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -2657,17 +2839,565 @@ "map-cache": "^0.2.2" } }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true + } + } + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -2691,6 +3421,12 @@ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=" }, + "get-stream": { + "version": "3.0.0", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -2724,6 +3460,36 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", @@ -2752,6 +3518,25 @@ "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", "dev": true }, + "got": { + "version": "6.7.1", + "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "dev": true, + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + } + }, "graceful-fs": { "version": "4.1.11", "resolved": "http://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", @@ -2930,6 +3715,12 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, "import-fresh": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", @@ -2940,6 +3731,12 @@ "resolve-from": "^4.0.0" } }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, "import-local": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", @@ -3073,6 +3870,15 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -3084,6 +3890,15 @@ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "dev": true }, + "is-ci": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz", + "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", + "dev": true, + "requires": { + "ci-info": "^1.0.0" + } + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -3149,6 +3964,22 @@ "is-extglob": "^2.1.1" } }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -3157,6 +3988,21 @@ "kind-of": "^3.0.2" } }, + "is-obj": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -3171,6 +4017,12 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, "is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", @@ -3188,6 +4040,12 @@ "is-unc-path": "^1.0.0" } }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -4290,6 +5148,15 @@ "colornames": "0.0.2" } }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "dev": true, + "requires": { + "package-json": "^4.0.0" + } + }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -4396,6 +5263,12 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -4746,6 +5619,50 @@ "which": "^1.3.0" } }, + "nodemon": { + "version": "1.18.9", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.18.9.tgz", + "integrity": "sha512-oj/eEVTEI47pzYAjGkpcNw0xYwTl4XSTUQv2NPQI6PpN3b75PhpuYk3Vb3U80xHCyM2Jm+1j68ULHXl4OR3Afw==", + "dev": true, + "requires": { + "chokidar": "^2.0.4", + "debug": "^3.1.0", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.6", + "semver": "^5.5.0", + "supports-color": "^5.2.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.2", + "update-notifier": "^2.5.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -5066,6 +5983,18 @@ "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", "dev": true }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, "packet-reader": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", @@ -5121,6 +6050,12 @@ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -5371,6 +6306,12 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, "pretty-format": { "version": "24.5.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.5.0.tgz", @@ -5413,12 +6354,24 @@ "sisteransi": "^1.0.0" } }, + "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.31", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", "dev": true }, + "pstree.remy": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.6.tgz", + "integrity": "sha512-NdF35+QsqD7EgNEI5mkI/X+UwaxVEbQaz9f4IooEmMUv6ZPmlTQYGjBPJGgrlzNdjSvIy4MWMg6Q6vCgBO2K+w==", + "dev": true + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -5460,6 +6413,18 @@ "unpipe": "1.0.0" } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, "react-is": { "version": "16.8.4", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.4.tgz", @@ -5502,6 +6467,17 @@ "util-deprecate": "~1.0.1" } }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, "realpath-native": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", @@ -5539,6 +6515,25 @@ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "^1.0.1" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -5845,6 +6840,15 @@ "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "^5.0.3" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -6295,6 +7299,15 @@ "resolved": "https://registry.npmjs.org/tarn/-/tarn-1.1.5.tgz", "integrity": "sha512-PMtJ3HCLAZeedWjJPgGnCvcphbCOMbtZpjKgLq3qM5Qq9aQud+XHrL0WlrlgnTyS8U+jrjGbEXprFcQrxPy52g==" }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "^0.7.0" + } + }, "test-exclude": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.1.0.tgz", @@ -6337,6 +7350,12 @@ "os-homedir": "^1.0.0" } }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, "timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", @@ -6404,6 +7423,15 @@ "hoek": "5.x.x" } }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "requires": { + "nopt": "~1.0.10" + } + }, "tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", @@ -6578,6 +7606,15 @@ "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" }, + "undefsafe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", + "integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=", + "dev": true, + "requires": { + "debug": "^2.2.0" + } + }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -6589,6 +7626,15 @@ "set-value": "^2.0.1" } }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -6630,6 +7676,36 @@ } } }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "dev": true, + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -6649,6 +7725,15 @@ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -6784,6 +7869,15 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "requires": { + "string-width": "^2.1.1" + } + }, "winston": { "version": "3.0.0-rc4", "resolved": "http://registry.npmjs.org/winston/-/winston-3.0.0-rc4.tgz", @@ -6866,6 +7960,17 @@ "mkdirp": "^0.5.1" } }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, "ws": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", @@ -6875,6 +7980,12 @@ "async-limiter": "~1.0.0" } }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true + }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", From 7ef652485d84ece3e357ed9afdc653ab7f8af1b5 Mon Sep 17 00:00:00 2001 From: Pavel Prokhorov Date: Thu, 6 Apr 2023 14:31:53 +0300 Subject: [PATCH 4/9] Update openapi.json --- docs/openapi.json | 735 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 734 insertions(+), 1 deletion(-) diff --git a/docs/openapi.json b/docs/openapi.json index fc618076..449ec8b1 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -4703,7 +4703,7 @@ "tags": [ "transactions" ], - "summary": "Get a Invoke-script transaction info by id", + "summary": "Get an Invoke-script transaction info by id", "operationId": "getTxsInvokeScript", "parameters": [ { @@ -4964,6 +4964,510 @@ } } }, + "/transactions/update-asset-info/{id}": { + "get": { + "tags": [ + "transactions" + ], + "summary": "Get an Update asset info transaction by id", + "operationId": "getTxsUpdateAssetInfo", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "transaction ID", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Update asset info transaction", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TxUpdateAssetInfo" + } + } + } + }, + "404": { + "description": "Transaction not found" + } + } + } + }, + "/transactions/update-asset-info": { + "get": { + "tags": [ + "transactions" + ], + "summary": "Get a list of Update asset info transactions by applying filters", + "operationId": "searchTxsUpdateAssetInfo", + "parameters": [ + { + "in": "query", + "name": "ids", + "description": "Transaction IDs array", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "sender", + "description": "Address-sender of the transaction; has exclusive relation with senders", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "senders", + "description": "Array of address-senders of the transaction; has exclusive relation with sender", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "timeStart", + "description": "Time range filter, start. Defaults to first transaction's time_stamp in db. (ISO-8601 or timestamp in milliseconds, UTC)", + "schema": { + "oneOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "number" + } + ] + } + }, + { + "in": "query", + "name": "timeEnd", + "description": "Time range filter, end. Defaults to now. (ISO-8601 or timestamp in milliseconds, UTC)", + "schema": { + "oneOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "number" + } + ] + } + }, + { + "in": "query", + "name": "after", + "description": "Cursor in base64 encoding. Holds information about timestamp, id, sort.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "sort", + "description": "Sort order. Gonna be rewritten by cursor's sort if present.", + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "default": "desc" + } + }, + { + "in": "query", + "name": "limit", + "description": "How many transactions to await in response.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 100 + } + } + ], + "responses": { + "200": { + "description": "List of UpdateAssetInfo transactions satisfying provided filters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListOfTxUpdateAssetInfo" + } + } + } + } + } + }, + "post": { + "tags": [ + "transactions" + ], + "summary": "Get a list of Update asset info transactions by applying filters", + "operationId": "postSearchTxsUpdateAssetInfo", + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "description": "Transaction IDs array", + "items": { + "type": "string" + } + }, + "sender": { + "type": "string", + "description": "Address-sender of the transaction" + }, + "timeStart": { + "oneOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "number" + } + ], + "description": "Time range filter, start. Defaults to first transaction's time_stamp in db. (ISO-8601 or timestamp in milliseconds, UTC)", + "example": "2019-01-01T00:00:00.000" + }, + "timeEnd": { + "oneOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "number" + } + ], + "description": "Time range filter, end. Defaults to now. (ISO-8601 or timestamp in milliseconds, UTC)", + "example": "2020-01-01T00:00:00.000" + }, + "after": { + "type": "string", + "description": "Cursor in base64 encoding. Holds information about timestamp, id, sort." + }, + "sort": { + "type": "string", + "description": "Sort order. Gonna be rewritten by cursor's sort if present.", + "enum": [ + "asc", + "desc" + ], + "default": "desc" + }, + "limit": { + "type": "integer", + "description": "How many transactions to await in response.", + "minimum": 1, + "maximum": 100, + "default": 100, + "example": 100 + } + } + } + } + } + }, + "responses": { + "200": { + "description": "List of UpdateAssetInfo transactions satisfying provided filters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListOfTxUpdateAssetInfo" + } + } + } + } + } + } + }, + "/transactions/ethereum-like/{id}": { + "get": { + "tags": [ + "transactions" + ], + "summary": "Get an Ethereum-like info transaction info by id", + "operationId": "getTxsEthereumLike", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "transaction ID", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Ethereum-like transaction", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TxEthereumLike" + } + } + } + }, + "404": { + "description": "Transaction not found" + } + } + } + }, + "/transactions/ethereum-like": { + "get": { + "tags": [ + "transactions" + ], + "summary": "Get a list of Ethereum-like transactions by applying filters", + "operationId": "searchTxsEthereumLike", + "parameters": [ + { + "in": "query", + "name": "ids", + "description": "Transaction IDs array", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "sender", + "description": "Address-sender of the transaction; has exclusive relation with senders", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "senders", + "description": "Array of address-senders of the transaction; has exclusive relation with sender", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "timeStart", + "description": "Time range filter, start. Defaults to first transaction's time_stamp in db. (ISO-8601 or timestamp in milliseconds, UTC)", + "schema": { + "oneOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "number" + } + ] + } + }, + { + "in": "query", + "name": "timeEnd", + "description": "Time range filter, end. Defaults to now. (ISO-8601 or timestamp in milliseconds, UTC)", + "schema": { + "oneOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "number" + } + ] + } + }, + { + "in": "query", + "name": "type", + "description": "Transaction type.", + "schema": { + "type": "string", + "enum": [ + "invocation", + "transfer" + ], + } + }, + { + "in": "query", + "name": "function", + "description": "Search transactions by the called function name. Only for `invocation` type transactions.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "after", + "description": "Cursor in base64 encoding. Holds information about timestamp, id, sort.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "sort", + "description": "Sort order. Gonna be rewritten by cursor's sort if present.", + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "default": "desc" + } + }, + { + "in": "query", + "name": "limit", + "description": "How many transactions to await in response.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 100 + } + } + ], + "responses": { + "200": { + "description": "List of EthereumLike transactions satisfying provided filters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListOfTxEthereumLike" + } + } + } + } + } + }, + "post": { + "tags": [ + "transactions" + ], + "summary": "Get a list of Ethereum-like transactions by applying filters", + "operationId": "postSearchTxsEthereumLike", + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "description": "Transaction IDs array", + "items": { + "type": "string" + } + }, + "sender": { + "type": "string", + "description": "Address-sender of the transaction" + }, + "timeStart": { + "oneOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "number" + } + ], + "description": "Time range filter, start. Defaults to first transaction's time_stamp in db. (ISO-8601 or timestamp in milliseconds, UTC)", + "example": "2019-01-01T00:00:00.000" + }, + "timeEnd": { + "oneOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "number" + } + ], + "description": "Time range filter, end. Defaults to now. (ISO-8601 or timestamp in milliseconds, UTC)", + "example": "2020-01-01T00:00:00.000" + }, + "after": { + "type": "string", + "description": "Cursor in base64 encoding. Holds information about timestamp, id, sort." + }, + "sort": { + "type": "string", + "description": "Sort order. Gonna be rewritten by cursor's sort if present.", + "enum": [ + "asc", + "desc" + ], + "default": "desc" + }, + "limit": { + "type": "integer", + "description": "How many transactions to await in response.", + "minimum": 1, + "maximum": 100, + "default": 100, + "example": 100 + } + } + } + } + } + }, + "responses": { + "200": { + "description": "List of UpdateAssetInfo transactions satisfying provided filters", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListOfTxUpdateAssetInfo" + } + } + } + } + } + } + }, "/aliases/{alias}": { "get": { "tags": [ @@ -5829,6 +6333,9 @@ "signature": { "type": "string" }, + "applicationStatus": { + "type": "string" + }, "order1": { "$ref": "#/components/schemas/Order" }, @@ -5924,6 +6431,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "data": { "type": "array", "items": { @@ -6024,6 +6534,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "assetId": { "type": "string" }, @@ -6096,6 +6609,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "recipient": { "type": "string" }, @@ -6157,6 +6673,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "recipient": { "type": "string" }, @@ -6211,6 +6730,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "leaseId": { "type": "string" } @@ -6263,6 +6785,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "script": { "type": "string" } @@ -6315,6 +6840,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "recipient": { "type": "string" }, @@ -6370,6 +6898,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "assetId": { "type": "string" }, @@ -6440,6 +6971,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "assetId": { "type": "string" }, @@ -6498,6 +7032,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "assetId": { "type": "string" }, @@ -6553,6 +7090,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "assetId": { "type": "string" }, @@ -6608,6 +7148,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "alias": { "type": "string" } @@ -6657,6 +7200,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "recipient": { "type": "string" }, @@ -6712,6 +7258,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "assetId": { "type": "string" }, @@ -6767,6 +7316,9 @@ "type": "string" } }, + "applicationStatus": { + "type": "string" + }, "dApp": { "type": "string" }, @@ -6838,6 +7390,135 @@ } } }, + "TxUpdateAssetInfo": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "example": "transaction" + }, + "data": { + "type": "object", + "properties": { + "height": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "signature": { + "type": "string" + }, + "proofs": { + "type": "array", + "items": { + "type": "string" + } + }, + "version": { + "type": "integer" + }, + "fee": { + "type": "number" + }, + "applicationStatus": { + "type": "string" + }, + "sender": { + "type": "string" + }, + "senderPublicKey": { + "type": "string" + }, + "assetId": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + } + } + } + }, + "TxEthereumLike": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "example": "transaction" + }, + "data": { + "type": "object", + "properties": { + "height": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "proofs": { + "type": "array", + "items": { + "type": "string" + } + }, + "version": { + "type": "integer" + }, + "fee": { + "type": "number" + }, + "applicationStatus": { + "type": "string" + }, + "sender": { + "type": "string" + }, + "senderPublicKey": { + "type": "string" + }, + "bytes": { + "type": "string", + }, + "payload": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "call": { + "type": "object", + "properties": { + "function": { + "type": "string" + } + } + } + } + } + } + } + } + }, "Rate": { "type": "object", "required": [ @@ -7456,6 +8137,58 @@ "type": "boolean" } } + }, + "ListOfTxUpdateAssetInfo": { + "type": "object", + "required": [ + "__type", + "data" + ], + "properties": { + "__type": { + "type": "string", + "example": "list" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TxUpdateAssetInfo" + } + }, + "lastCursor": { + "type": "string", + "example": "U2F0IEp1biAwMiAyMDE4IDE0OjAxOjQ1IEdNVCswMzAwIChNU0spOjozUHVrdnJzN2FwN1ZmQVlyTHlpZlNvZ0xYM0NuTVV4c0VFbmhuNk40WUVHWjo6YXNj" + }, + "isLastPage": { + "type": "boolean" + } + } + }, + "ListOfTxEthereumLike": { + "type": "object", + "required": [ + "__type", + "data" + ], + "properties": { + "__type": { + "type": "string", + "example": "list" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TxEthereumLike" + } + }, + "lastCursor": { + "type": "string", + "example": "U2F0IEp1biAwMiAyMDE4IDE0OjAxOjQ1IEdNVCswMzAwIChNU0spOjozUHVrdnJzN2FwN1ZmQVlyTHlpZlNvZ0xYM0NuTVV4c0VFbmhuNk40WUVHWjo6YXNj" + }, + "isLastPage": { + "type": "boolean" + } + } } } } From c45ca6e3157663ea4b0be0b059a30307f3b08403 Mon Sep 17 00:00:00 2001 From: Pavel Prokhorov Date: Thu, 6 Apr 2023 16:48:22 +0300 Subject: [PATCH 5/9] Update openapi.json --- docs/openapi.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/openapi.json b/docs/openapi.json index 449ec8b1..22dfb92f 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -5038,6 +5038,14 @@ } } }, + { + "in": "query", + "name": "assetId", + "description": "Filter transactions by assetId", + "schema": { + "type": "string" + } + }, { "in": "query", "name": "timeStart", From d710d89997f29e7e945013aded338625f294f129 Mon Sep 17 00:00:00 2001 From: Dmitry Shuranov Date: Tue, 11 Apr 2023 18:09:40 +0300 Subject: [PATCH 6/9] 0.37.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8c12cca2..9122a0e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "data-service", - "version": "0.36.0", + "version": "0.37.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 1abbcef6..b2d2bdab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "data-service", - "version": "0.36.0", + "version": "0.37.0", "description": "Waves data service", "main": "src/index.js", "repository": "git@github.com:wavesplatform/data-service.git", From 85449e197a044e2f31726c9ba05d823d8fc9e714 Mon Sep 17 00:00:00 2001 From: Dmitry Shuranov Date: Tue, 18 Apr 2023 12:27:29 +0300 Subject: [PATCH 7/9] eth txs: rename db column payload to bytes --- src/services/transactions/ethereumLike/repo/sql/query.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/transactions/ethereumLike/repo/sql/query.js b/src/services/transactions/ethereumLike/repo/sql/query.js index 10d4ada0..19dd3e70 100644 --- a/src/services/transactions/ethereumLike/repo/sql/query.js +++ b/src/services/transactions/ethereumLike/repo/sql/query.js @@ -17,7 +17,7 @@ const selectFromFiltered = (filtered) => sender: 't.sender', sender_public_key: 't.sender_public_key', - bytes: 't.payload', // todo rename in DB + bytes: 't.bytes', function_name: 't.function_name', }); From f4edaa2582a0b5409ab08b7479d1140ee014e1c8 Mon Sep 17 00:00:00 2001 From: Dmitry Shuranov Date: Thu, 20 Apr 2023 12:26:05 +0300 Subject: [PATCH 8/9] pairs daemon: use decimals view instead of assets --- src/daemons/pairs/sql/fillTable.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/daemons/pairs/sql/fillTable.ts b/src/daemons/pairs/sql/fillTable.ts index e35b79a3..ffc541ea 100644 --- a/src/daemons/pairs/sql/fillTable.ts +++ b/src/daemons/pairs/sql/fillTable.ts @@ -10,8 +10,8 @@ const selectExchanges = pg({ t: 'txs_7' }) price: pg.raw(` CASE WHEN t.tx_version > 2 THEN t.price::numeric - * 10^(select decimals from assets where asset_id = t.price_asset_id) - * 10^(select -decimals from assets where asset_id = t.amount_asset_id) + * 10^(select decimals from decimals where asset_id = t.price_asset_id) + * 10^(select -decimals from decimals where asset_id = t.amount_asset_id) ELSE t.price::numeric END `), @@ -27,12 +27,8 @@ const selectPairsCTE = pg qb.select({ amount_asset_id: 'amount_asset_id', price_asset_id: 'price_asset_id', - last_price: pg.raw( - '(array_agg(e.price ORDER BY e.uid DESC)::numeric[])[1]' - ), - first_price: pg.raw( - '(array_agg(e.price ORDER BY e.uid)::numeric[])[1]' - ), + last_price: pg.raw('(array_agg(e.price ORDER BY e.uid DESC)::numeric[])[1]'), + first_price: pg.raw('(array_agg(e.price ORDER BY e.uid)::numeric[])[1]'), volume: pg.raw('sum(e.amount)'), quote_volume: pg.raw('sum(e.amount::numeric * e.price::numeric)'), weighted_average_price: pg.raw( @@ -57,7 +53,9 @@ const selectPairsCTE = pg 'p.last_price', 'p.volume', { - volume_waves: pg.raw('COALESCE(p.volume_waves, floor(p.quote_volume / p1.weighted_average_price), p.quote_volume * p2.weighted_average_price)'), + volume_waves: pg.raw( + 'COALESCE(p.volume_waves, floor(p.quote_volume / p1.weighted_average_price), p.quote_volume * p2.weighted_average_price)' + ), }, 'p.quote_volume', 'p.high', From d44b4c1c11fc78001c4dca14744bcd4e13fd111e Mon Sep 17 00:00:00 2001 From: Dmitry Shuranov Date: Thu, 20 Apr 2023 12:27:45 +0300 Subject: [PATCH 9/9] removed candles daemon --- README.md | 72 ++++--- package.json | 1 - src/daemons/candles/Dockerfile | 24 --- src/daemons/candles/README.md | 37 ---- src/daemons/candles/create.js | 171 --------------- src/daemons/candles/index.js | 29 --- src/daemons/candles/loadConfig.ts | 30 --- .../__test__/__snapshots__/sql.test.js.snap | 17 -- src/daemons/candles/sql/__test__/sql.test.js | 64 ------ src/daemons/candles/sql/query.js | 203 ------------------ src/daemons/candles/sql/utils.js | 111 ---------- 11 files changed, 39 insertions(+), 720 deletions(-) delete mode 100644 src/daemons/candles/Dockerfile delete mode 100644 src/daemons/candles/README.md delete mode 100644 src/daemons/candles/create.js delete mode 100644 src/daemons/candles/index.js delete mode 100644 src/daemons/candles/loadConfig.ts delete mode 100644 src/daemons/candles/sql/__test__/__snapshots__/sql.test.js.snap delete mode 100644 src/daemons/candles/sql/__test__/sql.test.js delete mode 100644 src/daemons/candles/sql/query.js delete mode 100644 src/daemons/candles/sql/utils.js diff --git a/README.md b/README.md index e5e6468a..8c647be7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ **⚠️ This service is currently in /v0. Breaking changes are coming in /v1 (also possible, but not likely, within /v0 releases). Please use with caution.** -This is an API aimed at retrieving data from blockchain quickly and conveniently. We support public APIs for: +This is an API aimed at retrieving data from blockchain quickly and conveniently. We support public APIs for: + - Mainnet - [https://api.wavesplatform.com/v0/](https://api.wavesplatform.com/v0/) - Testnet @@ -10,7 +11,6 @@ This is an API aimed at retrieving data from blockchain quickly and conveniently Visit `/docs` for Swagger documentation. - ## Data service on-premise It is possible to create your own instance of this service. To do so, follow the guide below. @@ -19,26 +19,26 @@ It is possible to create your own instance of this service. To do so, follow the 1. PostgreSQL 11 database with a table stricture found in [wavesplatform/blockchain-postgres-sync](https://github.com/wavesplatform/blockchain-postgres-sync) 2. Downloaded and continuously updated blockchain data in the database -2. NodeJS or Docker for either running the service directly, or in a container +3. NodeJS or Docker for either running the service directly, or in a container #### Installation and start The service uses following environment variables: -|Env variable|Default|Required|Description| -|------------|-------|--------|-----------| -|`PORT`|3000|NO|HTTP service port| -|`PGHOST`||YES|Postgres host address| -|`PGPORT`|`5432`|NO|Postgres port| -|`PGDATABASE`||YES|Postgres database name| -|`PGUSER`||YES|Postgres user name| -|`PGPASSWORD`||YES|Postgres password| -|`PGPOOLSIZE`|`20`|NO|Postgres pool size| -|`PGSTATEMENTTIMEOUT`|false|NO|Postgres `statement_timeout` number in ms. 0 disables timeout, false — use server settings; at this moment used only as default `STATEMENT_TIMEOUT`| -|`LOG_LEVEL`|`info`|NO|Log level `['info','warn','error']`| -|`DEFAULT_MATCHER`||YES|Default matcher public address| -|`MATCHER_SETTINGS_URL`||NO|Default matcher URL for getting settings| -|`DEFAULT_TIMEOUT`|30000|NO|Default timeout in ms; at this moment used only as `PG STATEMENT_TIMEOUT`| +| Env variable | Default | Required | Description | +| ---------------------- | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `PORT` | 3000 | NO | HTTP service port | +| `PGHOST` | | YES | Postgres host address | +| `PGPORT` | `5432` | NO | Postgres port | +| `PGDATABASE` | | YES | Postgres database name | +| `PGUSER` | | YES | Postgres user name | +| `PGPASSWORD` | | YES | Postgres password | +| `PGPOOLSIZE` | `20` | NO | Postgres pool size | +| `PGSTATEMENTTIMEOUT` | false | NO | Postgres `statement_timeout` number in ms. 0 disables timeout, false — use server settings; at this moment used only as default `STATEMENT_TIMEOUT` | +| `LOG_LEVEL` | `info` | NO | Log level `['info','warn','error']` | +| `DEFAULT_MATCHER` | | YES | Default matcher public address | +| `MATCHER_SETTINGS_URL` | | NO | Default matcher URL for getting settings | +| `DEFAULT_TIMEOUT` | 30000 | NO | Default timeout in ms; at this moment used only as `PG STATEMENT_TIMEOUT` | `PGPOOLSIZE` is used by the `pg-pool` library to determine Postgres connection pool size per NodeJS process instance. A good value depends on your server and db configuration and can be found empirically. You can leave it at the default value to start with. @@ -47,23 +47,27 @@ Set those variables to a `variables.env` file in the root of the project for con If you would like to use some other way of setting environment variables, just replace relevant commands below with custom alternatives. ##### Docker + If you wish to build data-service image locally, run this command from the project root - ```bash - docker build -t wavesplatform/data-service . - ``` + +```bash +docker build -t wavesplatform/data-service . +``` Otherwise you can use our public image from https://hub.docker.com/r/wavesplatform/data-service Run the container using this command: - ```bash - docker run -p=:3000 --env-file=variables.env wavesplatform/data-service - ``` + +```bash +docker run -p=:3000 --env-file=variables.env wavesplatform/data-service +``` A server will start at `localhost:` (used in the `docker run` command). Logs will be handled by Docker. Use any other Docker options if necessary. When using the container in production, we recommend establishing a Docker logging and restart policy. ##### NodeJS + 1. Install dependencies ```bash npm install # or `yarn install`, if you prefer @@ -81,28 +85,30 @@ Server will start at `localhost:PORT` (defaults to 3000). Logs will be directed If you decide to use NodeJS directly (without Docker), we recommend using a process manager, such as `pm2`. - #### Daemons -To add candles and pairs functionality the following Docker daemons must be used: -- Candles — calculate candles for exchange transactions (see [description](https://hub.docker.com/r/wavesplatform/data-service-candles/)) -- Pairs — calculate last pairs for 24h exchange transactions (see [description](https://hub.docker.com/r/wavesplatform/data-service-pairs/)) +To add and pairs functionality the following Docker daemons must be used: + +- Pairs — calculate last pairs for 24h exchange transactions (see [description](https://hub.docker.com/r/wavesplatform/data-service-pairs/)) #### Documentation + You can run your own instance of Swagger online documentation. To do this, you have to: + 1. Build Docker image from docs/ directory: - ```bash - docker build -t wavesplatform/data-service-docs docs/ - ``` + ```bash + docker build -t wavesplatform/data-service-docs docs/ + ``` 2. Run the container - ```bash - docker run --rm -d -p 8080:8080 -e SWAGGER_JSON=/app/openapi.json wavesplatform/data-service-docs - ``` + ```bash + docker run --rm -d -p 8080:8080 -e SWAGGER_JSON=/app/openapi.json wavesplatform/data-service-docs + ``` Its will start the documentation server at `localhost:8080`. Enjoy! #### General recommendations + - Set up a dedicated web server such as Nginx in front of data-service backends (for ssl/caching/balancing); - Implement a caching strategy. Different endpoints may need different cache time (or no cache at all); - Run several process instances behind a load balancer per machine. `docker-compose --scale` can help with that, or it can be done manually. A good rule of thumb is to use as many instances as CPU cores available; diff --git a/package.json b/package.json index b2d2bdab..dd5d5e72 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "build": "rm -rf dist/ && tsc", "start": "NODE_PG_FORCE_NATIVE=1 node dist/index.js", "dev": "NODE_PG_FORCE_NATIVE=1 NODE_ENV=development LOG_LEVEL=debug node dist/index.js", - "candles": "NODE_PG_FORCE_NATIVE=1 node dist/daemons/candles/index.js", "pairs": "NODE_PG_FORCE_NATIVE=1 node dist/daemons/pairs/index.js", "lint": "eslint src", "test": "jest --runInBand --detectOpenHandles --config=config/jest.config.unit.json", diff --git a/src/daemons/candles/Dockerfile b/src/daemons/candles/Dockerfile deleted file mode 100644 index fba0d583..00000000 --- a/src/daemons/candles/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM node:10-alpine - -# pg-native -RUN apk --no-cache add make python gcc postgresql-dev g++ - -# enable node_modules caching layer -RUN apk add --no-cache tini git -ADD package.json /tmp/package.json -ADD package-lock.json /tmp/package-lock.json -RUN cd /tmp && npm install -RUN mkdir -p /opt/app && cp -a /tmp/node_modules /opt/app - -# set work dir -WORKDIR /opt/app -ADD . /opt/app -RUN cd /opt/app -RUN npm run build - -# add tini for PID 1 handling -ENTRYPOINT ["/sbin/tini", "--"] - -# NodeJS launch -USER node -CMD ["npm", "run", "candles"] diff --git a/src/daemons/candles/README.md b/src/daemons/candles/README.md deleted file mode 100644 index fd13125c..00000000 --- a/src/daemons/candles/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# Data Service Candles Daemon in Docker - -## About the image -This Docker image contains scripts and configs to run Data Service Candles Daemon. The image adds functionality to [Data Service](https://github.com/wavesplatform/data-service) to calculate and update DEX candles inside the Postgres database (see Requirements). - -Container downloads source code and configuration files from the [repository](https://github.com/wavesplatform/data-service) and runs it. - -## Requirements ⚠️ - -1. PostgreSQL 10 database with a table structure found in [wavesplatform/blockchain-postgres-sync](https://github.com/wavesplatform/blockchain-postgres-sync) -2. Downloaded and continuously updated blockchain data in the database -2. Docker for running the service in a container - -## Running the image - -The simplest way to run a container: -``` -docker run -e PGHOST=*** -e PGDATABASE=*** -e PGUSER=*** -e PGPASSWORD=*** -it wavesplatform/candles-daemon -``` - -**You can run container with environment variables:** - -|Env variable|Default|Required|Description| -|------------|-------|--------|-----------| -|`PGHOST`||YES|Postgres host address| -|`PGPORT`|`5432`|NO|Postgres port| -|`PGDATABASE`||YES|Postgres database name| -|`PGUSER`||YES|Postgres user name| -|`PGPASSWORD`||YES|Postgres password| -|`PGPOOLSIZE`|`20`|NO|Postgres pool size| -|`PGSTATEMENTTIMEOUT`|`false`|NO|Postgres statement timeout; number in ms (false = disabled)| -|`LOG_LEVEL`|`info`|NO|Log level `['info','warn','error']`| -|`CANDLES_UPDATE_INTERVAL_`|`2500`|NO|Minimum daemon update time in ms. If time is exceeded, the next iteration starts immediately| -|`CANDLES_UPDATE_TIMEOUT`|`20000`|NO|If the update time in ms is exceeded, the daemon terminates| -|`RECALCULATE_ALL_CANDLES_ON_START`|`true`|NO|Truncate all data from candles table and recalculate all candles| - -`PGPOOLSIZE` is used by the `pg-pool` library to determine Postgres connection pool size per NodeJS process instance. A good value depends on your server and db configuration and can be found empirically. You can leave it at the default value to start with. diff --git a/src/daemons/candles/create.js b/src/daemons/candles/create.js deleted file mode 100644 index 438d6bbd..00000000 --- a/src/daemons/candles/create.js +++ /dev/null @@ -1,171 +0,0 @@ -const { compose, map, nth } = require('ramda'); -const Task = require('folktale/concurrency/task'); -const { fromNullable } = require('folktale/maybe'); - -const getErrorMessage = require('../../errorHandling/getErrorMessage'); -const { CandleInterval } = require('../../types'); - -const logTaskProgress = require('../utils/logTaskProgress'); - -const { - withoutStatementTimeout, - truncateTable, - insertAllMinuteCandles, - insertAllCandles, - selectCandlesAfterTimestamp, - insertOrUpdateCandles, - selectLastCandleHeight, - selectLastExchangeTxHeight, - insertOrUpdateCandlesFromShortInterval, - selectMinTimestampFromHeight, -} = require('./sql/query'); - -/** for combining candles */ -const intervalPairs = [ - [CandleInterval.Minute1, CandleInterval.Minute5], // 1m -> 5m - [CandleInterval.Minute5, CandleInterval.Minute15], // 5m -> 15m - [CandleInterval.Minute15, CandleInterval.Minute30], // 15m -> 30m - [CandleInterval.Minute30, CandleInterval.Hour1], // 30m -> 1h - [CandleInterval.Hour1, CandleInterval.Hour2], // 1h -> 2h - [CandleInterval.Hour1, CandleInterval.Hour3], // 1h -> 3h - [CandleInterval.Hour2, CandleInterval.Hour4], // 2h -> 4h - [CandleInterval.Hour3, CandleInterval.Hour6], // 3h -> 6h - [CandleInterval.Hour6, CandleInterval.Hour12], // 6h -> 12h - [CandleInterval.Hour12, CandleInterval.Day1], // 12h -> 24h - [CandleInterval.Day1, CandleInterval.Week1], // 24h -> 1w - [CandleInterval.Day1, CandleInterval.Month1], // 24h -> 1M -]; - -/** getStartBlock :: (Object, Object) -> Number */ -const getStartBlock = (exchangeTx, candle) => { - if (candle && exchangeTx) { - if (candle.max_height > exchangeTx.height) { - return exchangeTx.height - 2000; // handle rollback - } else { - return candle.max_height - 1; - } - } - - return 1; -}; - -/** updateCandlesLoop :: (LogTask, Pg, String) -> Task */ -const updateCandlesLoop = (logTask, pg, candlesTableName) => { - const logMessages = { - start: (timeStart) => ({ - message: '[CANDLES] start updating candles', - time: timeStart, - }), - error: (e, timeTaken) => { - return { - message: '[CANDLES] update error', - time: timeTaken, - error: getErrorMessage(e), - }; - }, - success: (_, timeTaken) => ({ - message: '[CANDLES] update successful', - time: timeTaken, - }), - }; - - const pgPromiseUpdateCandles = (t, fromTimetamp) => - t - .any(selectCandlesAfterTimestamp(fromTimetamp)) - .then((candles) => - t.any(insertOrUpdateCandles(candlesTableName, candles)) - ); - - return logTask( - logMessages, - pg.tx((t) => - t - .batch([ - t.oneOrNone(selectLastExchangeTxHeight()), - t.oneOrNone(selectLastCandleHeight(candlesTableName)), - ]) - .then(([lastTx, candle]) => { - if (!lastTx) { - return new Date(); - } - const startHeight = getStartBlock(lastTx, candle); - return t - .one(selectMinTimestampFromHeight(startHeight)) - .then((row) => row.time_stamp); - }) - .then((timestamp) => { - const nextInterval = compose( - (m) => m.getOrElse(undefined), - map((interval) => - t.any( - insertOrUpdateCandlesFromShortInterval( - candlesTableName, - timestamp, - interval[0], - interval[1] - ) - ) - ), - fromNullable, - (index) => nth(index, intervalPairs) - ); - - return pgPromiseUpdateCandles(t, timestamp).then(() => - t.sequence(nextInterval) - ); - }) - ) - ); -}; - -/** fillCandlesDBAll :: (LogTask, Pg, String) -> Task */ -const fillCandlesDBAll = (logTask, pg, candlesTableName) => - logTask( - { - start: (timeStart) => ({ - message: '[DB] start filling', - time: timeStart, - }), - error: (e, timeTaken) => ({ - message: '[DB] fill error', - time: timeTaken, - error: e, - }), - success: (_, timeTaken) => ({ - message: '[DB] fill successful', - time: timeTaken, - }), - }, - pg.tx((t) => - t.batch([ - t.none(withoutStatementTimeout()), - t.any(truncateTable(candlesTableName)), - t.any(insertAllMinuteCandles(candlesTableName)), - ...intervalPairs.map(([shorter, longer]) => - t.any(insertAllCandles(candlesTableName, shorter, longer)) - ), - ]) - ) - ); - -module.exports = ({ logger, pg }, configuration) => { - const unsafeLogTaskProgress = logTaskProgress(logger); - - return { - init: () => { - if (configuration.candlesTruncateTable) - return fillCandlesDBAll( - unsafeLogTaskProgress, - pg, - configuration.candlesTableName - ); - else return Task.of(); - }, - loop: () => - updateCandlesLoop( - unsafeLogTaskProgress, - pg, - configuration.candlesTableName - ), - }; -}; diff --git a/src/daemons/candles/index.js b/src/daemons/candles/index.js deleted file mode 100644 index 79281e49..00000000 --- a/src/daemons/candles/index.js +++ /dev/null @@ -1,29 +0,0 @@ -const { loadConfig } = require('./loadConfig'); -const options = loadConfig(); - -// logger -const createLogger = require('../../logger/winston'); -const logger = createLogger({ - logLevel: 'info', -}); - -// pg -const { createPgDriver } = require('../../db'); -const pgDriver = createPgDriver(options); - -const { daemon: runDaemon } = require('../presets/daemon'); -const createDaemon = require('./create'); - -runDaemon( - createDaemon( - { - logger: logger, - pg: pgDriver, - }, - options - ), - options, - options.candlesUpdateInterval, - options.candlesUpdateTimeout, - logger -); diff --git a/src/daemons/candles/loadConfig.ts b/src/daemons/candles/loadConfig.ts deleted file mode 100644 index 35aae963..00000000 --- a/src/daemons/candles/loadConfig.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { memoizeWith, always } from 'ramda'; -import { - PostgresConfig, - LoggerConfig, - loadDefaultConfig, -} from '../../loadConfig'; - -export type CandlesConfig = PostgresConfig & - LoggerConfig & { - candlesUpdateInterval: number; - candlesUpdateTimeout: number; - candlesTruncateTable: boolean; - candlesTableName: string; - }; - -const load = (): CandlesConfig => ({ - ...loadDefaultConfig(), - candlesUpdateInterval: process.env.CANDLES_UPDATE_INTERVAL - ? parseInt(process.env.CANDLES_UPDATE_INTERVAL) - : 2500, - candlesUpdateTimeout: process.env.CANDLES_UPDATE_TIMEOUT - ? parseInt(process.env.CANDLES_UPDATE_TIMEOUT) - : 20000, - candlesTruncateTable: process.env.RECALCULATE_ALL_CANDLES_ON_START - ? process.env.RECALCULATE_ALL_CANDLES_ON_START == 'true' - : false, - candlesTableName: process.env.CANDLES_TABLE_NAME || 'candles', -}); - -export const loadConfig = memoizeWith(always('config'), load); diff --git a/src/daemons/candles/sql/__test__/__snapshots__/sql.test.js.snap b/src/daemons/candles/sql/__test__/__snapshots__/sql.test.js.snap deleted file mode 100644 index 0d470069..00000000 --- a/src/daemons/candles/sql/__test__/__snapshots__/sql.test.js.snap +++ /dev/null @@ -1,17 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`candles daemon sql test calculate and insert all candles from other small candles 1`] = `"insert into \\"candles\\" select to_timestamp(floor((extract('epoch' from time_start) / 300 )) * 300) as \\"candle_time\\", \\"amount_asset_id\\" as \\"amount_asset_id\\", \\"price_asset_id\\" as \\"price_asset_id\\", (select min(\\"low\\")) as \\"low\\", (select max(\\"high\\")) as \\"high\\", (select sum(\\"volume\\")) as \\"volume\\", (select sum(\\"quote_volume\\")) as \\"quote_volume\\", (select max(\\"max_height\\")) as \\"max_height\\", (select sum(\\"txs_count\\")) as \\"txs_count\\", floor(sum((weighted_average_price * volume)::numeric)::numeric / sum(volume)::numeric)::numeric as \\"weighted_average_price\\", (array_agg(open ORDER BY time_start)::numeric[])[1] as \\"open\\", (array_agg(close ORDER BY time_start DESC)::numeric[])[1] as \\"close\\", '5m' as \\"interval\\", \\"matcher_address\\" as \\"matcher_address\\" from \\"candles\\" as \\"t\\" where \\"t\\".\\"interval\\" = '1m' group by \\"candle_time\\", \\"amount_asset_id\\", \\"price_asset_id\\", \\"matcher_address\\""`; - -exports[`candles daemon sql test get last candle height 1`] = `"select \\"max_height\\" from \\"candles\\" as \\"t\\" order by \\"max_height\\" desc limit 1"`; - -exports[`candles daemon sql test get last exchange tx height 1`] = `"select \\"height\\" from \\"txs_7\\" as \\"t\\" order by \\"uid\\" desc limit 1"`; - -exports[`candles daemon sql test insert all candles group by 1 minute 1`] = `"insert into \\"candles\\" with \\"e_cte\\" as (select \\"t\\".\\"uid\\" as \\"uid\\", \\"t\\".\\"amount_asset_id\\" as \\"amount_asset_id\\", \\"t\\".\\"price_asset_id\\" as \\"price_asset_id\\", \\"t\\".\\"sender\\" as \\"sender\\", \\"t\\".\\"height\\" as \\"height\\", date_trunc('minute', t.time_stamp) as \\"candle_time\\", \\"t\\".\\"amount\\" as \\"amount\\", \\"t\\".\\"price\\" as \\"price\\" from \\"txs_7\\" as \\"t\\") select \\"e\\".\\"candle_time\\" as \\"time_start\\", \\"amount_asset_id\\" as \\"amount_asset_id\\", \\"price_asset_id\\" as \\"price_asset_id\\", (select min(\\"e\\".\\"price\\")) as \\"low\\", (select max(\\"e\\".\\"price\\")) as \\"high\\", (select sum(\\"e\\".\\"amount\\")) as \\"volume\\", sum((e.amount)::numeric * (e.price)::numeric) as \\"quote_volume\\", (select max(\\"height\\")) as \\"max_height\\", (select count(\\"e\\".\\"price\\")) as \\"txs_count\\", floor(sum((e.amount)::numeric * (e.price)::numeric)/sum((e.amount)::numeric))::numeric as \\"weighted_average_price\\", (array_agg(e.price ORDER BY e.uid)::numeric[])[1] as \\"open\\", (array_agg(e.price ORDER BY e.uid DESC)::numeric[])[1] as \\"close\\", '1m' as \\"interval\\", \\"e\\".\\"sender\\" as \\"matcher_address\\" from \\"e_cte\\" as \\"e\\" group by e.candle_time, e.amount_asset_id, e.price_asset_id, e.sender"`; - -exports[`candles daemon sql test insert or update array of candles 1`] = `"insert into \\"candles\\" as \\"t\\" (\\"amount_asset_id\\", \\"close\\", \\"high\\", \\"interval\\", \\"low\\", \\"matcher_address\\", \\"max_height\\", \\"open\\", \\"price_asset_id\\", \\"quote_volume\\", \\"time_start\\", \\"txs_count\\", \\"volume\\", \\"weighted_average_price\\") values ('aai', '80', '100', '1m', '1', DEFAULT, DEFAULT, '20', 'pai', '100.2', '1970-01-01T00:00:00.000Z', '22', '200.2', '2.1') on conflict (time_start, amount_asset_id, price_asset_id, matcher_address, interval) do update set open=EXCLUDED.open, close=EXCLUDED.close, low=EXCLUDED.low, high=EXCLUDED.high, max_height=EXCLUDED.max_height, quote_volume=EXCLUDED.quote_volume, txs_count=EXCLUDED.txs_count, volume=EXCLUDED.volume, weighted_average_price=EXCLUDED.weighted_average_price"`; - -exports[`candles daemon sql test insert or update candles empty 1`] = `";"`; - -exports[`candles daemon sql test insert or update candles from height 1`] = `"insert into \\"candles\\" select to_timestamp(floor((extract('epoch' from time_start) / 300 )) * 300) as \\"candle_time\\", \\"amount_asset_id\\" as \\"amount_asset_id\\", \\"price_asset_id\\" as \\"price_asset_id\\", (select min(\\"low\\")) as \\"low\\", (select max(\\"high\\")) as \\"high\\", (select sum(\\"volume\\")) as \\"volume\\", (select sum(\\"quote_volume\\")) as \\"quote_volume\\", (select max(\\"max_height\\")) as \\"max_height\\", (select sum(\\"txs_count\\")) as \\"txs_count\\", floor(sum((weighted_average_price * volume)::numeric)::numeric / sum(volume)::numeric)::numeric as \\"weighted_average_price\\", (array_agg(open ORDER BY time_start)::numeric[])[1] as \\"open\\", (array_agg(close ORDER BY time_start DESC)::numeric[])[1] as \\"close\\", '5m' as \\"interval\\", \\"matcher_address\\" as \\"matcher_address\\" from \\"candles\\" where \\"interval\\" = '1m' and time_start >= to_timestamp(floor((extract('epoch' from '2019-01-01T00:00:00.000Z'::timestamptz) / 300 )) * 300) group by \\"candle_time\\", \\"amount_asset_id\\", \\"price_asset_id\\", \\"matcher_address\\" on conflict (time_start, amount_asset_id, price_asset_id, matcher_address, interval) do update set open=EXCLUDED.open, close=EXCLUDED.close, low=EXCLUDED.low, high=EXCLUDED.high, max_height=EXCLUDED.max_height, quote_volume=EXCLUDED.quote_volume, txs_count=EXCLUDED.txs_count, volume=EXCLUDED.volume, weighted_average_price=EXCLUDED.weighted_average_price"`; - -exports[`candles daemon sql test truncate table 1`] = `"truncate \\"candles\\" restart identity"`; diff --git a/src/daemons/candles/sql/__test__/sql.test.js b/src/daemons/candles/sql/__test__/sql.test.js deleted file mode 100644 index bf112dc1..00000000 --- a/src/daemons/candles/sql/__test__/sql.test.js +++ /dev/null @@ -1,64 +0,0 @@ -const { BigNumber } = require('@waves/data-entities'); -const { CandleInterval } = require('../../../../types'); -const sql = require('../query'); - -describe('candles daemon sql test', () => { - it('truncate table', () => { - expect(sql.truncateTable('candles')).toMatchSnapshot(); - }); - - it('insert all candles group by 1 minute', () => { - expect(sql.insertAllMinuteCandles('candles')).toMatchSnapshot(); - }); - - it('calculate and insert all candles from other small candles', () => { - expect(sql.insertAllCandles('candles', CandleInterval.Minute1, CandleInterval.Minute5)).toMatchSnapshot(); - }); - - it('insert or update array of candles', () => { - expect( - sql.insertOrUpdateCandles('candles', [ - { - time_start: new Date(0), - low: new BigNumber(1), - high: new BigNumber(100), - open: new BigNumber(20), - close: new BigNumber(80), - amount_asset_id: 'aai', - price_asset_id: 'pai', - price: new BigNumber(1.2), - volume: new BigNumber(200.2), - quote_volume: new BigNumber(100.2), - txs_count: new BigNumber(22), - weighted_average_price: new BigNumber(2.1), - matcher_address_uid: new BigNumber(3), - }, - ]) - ).toMatchSnapshot(); - }); - - it('insert or update candles empty', () => { - expect(sql.insertOrUpdateCandles('candles', []).toString()).toMatchSnapshot(); - }); - - it('get last candle height', () => { - expect(sql.selectLastCandleHeight('candles').toString()).toMatchSnapshot(); - }); - - it('get last exchange tx height', () => { - expect(sql.selectLastExchangeTxHeight().toString()).toMatchSnapshot(); - }); - - it('insert or update candles from height', () => { - expect( - sql - .insertOrUpdateCandlesFromShortInterval( - 'candles', - new Date('2019-01-01T00:00:00.000Z'), - CandleInterval.Minute1, - CandleInterval.Minute5 - ) - .toString() - ).toMatchSnapshot(); - }); -}); diff --git a/src/daemons/candles/sql/query.js b/src/daemons/candles/sql/query.js deleted file mode 100644 index 4ff40b7f..00000000 --- a/src/daemons/candles/sql/query.js +++ /dev/null @@ -1,203 +0,0 @@ -const knex = require('knex'); -const pg = knex({ client: 'pg' }); - -const { CandleInterval } = require('../../../types'); - -const { - pgRawDateTrunc, - makeRawTimestamp, - serializeCandle, - candlePresets, -} = require('./utils'); - -/** makeCandleCalculateColumns :: String -> Array */ -const makeCandleCalculateColumns = (interval) => { - return { - candle_time: candlePresets.aggregate.candle_time(interval), - amount_asset_id: 'amount_asset_id', - price_asset_id: 'price_asset_id', - low: candlePresets.aggregate.low, - high: candlePresets.aggregate.high, - volume: candlePresets.aggregate.volume, - quote_volume: candlePresets.aggregate.quote_volume, - max_height: candlePresets.aggregate.max_height, - txs_count: candlePresets.aggregate.txs_count, - weighted_average_price: candlePresets.aggregate.weighted_average_price, - open: candlePresets.aggregate.open, - close: candlePresets.aggregate.close, - interval: pg.raw(`'${interval}'`), - matcher_address: 'matcher_address', - }; -}; - -const candleSelectColumns = { - time_start: 'e.candle_time', - amount_asset_id: 'amount_asset_id', - price_asset_id: 'price_asset_id', - low: pg.min('e.price'), - high: pg.max('e.price'), - volume: pg.sum('e.amount'), - quote_volume: pg.raw('sum((e.amount)::numeric * (e.price)::numeric)'), - max_height: pg.max('height'), - txs_count: pg.count('e.price'), - weighted_average_price: pg.raw( - 'floor(sum((e.amount)::numeric * (e.price)::numeric)/sum((e.amount)::numeric))::numeric' - ), - open: pg.raw('(array_agg(e.price ORDER BY e.uid)::numeric[])[1]'), - close: pg.raw('(array_agg(e.price ORDER BY e.uid DESC)::numeric[])[1]'), - interval: pg.raw(`'${CandleInterval.Minute1}'`), - matcher_address: 'e.sender', -}; - -/** insertIntoCandlesFromSelect :: (String, Function) -> QueryBuilder */ -const insertIntoCandlesFromSelect = (candlesTableName, selectFunction) => - pg.into(candlesTableName).insert(selectFunction); - -/** selectExchanges :: QueryBuilder */ -const selectExchanges = pg({ t: 'txs_7' }).select({ - uid: 't.uid', - amount_asset_id: 't.amount_asset_id', - price_asset_id: 't.price_asset_id', - sender: 't.sender', - height: 't.height', - candle_time: pgRawDateTrunc('t.time_stamp')('minute'), - amount: 't.amount', - price: pg.raw(` - CASE WHEN t.tx_version > 2 - THEN t.price::numeric - * 10^(select decimals from assets where asset_id = t.price_asset_id) - * 10^(select -decimals from assets where asset_id = t.amount_asset_id) - ELSE t.price::numeric - END - `), -}); - -/** selectExchangesAfterTimestamp :: Date -> QueryBuilder */ -const selectExchangesAfterTimestamp = (fromTimestamp) => { - let ts = pgRawDateTrunc(`'${fromTimestamp.toISOString()}'::timestamptz`)('minute'); - return selectExchanges - .clone() - .whereRaw(`time_stamp >= ${ts}`) - .orderBy('uid') - .orderByRaw(`time_stamp <-> ${ts}`); -}; - -/** selectLastCandle :: String -> String query */ -const selectLastCandleHeight = (candlesTableName) => - pg({ t: candlesTableName }) - .select('max_height') - .limit(1) - .orderBy('max_height', 'desc') - .toString(); - -/** selectLastExchangeTx :: String query */ -const selectLastExchangeTxHeight = () => - pg({ t: 'txs_7' }).select('height').limit(1).orderBy('uid', 'desc').toString(); - -/** selectLastExchangeTx :: String query */ -const selectMinTimestampFromHeight = (height) => - pg('txs_7') - .column('time_stamp') - .where('height', '>=', height) - .orderBy('uid') - .limit(1) - .toString(); - -/** for make complex query with "on conflict (...) update ... without set concrete values" See insertOrUpdateCandles or insertOrUpdateCandlesFromShortInterval */ -const updatedFieldsExcluded = [ - 'open', - 'close', - 'low', - 'high', - 'max_height', - 'quote_volume', - 'txs_count', - 'volume', - 'weighted_average_price', -] - .map((field) => field + '=EXCLUDED.' + field) - .join(', '); - -/** insertOrUpdateCandles :: (String, Array[Object]) -> String query */ -const insertOrUpdateCandles = (candlesTableName, candles) => { - if (candles.length) { - return pg - .raw( - `${pg({ t: candlesTableName }).insert( - candles.map(serializeCandle) - )} on conflict (time_start, amount_asset_id, price_asset_id, matcher_address, interval) do update set ${updatedFieldsExcluded}` - ) - .toString(); - } - - return ';'; -}; - -/** insertOrUpdateCandlesFromShortInterval :: (String, Date, Number, Number) -> String query */ -const insertOrUpdateCandlesFromShortInterval = ( - candlesTableName, - fromTimestamp, - shortInterval, - longerInterval -) => - pg - .raw( - `${insertIntoCandlesFromSelect(candlesTableName, function () { - this.from(candlesTableName) - .select(makeCandleCalculateColumns(longerInterval)) - .where('interval', shortInterval) - .whereRaw( - pg.raw(`time_start >= ${makeRawTimestamp(fromTimestamp, longerInterval)}`) - ) - .groupBy('candle_time', 'amount_asset_id', 'price_asset_id', 'matcher_address'); - })} on conflict (time_start, amount_asset_id, price_asset_id, matcher_address, interval) do update set ${updatedFieldsExcluded}` - ) - .toString(); - -/** - * SET statement_timeout = 0 - * @returns string - */ -const withoutStatementTimeout = () => pg.raw('SET statement_timeout = 0').toString(); - -/** truncateTable :: String -> String query */ -const truncateTable = (candlesTableName) => pg(candlesTableName).truncate().toString(); - -/** insertAllMinuteCandles :: String -> String query */ -const insertAllMinuteCandles = (candlesTableName) => - insertIntoCandlesFromSelect(candlesTableName, function () { - this.with('e_cte', selectExchanges) - .select(candleSelectColumns) - .from({ e: 'e_cte' }) - .groupByRaw('e.candle_time, e.amount_asset_id, e.price_asset_id, e.sender'); - }).toString(); - -/** insertAllCandles :: (String, Number, Number, Number) -> String query */ -const insertAllCandles = (candlesTableName, shortInterval, longerInterval) => - insertIntoCandlesFromSelect(candlesTableName, function () { - this.from({ t: candlesTableName }) - .column(makeCandleCalculateColumns(longerInterval)) - .where('t.interval', shortInterval) - .groupBy(['candle_time', 'amount_asset_id', 'price_asset_id', 'matcher_address']); - }).toString(); - -/** selectCandlesAfterTimestamp :: Date -> String query */ -const selectCandlesAfterTimestamp = (timetamp) => - pg - .columns(candleSelectColumns) - .from(selectExchangesAfterTimestamp(timetamp).clone().as('e')) - .groupBy(['e.candle_time', 'e.amount_asset_id', 'e.price_asset_id', 'e.sender']) - .toString(); - -module.exports = { - withoutStatementTimeout, - truncateTable, - insertAllMinuteCandles, - insertAllCandles, - selectCandlesAfterTimestamp, - insertOrUpdateCandles, - selectLastCandleHeight, - selectLastExchangeTxHeight, - insertOrUpdateCandlesFromShortInterval, - selectMinTimestampFromHeight, -}; diff --git a/src/daemons/candles/sql/utils.js b/src/daemons/candles/sql/utils.js deleted file mode 100644 index 0e4ddfa3..00000000 --- a/src/daemons/candles/sql/utils.js +++ /dev/null @@ -1,111 +0,0 @@ -const knex = require('knex'); -const pg = knex({ client: 'pg' }); - -const { CandleInterval } = require('../../../types'); - -/** - * - * @param {string} from - */ -const pgRawExtractFromToTimestamp = (from) => /** @param {string} interval */ ( - interval -) => - pg.raw( - `to_timestamp(floor((extract('epoch' from ${from}) / ${interval} )) * ${interval})` - ); - -/** - * - * @param {string} from - */ -const pgRawDateTrunc = (from) => /** @param {string} interval */ (interval) => - pg.raw(`date_trunc('${interval}', ${from})`); - -/** - * - * @param {string} from - * @param {keyof CandleInterval} interval - */ -const toRawTimestamp = (from, interval) => { - const nf = pgRawExtractFromToTimestamp(from); - const sf = pgRawDateTrunc(from); - - switch (interval) { - case CandleInterval.Minute1: - return nf(60); - case CandleInterval.Minute5: - return nf(300); - case CandleInterval.Minute15: - return nf(900); - case CandleInterval.Minute30: - return nf(1800); - case CandleInterval.Hour1: - return nf(3600); - case CandleInterval.Hour2: - return nf(7200); - case CandleInterval.Hour3: - return nf(10800); - case CandleInterval.Hour4: - return nf(14400); - case CandleInterval.Hour6: - return nf(21600); - case CandleInterval.Hour12: - return nf(43200); - case CandleInterval.Day1: - return nf(86400); - case CandleInterval.Week1: - return sf('week'); - case CandleInterval.Month1: - return sf('month'); - } -}; - -/** - * @param {Date} timestamp - * @param {string} interval - */ -const makeRawTimestamp = (timestamp, interval) => - toRawTimestamp(`'${timestamp.toISOString()}'::timestamptz`, interval); - -// serializeCandle:: Object => Object -// @todo refactor after pg updating for work with BigInt instead of BigNumber -const serializeCandle = (candle) => ({ - time_start: candle.time_start.toISOString(), - amount_asset_id: candle.amount_asset_id, - price_asset_id: candle.price_asset_id, - matcher_address: candle.matcher_address, - low: candle.low.toString(), - high: candle.high.toString(), - volume: candle.volume.toString(), - quote_volume: candle.quote_volume.toString(), - max_height: candle.max_height, - txs_count: candle.txs_count.toString(), - weighted_average_price: candle.weighted_average_price.toString(), - open: candle.open.toString(), - close: candle.close.toString(), - interval: CandleInterval.Minute1, -}); - -const candlePresets = { - aggregate: { - candle_time: (interval) => toRawTimestamp('time_start', interval), - low: pg.min('low'), - high: pg.max('high'), - volume: pg.sum('volume'), - quote_volume: pg.sum('quote_volume'), - max_height: pg.max('max_height'), - txs_count: pg.sum('txs_count'), - weighted_average_price: pg.raw( - 'floor(sum((weighted_average_price * volume)::numeric)::numeric / sum(volume)::numeric)::numeric' - ), - open: pg.raw('(array_agg(open ORDER BY time_start)::numeric[])[1]'), - close: pg.raw('(array_agg(close ORDER BY time_start DESC)::numeric[])[1]'), - }, -}; - -module.exports = { - pgRawDateTrunc, - makeRawTimestamp, - serializeCandle, - candlePresets, -};