diff --git a/package-lock.json b/package-lock.json index 154434cfa..5cdb34a33 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,11 +18,11 @@ "@multiversx/sdk-data-api-client": "^0.5.8", "@multiversx/sdk-exchange": "^0.2.19", "@multiversx/sdk-native-auth-server": "1.0.15", - "@multiversx/sdk-nestjs-cache": "^2.0.0-beta.2", - "@multiversx/sdk-nestjs-common": "^2.0.0-beta.2", - "@multiversx/sdk-nestjs-elastic": "^2.0.0-beta.3", - "@multiversx/sdk-nestjs-http": "^2.0.0-beta.2", - "@multiversx/sdk-nestjs-monitoring": "^2.0.0-beta.2", + "@multiversx/sdk-nestjs-cache": "^3.7.0", + "@multiversx/sdk-nestjs-common": "^3.7.0", + "@multiversx/sdk-nestjs-elastic": "^3.7.0", + "@multiversx/sdk-nestjs-http": "^3.7.0", + "@multiversx/sdk-nestjs-monitoring": "^3.7.0", "@multiversx/sdk-network-providers": "^2.0.0", "@nestjs/apollo": "^12.0.7", "@nestjs/axios": "^3.0.0", @@ -2954,9 +2954,9 @@ "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" }, "node_modules/@multiversx/sdk-nestjs-cache": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-cache/-/sdk-nestjs-cache-2.4.2.tgz", - "integrity": "sha512-eP1mMp4WbU8hk0aRXxK13TY3ewiD3pykZ6y0psuEyu/5j9KpctJpuRWMv9Q77dxWCb9/DQWuSXv19kt70EbE8g==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-cache/-/sdk-nestjs-cache-3.7.0.tgz", + "integrity": "sha512-fl4oToEgXoJ8fsi47htG9QsIMcOukx972ECBntaNB++gUwbgGNpWhRxH/4y2t8CWNFsln9/MXBLGUQT6LPMaXQ==", "dependencies": { "lru-cache": "^8.0.4", "moment": "^2.29.4", @@ -2965,9 +2965,9 @@ "uuid": "^8.3.2" }, "peerDependencies": { - "@multiversx/sdk-nestjs-common": "^2.0.0", - "@multiversx/sdk-nestjs-monitoring": "^2.0.0", - "@multiversx/sdk-nestjs-redis": "^2.0.0", + "@multiversx/sdk-nestjs-common": "^3.0.0", + "@multiversx/sdk-nestjs-monitoring": "^3.0.0", + "@multiversx/sdk-nestjs-redis": "^3.0.0", "@nestjs/common": "^10.x", "@nestjs/core": "^10.x" } @@ -2989,20 +2989,18 @@ } }, "node_modules/@multiversx/sdk-nestjs-common": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-common/-/sdk-nestjs-common-2.4.2.tgz", - "integrity": "sha512-0CmBXER/UDsRweRH82oJxIl9WMXE4BhdftDCzpR7xbjdnDTg+4pHDtmkejwaSdu5g8AGbsgltM7Mr26YE9R3+w==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-common/-/sdk-nestjs-common-3.7.0.tgz", + "integrity": "sha512-+g7lhCywHd6Zz/oIabw+RxdyJqMwzGKrl+IbofYCm2kpGz6tDiwmVi38SFmkb7wWJoVsKqLDn7G/XLuwdYylow==", "dependencies": { - "@multiversx/sdk-core": "12.6.1", - "@multiversx/sdk-native-auth-client": "^1.0.0", - "@multiversx/sdk-native-auth-server": "^1.0.4", - "@multiversx/sdk-network-providers": "^1.3.0", + "@multiversx/sdk-core": "^13.1.0", + "@multiversx/sdk-network-providers": "^2.4.3", "nest-winston": "^1.6.2", "uuid": "^8.3.2", "winston": "^3.7.2" }, "peerDependencies": { - "@multiversx/sdk-nestjs-monitoring": "^2.0.0", + "@multiversx/sdk-nestjs-monitoring": "^3.0.0", "@nestjs/common": "^10.x", "@nestjs/config": "^3.x", "@nestjs/core": "^10.x", @@ -3010,69 +3008,50 @@ } }, "node_modules/@multiversx/sdk-nestjs-common/node_modules/@multiversx/sdk-core": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-12.6.1.tgz", - "integrity": "sha512-T21TMC3euAi3C0WtB6WOzNYQW4XbKTrH0Q1K7gxcNpLDqnQbMwh0SuVAossQRL/s1Ca829Zjt3zmuGQUtWAU1A==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-13.1.0.tgz", + "integrity": "sha512-Z8lDPX4mKKD0QUtAqRzM0bf8zex3xCWRd5yYRLCxjW1F+jYg+9LjIQjkyvDSWGYJHY4IJeYqkORoS3gQG8NDbA==", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", "bech32": "1.1.4", - "bignumber.js": "9.0.1", "blake2b": "2.1.3", "buffer": "6.0.3", - "json-duplicate-key-handle": "1.0.0", - "keccak": "3.0.2", - "protobufjs": "7.2.4" - } - }, - "node_modules/@multiversx/sdk-nestjs-common/node_modules/@multiversx/sdk-native-auth-client": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-native-auth-client/-/sdk-native-auth-client-1.0.7.tgz", - "integrity": "sha512-Fl/4DcM8tJ4dULIu03lMfi875qatGMe8DLg6HglQRB+2s5YoW3NrWkqKNrIbG0CbYCaCH9Sk5nOZkZse8FwNQg==", - "dependencies": { - "axios": "^1.6.5" - } - }, - "node_modules/@multiversx/sdk-nestjs-common/node_modules/@multiversx/sdk-native-auth-client/node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", - "dependencies": { - "follow-redirects": "^1.15.4", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/@multiversx/sdk-nestjs-common/node_modules/@multiversx/sdk-network-providers": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-1.5.0.tgz", - "integrity": "sha512-GgmpOfwdeK8QvBCVJ96/L2ATNax7/rdSDvPLlmppKHVuFAj56/EqGnrLuktNPRWBsZse+7DMoS38kGtN77AwJQ==", - "dependencies": { - "axios": "0.24.0", - "bech32": "1.1.4", - "bignumber.js": "9.0.1", - "buffer": "6.0.3", - "json-bigint": "1.0.0" + "json-bigint": "1.0.0", + "keccak": "3.0.2" + }, + "peerDependencies": { + "bignumber.js": "^9.0.1", + "protobufjs": "^7.2.6" } }, - "node_modules/@multiversx/sdk-nestjs-common/node_modules/axios": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", - "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", - "dependencies": { - "follow-redirects": "^1.14.4" - } + "node_modules/@multiversx/sdk-nestjs-common/node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "peer": true }, - "node_modules/@multiversx/sdk-nestjs-common/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "node_modules/@multiversx/sdk-nestjs-common/node_modules/protobufjs": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.0.tgz", + "integrity": "sha512-YWD03n3shzV9ImZRX3ccbjqLxj7NokGN0V/ESiBV5xWqrommYHYiihuIyavq03pWSGqlyvYUFmfoMKd+1rPA/g==", + "hasInstallScript": true, + "peer": true, "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" }, "engines": { - "node": ">= 6" + "node": ">=12.0.0" } }, "node_modules/@multiversx/sdk-nestjs-common/node_modules/uuid": { @@ -3084,55 +3063,46 @@ } }, "node_modules/@multiversx/sdk-nestjs-elastic": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-elastic/-/sdk-nestjs-elastic-2.4.2.tgz", - "integrity": "sha512-XltsOgsBxuqQIvZKQ563XdObx9Ce9FXaUz8requZPo3EEG2Qafk2FVp01fTyp5bqBMjHfTEDML4wAdsr9wOrZQ==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-elastic/-/sdk-nestjs-elastic-3.7.0.tgz", + "integrity": "sha512-+IoknzKUMAde7WNRT2l+oP8h1mCsSRjk4eEftb8NPO4T8QpUAgIluDc9FOwmCAhfm/32BfFaJ9VvjZXJtcxTrQ==", "peerDependencies": { - "@multiversx/sdk-nestjs-http": "^2.0.0", + "@multiversx/sdk-nestjs-http": "^3.2.1", "@nestjs/common": "^10.x" } }, "node_modules/@multiversx/sdk-nestjs-http": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-http/-/sdk-nestjs-http-2.4.2.tgz", - "integrity": "sha512-SPl8DFeoUmrIaPLvuU/SiLjzwwLu8ziSx7xr5wPlKKDR2M9TdcTa7hneeNoAcqOl36iCv1dGvKqh6qZRo6xITg==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-http/-/sdk-nestjs-http-3.7.0.tgz", + "integrity": "sha512-RzZPiVxWbrLfPAFydZOHBcQyqKCLZ7bYpRo+K6xV6X/BbcHEXLUfp3sI7Cz7jsTMhUddxguarwcKYmCtY4j9EA==", "dependencies": { - "@multiversx/sdk-wallet": "3.0.0", + "@multiversx/sdk-native-auth-client": "^1.0.8", "agentkeepalive": "^4.3.0", - "axios": "^0.27.2" + "axios": "^1.6.8" }, "peerDependencies": { - "@multiversx/sdk-nestjs-common": "^2.0.0", - "@multiversx/sdk-nestjs-monitoring": "^2.0.0", - "@multiversx/sdk-wallet": "<=3.0.0", + "@multiversx/sdk-nestjs-common": "^3.0.0", + "@multiversx/sdk-nestjs-monitoring": "^3.0.0", "@nestjs/common": "^10.x", "@nestjs/core": "^10.x" } }, - "node_modules/@multiversx/sdk-nestjs-http/node_modules/@multiversx/sdk-wallet": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-wallet/-/sdk-wallet-3.0.0.tgz", - "integrity": "sha512-nDVBtva1mpfutXA8TfUnpdeFqhY9O+deNU3U/Z41yPBcju1trHDC9gcKPyQqcQ3qjG/6LwEXmIm7Dc5fIsvVjg==", + "node_modules/@multiversx/sdk-nestjs-http/node_modules/@multiversx/sdk-native-auth-client": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-native-auth-client/-/sdk-native-auth-client-1.0.8.tgz", + "integrity": "sha512-anXcQplVp3/m2rBH4oGQZNIhk0m/J45SomubNMCgSzepJ2PU5E5eQLYletvSDObhTGfRnNCF8edAldkDP9a4Kw==", "dependencies": { - "@multiversx/sdk-bls-wasm": "0.3.5", - "bech32": "1.1.4", - "bip39": "3.0.2", - "blake2b": "2.1.3", - "ed25519-hd-key": "1.1.2", - "ed2curve": "0.3.0", - "keccak": "3.0.1", - "scryptsy": "2.1.0", - "tweetnacl": "1.0.3", - "uuid": "8.3.2" + "axios": "^1.6.8" } }, "node_modules/@multiversx/sdk-nestjs-http/node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "node_modules/@multiversx/sdk-nestjs-http/node_modules/form-data": { @@ -3148,31 +3118,10 @@ "node": ">= 6" } }, - "node_modules/@multiversx/sdk-nestjs-http/node_modules/keccak": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", - "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@multiversx/sdk-nestjs-http/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@multiversx/sdk-nestjs-monitoring": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-monitoring/-/sdk-nestjs-monitoring-2.4.2.tgz", - "integrity": "sha512-9qe/5FPYoL6cWAcPVuIArWbteCE4nh207sSQYCHDVdBrs5c3BqEGItWXZ5o+SVQ0xW5F6oWlHPUmUqI6Odk/UA==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-monitoring/-/sdk-nestjs-monitoring-3.7.0.tgz", + "integrity": "sha512-hSFHIJKoraoZ8gaZo+Y/R9uTF8JGEOU6PmAW8jAgYUV+QyqaG2eFRrN8ERyDv0vELa7XCqMgMnHzkd8Sydzwlw==", "dependencies": { "prom-client": "^14.0.1", "winston": "^3.7.2", @@ -3183,9 +3132,9 @@ } }, "node_modules/@multiversx/sdk-nestjs-redis": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-redis/-/sdk-nestjs-redis-2.4.2.tgz", - "integrity": "sha512-VCYeJqUti9a4L+XsVeE4Q3nCQw1CSD+cF48dQYaNo8pMIieVWqY9dJbI3P0fd4kSuiuv9ouRTEYHwDfFTov5ag==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-redis/-/sdk-nestjs-redis-3.7.0.tgz", + "integrity": "sha512-6VwFGCELTZYvnkxCD7cDOKs7FSTsLSjRfDN2klhdsYFdp5fFqAHOH1uNyrzg1HReeQayJ7PPRatEPBI7fj9/xg==", "peer": true, "dependencies": { "ioredis": "^5.2.3" @@ -3195,40 +3144,17 @@ } }, "node_modules/@multiversx/sdk-network-providers": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.2.1.tgz", - "integrity": "sha512-JsGznvyZSIBLpQ9bRjyv0EWfstaqDyFRBzokNZSbwk5z+3LjQFZxPTU3iv95BvW/rPQh8L0zD8Xwjw05pjTLyA==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.4.3.tgz", + "integrity": "sha512-tJmJuxU+BjtC2q29PuzQOM4Qr6aiXujKwQXgIAPHTiuNbMc3Yi6Q4B0DC1PfI3iG+M4DONwfXknvM1uwqnY2zA==", "dependencies": { - "axios": "1.6.5", + "axios": "1.6.8", "bech32": "1.1.4", "bignumber.js": "9.0.1", "buffer": "6.0.3", "json-bigint": "1.0.0" } }, - "node_modules/@multiversx/sdk-network-providers/node_modules/axios": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", - "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", - "dependencies": { - "follow-redirects": "^1.15.4", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/@multiversx/sdk-network-providers/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/@multiversx/sdk-transaction-decoder": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@multiversx/sdk-transaction-decoder/-/sdk-transaction-decoder-1.0.2.tgz", @@ -6191,11 +6117,11 @@ } }, "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -9235,9 +9161,9 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -19073,9 +18999,9 @@ } }, "@multiversx/sdk-nestjs-cache": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-cache/-/sdk-nestjs-cache-2.4.2.tgz", - "integrity": "sha512-eP1mMp4WbU8hk0aRXxK13TY3ewiD3pykZ6y0psuEyu/5j9KpctJpuRWMv9Q77dxWCb9/DQWuSXv19kt70EbE8g==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-cache/-/sdk-nestjs-cache-3.7.0.tgz", + "integrity": "sha512-fl4oToEgXoJ8fsi47htG9QsIMcOukx972ECBntaNB++gUwbgGNpWhRxH/4y2t8CWNFsln9/MXBLGUQT6LPMaXQ==", "requires": { "lru-cache": "^8.0.4", "moment": "^2.29.4", @@ -19097,82 +19023,54 @@ } }, "@multiversx/sdk-nestjs-common": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-common/-/sdk-nestjs-common-2.4.2.tgz", - "integrity": "sha512-0CmBXER/UDsRweRH82oJxIl9WMXE4BhdftDCzpR7xbjdnDTg+4pHDtmkejwaSdu5g8AGbsgltM7Mr26YE9R3+w==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-common/-/sdk-nestjs-common-3.7.0.tgz", + "integrity": "sha512-+g7lhCywHd6Zz/oIabw+RxdyJqMwzGKrl+IbofYCm2kpGz6tDiwmVi38SFmkb7wWJoVsKqLDn7G/XLuwdYylow==", "requires": { - "@multiversx/sdk-core": "12.6.1", - "@multiversx/sdk-native-auth-client": "^1.0.0", - "@multiversx/sdk-native-auth-server": "^1.0.4", - "@multiversx/sdk-network-providers": "^1.3.0", + "@multiversx/sdk-core": "^13.1.0", + "@multiversx/sdk-network-providers": "^2.4.3", "nest-winston": "^1.6.2", "uuid": "^8.3.2", "winston": "^3.7.2" }, "dependencies": { "@multiversx/sdk-core": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-12.6.1.tgz", - "integrity": "sha512-T21TMC3euAi3C0WtB6WOzNYQW4XbKTrH0Q1K7gxcNpLDqnQbMwh0SuVAossQRL/s1Ca829Zjt3zmuGQUtWAU1A==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-13.1.0.tgz", + "integrity": "sha512-Z8lDPX4mKKD0QUtAqRzM0bf8zex3xCWRd5yYRLCxjW1F+jYg+9LjIQjkyvDSWGYJHY4IJeYqkORoS3gQG8NDbA==", "requires": { "@multiversx/sdk-transaction-decoder": "1.0.2", "bech32": "1.1.4", - "bignumber.js": "9.0.1", "blake2b": "2.1.3", "buffer": "6.0.3", - "json-duplicate-key-handle": "1.0.0", - "keccak": "3.0.2", - "protobufjs": "7.2.4" + "json-bigint": "1.0.0", + "keccak": "3.0.2" } }, - "@multiversx/sdk-native-auth-client": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-native-auth-client/-/sdk-native-auth-client-1.0.7.tgz", - "integrity": "sha512-Fl/4DcM8tJ4dULIu03lMfi875qatGMe8DLg6HglQRB+2s5YoW3NrWkqKNrIbG0CbYCaCH9Sk5nOZkZse8FwNQg==", - "requires": { - "axios": "^1.6.5" - }, - "dependencies": { - "axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", - "requires": { - "follow-redirects": "^1.15.4", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - } - } - }, - "@multiversx/sdk-network-providers": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-1.5.0.tgz", - "integrity": "sha512-GgmpOfwdeK8QvBCVJ96/L2ATNax7/rdSDvPLlmppKHVuFAj56/EqGnrLuktNPRWBsZse+7DMoS38kGtN77AwJQ==", - "requires": { - "axios": "0.24.0", - "bech32": "1.1.4", - "bignumber.js": "9.0.1", - "buffer": "6.0.3", - "json-bigint": "1.0.0" - } - }, - "axios": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", - "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", - "requires": { - "follow-redirects": "^1.14.4" - } + "long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "peer": true }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "protobufjs": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.0.tgz", + "integrity": "sha512-YWD03n3shzV9ImZRX3ccbjqLxj7NokGN0V/ESiBV5xWqrommYHYiihuIyavq03pWSGqlyvYUFmfoMKd+1rPA/g==", + "peer": true, "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" } }, "uuid": { @@ -19183,45 +19081,37 @@ } }, "@multiversx/sdk-nestjs-elastic": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-elastic/-/sdk-nestjs-elastic-2.4.2.tgz", - "integrity": "sha512-XltsOgsBxuqQIvZKQ563XdObx9Ce9FXaUz8requZPo3EEG2Qafk2FVp01fTyp5bqBMjHfTEDML4wAdsr9wOrZQ==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-elastic/-/sdk-nestjs-elastic-3.7.0.tgz", + "integrity": "sha512-+IoknzKUMAde7WNRT2l+oP8h1mCsSRjk4eEftb8NPO4T8QpUAgIluDc9FOwmCAhfm/32BfFaJ9VvjZXJtcxTrQ==", "requires": {} }, "@multiversx/sdk-nestjs-http": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-http/-/sdk-nestjs-http-2.4.2.tgz", - "integrity": "sha512-SPl8DFeoUmrIaPLvuU/SiLjzwwLu8ziSx7xr5wPlKKDR2M9TdcTa7hneeNoAcqOl36iCv1dGvKqh6qZRo6xITg==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-http/-/sdk-nestjs-http-3.7.0.tgz", + "integrity": "sha512-RzZPiVxWbrLfPAFydZOHBcQyqKCLZ7bYpRo+K6xV6X/BbcHEXLUfp3sI7Cz7jsTMhUddxguarwcKYmCtY4j9EA==", "requires": { - "@multiversx/sdk-wallet": "3.0.0", + "@multiversx/sdk-native-auth-client": "^1.0.8", "agentkeepalive": "^4.3.0", - "axios": "^0.27.2" + "axios": "^1.6.8" }, "dependencies": { - "@multiversx/sdk-wallet": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-wallet/-/sdk-wallet-3.0.0.tgz", - "integrity": "sha512-nDVBtva1mpfutXA8TfUnpdeFqhY9O+deNU3U/Z41yPBcju1trHDC9gcKPyQqcQ3qjG/6LwEXmIm7Dc5fIsvVjg==", + "@multiversx/sdk-native-auth-client": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-native-auth-client/-/sdk-native-auth-client-1.0.8.tgz", + "integrity": "sha512-anXcQplVp3/m2rBH4oGQZNIhk0m/J45SomubNMCgSzepJ2PU5E5eQLYletvSDObhTGfRnNCF8edAldkDP9a4Kw==", "requires": { - "@multiversx/sdk-bls-wasm": "0.3.5", - "bech32": "1.1.4", - "bip39": "3.0.2", - "blake2b": "2.1.3", - "ed25519-hd-key": "1.1.2", - "ed2curve": "0.3.0", - "keccak": "3.0.1", - "scryptsy": "2.1.0", - "tweetnacl": "1.0.3", - "uuid": "8.3.2" + "axios": "^1.6.8" } }, "axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", "requires": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "form-data": { @@ -19233,27 +19123,13 @@ "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } - }, - "keccak": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", - "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", - "requires": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" } } }, "@multiversx/sdk-nestjs-monitoring": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-monitoring/-/sdk-nestjs-monitoring-2.4.2.tgz", - "integrity": "sha512-9qe/5FPYoL6cWAcPVuIArWbteCE4nh207sSQYCHDVdBrs5c3BqEGItWXZ5o+SVQ0xW5F6oWlHPUmUqI6Odk/UA==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-monitoring/-/sdk-nestjs-monitoring-3.7.0.tgz", + "integrity": "sha512-hSFHIJKoraoZ8gaZo+Y/R9uTF8JGEOU6PmAW8jAgYUV+QyqaG2eFRrN8ERyDv0vELa7XCqMgMnHzkd8Sydzwlw==", "requires": { "prom-client": "^14.0.1", "winston": "^3.7.2", @@ -19261,46 +19137,24 @@ } }, "@multiversx/sdk-nestjs-redis": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-redis/-/sdk-nestjs-redis-2.4.2.tgz", - "integrity": "sha512-VCYeJqUti9a4L+XsVeE4Q3nCQw1CSD+cF48dQYaNo8pMIieVWqY9dJbI3P0fd4kSuiuv9ouRTEYHwDfFTov5ag==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-redis/-/sdk-nestjs-redis-3.7.0.tgz", + "integrity": "sha512-6VwFGCELTZYvnkxCD7cDOKs7FSTsLSjRfDN2klhdsYFdp5fFqAHOH1uNyrzg1HReeQayJ7PPRatEPBI7fj9/xg==", "peer": true, "requires": { "ioredis": "^5.2.3" } }, "@multiversx/sdk-network-providers": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.2.1.tgz", - "integrity": "sha512-JsGznvyZSIBLpQ9bRjyv0EWfstaqDyFRBzokNZSbwk5z+3LjQFZxPTU3iv95BvW/rPQh8L0zD8Xwjw05pjTLyA==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-network-providers/-/sdk-network-providers-2.4.3.tgz", + "integrity": "sha512-tJmJuxU+BjtC2q29PuzQOM4Qr6aiXujKwQXgIAPHTiuNbMc3Yi6Q4B0DC1PfI3iG+M4DONwfXknvM1uwqnY2zA==", "requires": { - "axios": "1.6.5", + "axios": "1.6.8", "bech32": "1.1.4", "bignumber.js": "9.0.1", "buffer": "6.0.3", "json-bigint": "1.0.0" - }, - "dependencies": { - "axios": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", - "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", - "requires": { - "follow-redirects": "^1.15.4", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - } } }, "@multiversx/sdk-transaction-decoder": { @@ -21441,11 +21295,11 @@ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, "axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", "requires": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" }, @@ -23770,9 +23624,9 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==" + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" }, "for-each": { "version": "0.3.3", diff --git a/package.json b/package.json index 4da2b0793..f669042ef 100644 --- a/package.json +++ b/package.json @@ -35,11 +35,11 @@ "@multiversx/sdk-data-api-client": "^0.5.8", "@multiversx/sdk-exchange": "^0.2.19", "@multiversx/sdk-native-auth-server": "1.0.15", - "@multiversx/sdk-nestjs-cache": "^2.0.0-beta.2", - "@multiversx/sdk-nestjs-common": "^2.0.0-beta.2", - "@multiversx/sdk-nestjs-elastic": "^2.0.0-beta.3", - "@multiversx/sdk-nestjs-http": "^2.0.0-beta.2", - "@multiversx/sdk-nestjs-monitoring": "^2.0.0-beta.2", + "@multiversx/sdk-nestjs-cache": "^3.7.0", + "@multiversx/sdk-nestjs-common": "^3.7.0", + "@multiversx/sdk-nestjs-elastic": "^3.7.0", + "@multiversx/sdk-nestjs-http": "^3.7.0", + "@multiversx/sdk-nestjs-monitoring": "^3.7.0", "@multiversx/sdk-network-providers": "^2.0.0", "@nestjs/apollo": "^12.0.7", "@nestjs/axios": "^3.0.0", diff --git a/src/endpoints/metrics/metrics.controller.ts b/src/endpoints/metrics/metrics.controller.ts index e4b1fcae0..e2c99bb84 100644 --- a/src/endpoints/metrics/metrics.controller.ts +++ b/src/endpoints/metrics/metrics.controller.ts @@ -6,11 +6,11 @@ import { Param, } from '@nestjs/common'; import { MetricsCollector } from 'src/utils/metrics.collector'; -import { MetricsService } from './metrics.service'; +import { ESTransactionsService } from 'src/services/elastic-search/services/es.transactions.service'; @Controller() export class MetricsController { - constructor(private readonly metricsService: MetricsService) {} + constructor(private readonly metricsService: ESTransactionsService) {} @Get('/metrics') async getMetrics(): Promise { diff --git a/src/helpers/api.config.service.ts b/src/helpers/api.config.service.ts index ec5895504..f7acb28b5 100644 --- a/src/helpers/api.config.service.ts +++ b/src/helpers/api.config.service.ts @@ -312,4 +312,18 @@ export class ApiConfigService { } return password; } + + getElasticSearchUrl(): string { + const elasticSearchUrl = + this.configService.get('ELASTICSEARCH_URL'); + if (!elasticSearchUrl) { + throw new Error('No Elastic Search url present'); + } + + return elasticSearchUrl; + } + + getRateLimiterSecret(): string | undefined { + return this.configService.get('RATE_LIMITER_SECRET'); + } } diff --git a/src/modules/analytics/specs/analytics.service.spec.ts b/src/modules/analytics/specs/analytics.service.spec.ts index 57ce66a3c..90733d484 100644 --- a/src/modules/analytics/specs/analytics.service.spec.ts +++ b/src/modules/analytics/specs/analytics.service.spec.ts @@ -45,7 +45,7 @@ import { WinstonModule } from 'nest-winston'; import { ApiConfigService } from 'src/helpers/api.config.service'; import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('AnalyticsService', () => { let module: TestingModule; @@ -58,6 +58,7 @@ describe('AnalyticsService', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ ContextGetterServiceProvider, @@ -104,7 +105,6 @@ describe('AnalyticsService', () => { RemoteConfigGetterServiceProvider, AnalyticsQueryServiceProvider, ApiConfigService, - ElasticService, ], }).compile(); }); diff --git a/src/modules/farm/specs/farm.compute.service.spec.ts b/src/modules/farm/specs/farm.compute.service.spec.ts index 6364563d0..7db6dccf4 100644 --- a/src/modules/farm/specs/farm.compute.service.spec.ts +++ b/src/modules/farm/specs/farm.compute.service.spec.ts @@ -21,7 +21,7 @@ import { ApiConfigService } from 'src/helpers/api.config.service'; import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { AnalyticsQueryServiceProvider } from 'src/services/analytics/mocks/analytics.query.service.mock'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('FarmService', () => { let module: TestingModule; @@ -34,6 +34,7 @@ describe('FarmService', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ MXApiServiceProvider, @@ -51,7 +52,6 @@ describe('FarmService', () => { FarmServiceV1_2, ApiConfigService, AnalyticsQueryServiceProvider, - ElasticService, ], }).compile(); }); diff --git a/src/modules/farm/specs/farm.service.spec.ts b/src/modules/farm/specs/farm.service.spec.ts index d4db6dd16..2f20f6365 100644 --- a/src/modules/farm/specs/farm.service.spec.ts +++ b/src/modules/farm/specs/farm.service.spec.ts @@ -40,7 +40,7 @@ import { ApiConfigService } from 'src/helpers/api.config.service'; import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { AnalyticsQueryServiceProvider } from 'src/services/analytics/mocks/analytics.query.service.mock'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('FarmService', () => { let module: TestingModule; @@ -53,6 +53,7 @@ describe('FarmService', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ FarmFactoryService, @@ -98,7 +99,6 @@ describe('FarmService', () => { MXDataApiServiceProvider, AnalyticsQueryServiceProvider, ApiConfigService, - ElasticService, ], }).compile(); }); diff --git a/src/modules/farm/specs/farm.transactions.service.spec.ts b/src/modules/farm/specs/farm.transactions.service.spec.ts index 5cfc8e542..cb0d72750 100644 --- a/src/modules/farm/specs/farm.transactions.service.spec.ts +++ b/src/modules/farm/specs/farm.transactions.service.spec.ts @@ -21,7 +21,7 @@ import { WinstonModule } from 'nest-winston'; import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { AnalyticsQueryServiceProvider } from 'src/services/analytics/mocks/analytics.query.service.mock'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('FarmService', () => { let module: TestingModule; @@ -34,6 +34,7 @@ describe('FarmService', () => { transports: [new winston.transports.Console({})], }), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ ApiConfigService, @@ -52,7 +53,6 @@ describe('FarmService', () => { MXDataApiServiceProvider, AnalyticsQueryServiceProvider, ApiConfigService, - ElasticService, ], }).compile(); }); diff --git a/src/modules/farm/specs/farm.v1.2.compute.service.spec.ts b/src/modules/farm/specs/farm.v1.2.compute.service.spec.ts index 149bced41..d5f3de3c7 100644 --- a/src/modules/farm/specs/farm.v1.2.compute.service.spec.ts +++ b/src/modules/farm/specs/farm.v1.2.compute.service.spec.ts @@ -19,7 +19,7 @@ import { ApiConfigService } from 'src/helpers/api.config.service'; import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { AnalyticsQueryServiceProvider } from 'src/services/analytics/mocks/analytics.query.service.mock'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('FarmService', () => { let module: TestingModule; @@ -32,6 +32,7 @@ describe('FarmService', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ FarmAbiServiceProviderV1_2, @@ -49,7 +50,6 @@ describe('FarmService', () => { MXDataApiServiceProvider, AnalyticsQueryServiceProvider, ApiConfigService, - ElasticService, ], }).compile(); }); diff --git a/src/modules/farm/specs/farm.v1.3.compute.service.spec.ts b/src/modules/farm/specs/farm.v1.3.compute.service.spec.ts index d979b82d7..1462a0857 100644 --- a/src/modules/farm/specs/farm.v1.3.compute.service.spec.ts +++ b/src/modules/farm/specs/farm.v1.3.compute.service.spec.ts @@ -19,7 +19,7 @@ import { ApiConfigService } from 'src/helpers/api.config.service'; import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { AnalyticsQueryServiceProvider } from 'src/services/analytics/mocks/analytics.query.service.mock'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('FarmService', () => { let module: TestingModule; @@ -32,6 +32,7 @@ describe('FarmService', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ FarmAbiServiceProviderV1_3, @@ -49,7 +50,6 @@ describe('FarmService', () => { MXDataApiServiceProvider, AnalyticsQueryServiceProvider, ApiConfigService, - ElasticService, ], }).compile(); }); diff --git a/src/modules/farm/specs/farm.v2.compute.service.spec.ts b/src/modules/farm/specs/farm.v2.compute.service.spec.ts index 77020c9a2..8c9d0c56d 100644 --- a/src/modules/farm/specs/farm.v2.compute.service.spec.ts +++ b/src/modules/farm/specs/farm.v2.compute.service.spec.ts @@ -24,7 +24,7 @@ import { ApiConfigService } from 'src/helpers/api.config.service'; import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { AnalyticsQueryServiceProvider } from 'src/services/analytics/mocks/analytics.query.service.mock'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('FarmServiceV2', () => { let module: TestingModule; @@ -37,6 +37,7 @@ describe('FarmServiceV2', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ MXApiServiceProvider, @@ -59,7 +60,6 @@ describe('FarmServiceV2', () => { FarmServiceV2, AnalyticsQueryServiceProvider, ApiConfigService, - ElasticService, ], }).compile(); }); diff --git a/src/modules/fees-collector/specs/fees-collector.service.spec.ts b/src/modules/fees-collector/specs/fees-collector.service.spec.ts index d4736fcde..24bb6ca2a 100644 --- a/src/modules/fees-collector/specs/fees-collector.service.spec.ts +++ b/src/modules/fees-collector/specs/fees-collector.service.spec.ts @@ -29,7 +29,7 @@ import { ApiConfigService } from 'src/helpers/api.config.service'; import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { AnalyticsQueryServiceProvider } from 'src/services/analytics/mocks/analytics.query.service.mock'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('FeesCollectorService', () => { let module: TestingModule; @@ -43,6 +43,7 @@ describe('FeesCollectorService', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ FeesCollectorService, @@ -69,7 +70,6 @@ describe('FeesCollectorService', () => { }, AnalyticsQueryServiceProvider, ApiConfigService, - ElasticService, ], }).compile(); }); diff --git a/src/modules/fees-collector/specs/fees.collector.compute.service.spec.ts b/src/modules/fees-collector/specs/fees.collector.compute.service.spec.ts index 40ffad87b..0b666bc2b 100644 --- a/src/modules/fees-collector/specs/fees.collector.compute.service.spec.ts +++ b/src/modules/fees-collector/specs/fees.collector.compute.service.spec.ts @@ -33,7 +33,7 @@ import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { AnalyticsQueryServiceProvider } from 'src/services/analytics/mocks/analytics.query.service.mock'; import { MXApiServiceProvider } from 'src/services/multiversx-communication/mx.api.service.mock'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('FeesCollectorComputeService', () => { let module: TestingModule; @@ -46,6 +46,7 @@ describe('FeesCollectorComputeService', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ FeesCollectorComputeService, @@ -73,7 +74,6 @@ describe('FeesCollectorComputeService', () => { AnalyticsQueryServiceProvider, ApiConfigService, MXApiServiceProvider, - ElasticService, ], }).compile(); }); diff --git a/src/modules/pair/services/pair.filtering.service.ts b/src/modules/pair/services/pair.filtering.service.ts index dfc57d5b7..5e9d862cf 100644 --- a/src/modules/pair/services/pair.filtering.service.ts +++ b/src/modules/pair/services/pair.filtering.service.ts @@ -7,12 +7,14 @@ import { PairsFilter, } from 'src/modules/router/models/filter.args'; import BigNumber from 'bignumber.js'; +import { PairService } from './pair.service'; @Injectable() export class PairFilteringService { constructor( private readonly pairAbi: PairAbiService, private readonly pairCompute: PairComputeService, + private readonly pairService: PairService, ) {} async pairsByIssuedLpToken( @@ -82,6 +84,50 @@ export class PairFilteringService { return await Promise.resolve(pairsMetadata); } + async pairsByWildcardToken( + pairFilter: PairsFilter, + pairsMetadata: PairMetadata[], + ): Promise { + if ( + !pairFilter.searchToken || + pairFilter.searchToken.trim().length < 3 + ) { + return pairsMetadata; + } + + const searchTerm = pairFilter.searchToken.toUpperCase().trim(); + + const pairsFirstToken = await Promise.all( + pairsMetadata.map((pairMetadata) => + this.pairService.getFirstToken(pairMetadata.address), + ), + ); + const pairsSecondToken = await Promise.all( + pairsMetadata.map((pairMetadata) => + this.pairService.getSecondToken(pairMetadata.address), + ), + ); + + const filteredPairs: PairMetadata[] = []; + for (const [index, pair] of pairsMetadata.entries()) { + const firstToken = pairsFirstToken[index]; + const secondToken = pairsSecondToken[index]; + + if ( + firstToken.name.toUpperCase().includes(searchTerm) || + firstToken.identifier.toUpperCase().includes(searchTerm) || + firstToken.ticker.toUpperCase().includes(searchTerm) || + secondToken.name.toUpperCase().includes(searchTerm) || + secondToken.identifier.toUpperCase().includes(searchTerm) || + secondToken.ticker.toUpperCase().includes(searchTerm) + ) { + filteredPairs.push(pair); + } + } + + return filteredPairs; + } + async pairsByState( pairFilter: PairFilterArgs | PairsFilter, pairsMetadata: PairMetadata[], diff --git a/src/modules/pair/services/pair.metadata.builder.ts b/src/modules/pair/services/pair.metadata.builder.ts index e08ab4b77..48175a05c 100644 --- a/src/modules/pair/services/pair.metadata.builder.ts +++ b/src/modules/pair/services/pair.metadata.builder.ts @@ -52,6 +52,14 @@ export class PairsMetadataBuilder { } async filterByTokens(): Promise { + if (this.filters.searchToken) { + this.pairsMetadata = + await this.filteringService.pairsByWildcardToken( + this.filters, + this.pairsMetadata, + ); + } + this.pairsMetadata = await this.filteringService.pairsByTokens( this.filters, this.pairsMetadata, diff --git a/src/modules/pair/specs/pair.compute.service.spec.ts b/src/modules/pair/specs/pair.compute.service.spec.ts index 89248bb13..a445eecb9 100644 --- a/src/modules/pair/specs/pair.compute.service.spec.ts +++ b/src/modules/pair/specs/pair.compute.service.spec.ts @@ -27,6 +27,7 @@ import { ElasticService } from 'src/helpers/elastic.service'; import { RemoteConfigGetterServiceProvider } from 'src/modules/remote-config/mocks/remote-config.getter.mock'; import { StakingProxyAbiServiceProvider } from 'src/modules/staking-proxy/mocks/staking.proxy.abi.service.mock'; import { FarmAbiServiceProviderV2 } from 'src/modules/farm/mocks/farm.v2.abi.service.mock'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('PairService', () => { let module: TestingModule; @@ -39,6 +40,7 @@ describe('PairService', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ PairComputeService, diff --git a/src/modules/router/models/filter.args.ts b/src/modules/router/models/filter.args.ts index f3b207382..729ff2084 100644 --- a/src/modules/router/models/filter.args.ts +++ b/src/modules/router/models/filter.args.ts @@ -57,6 +57,8 @@ export class PairsFilter { hasDualFarms: boolean; @Field({ nullable: true }) minDeployedAt: number; + @Field({ nullable: true }) + searchToken: string; } @InputType() diff --git a/src/modules/router/router.module.ts b/src/modules/router/router.module.ts index 4a5f8129d..8453dd104 100644 --- a/src/modules/router/router.module.ts +++ b/src/modules/router/router.module.ts @@ -11,10 +11,10 @@ import { CommonAppModule } from 'src/common.app.module'; import { ContextModule } from 'src/services/context/context.module'; import { WrappingModule } from '../wrapping/wrap.module'; import { RemoteConfigModule } from '../remote-config/remote-config.module'; -import { MetricsService } from 'src/endpoints/metrics/metrics.service'; import { ElasticService } from 'src/helpers/elastic.service'; import { SwapEnableConfigResolver } from './swap.enable.config.resolver'; import { SimpleLockModule } from '../simple-lock/simple.lock.module'; +import { ESTransactionsService } from 'src/services/elastic-search/services/es.transactions.service'; @Module({ imports: [ @@ -32,7 +32,7 @@ import { SimpleLockModule } from '../simple-lock/simple.lock.module'; RouterSetterService, RouterComputeService, RouterTransactionService, - MetricsService, + ESTransactionsService, ElasticService, SwapEnableConfigResolver, RouterResolver, diff --git a/src/modules/router/services/router.compute.service.ts b/src/modules/router/services/router.compute.service.ts index 98283e418..2a71b431f 100644 --- a/src/modules/router/services/router.compute.service.ts +++ b/src/modules/router/services/router.compute.service.ts @@ -1,11 +1,11 @@ import { forwardRef, Inject, Injectable } from '@nestjs/common'; import BigNumber from 'bignumber.js'; -import { MetricsService } from 'src/endpoints/metrics/metrics.service'; import { PairComputeService } from '../../pair/services/pair.compute.service'; import { RouterAbiService } from './router.abi.service'; import { ErrorLoggerAsync } from '@multiversx/sdk-nestjs-common'; import { GetOrSetCache } from 'src/helpers/decorators/caching.decorator'; import { Constants } from '@multiversx/sdk-nestjs-common'; +import { ESTransactionsService } from 'src/services/elastic-search/services/es.transactions.service'; @Injectable() export class RouterComputeService { @@ -13,7 +13,7 @@ export class RouterComputeService { private readonly routerAbi: RouterAbiService, @Inject(forwardRef(() => PairComputeService)) private readonly pairCompute: PairComputeService, - private readonly metrics: MetricsService, + private readonly metrics: ESTransactionsService, ) {} @ErrorLoggerAsync() diff --git a/src/modules/router/specs/router.service.spec.ts b/src/modules/router/specs/router.service.spec.ts index 986962261..34d7e5a23 100644 --- a/src/modules/router/specs/router.service.spec.ts +++ b/src/modules/router/specs/router.service.spec.ts @@ -12,6 +12,11 @@ import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { PairComputeServiceProvider } from 'src/modules/pair/mocks/pair.compute.service.mock'; import { PairFilteringService } from 'src/modules/pair/services/pair.filtering.service'; +import { PairService } from 'src/modules/pair/services/pair.service'; +import { WrapAbiServiceProvider } from 'src/modules/wrapping/mocks/wrap.abi.service.mock'; +import { TokenServiceProvider } from 'src/modules/tokens/mocks/token.service.mock'; +import { ContextGetterServiceProvider } from 'src/services/context/mocks/context.getter.service.mock'; +import { MXApiServiceProvider } from 'src/services/multiversx-communication/mx.api.service.mock'; describe('RouterService', () => { let module: TestingModule; @@ -32,6 +37,11 @@ describe('RouterService', () => { RouterService, ApiConfigService, PairFilteringService, + PairService, + WrapAbiServiceProvider, + TokenServiceProvider, + ContextGetterServiceProvider, + MXApiServiceProvider, ], }).compile(); }); diff --git a/src/modules/staking-proxy/specs/staking.proxy.transaction.service.spec.ts b/src/modules/staking-proxy/specs/staking.proxy.transaction.service.spec.ts index 4d9f37ed4..4fca6a656 100644 --- a/src/modules/staking-proxy/specs/staking.proxy.transaction.service.spec.ts +++ b/src/modules/staking-proxy/specs/staking.proxy.transaction.service.spec.ts @@ -42,7 +42,7 @@ import { ApiConfigService } from 'src/helpers/api.config.service'; import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { AnalyticsQueryServiceProvider } from 'src/services/analytics/mocks/analytics.query.service.mock'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('StakingProxyTransactionService', () => { let module: TestingModule; @@ -55,6 +55,7 @@ describe('StakingProxyTransactionService', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ StakingProxyTransactionService, @@ -96,7 +97,6 @@ describe('StakingProxyTransactionService', () => { RemoteConfigGetterServiceProvider, AnalyticsQueryServiceProvider, ApiConfigService, - ElasticService, ], }).compile(); }); diff --git a/src/modules/tokens/models/esdtToken.model.ts b/src/modules/tokens/models/esdtToken.model.ts index f5fc2fdbf..9fe2f6483 100644 --- a/src/modules/tokens/models/esdtToken.model.ts +++ b/src/modules/tokens/models/esdtToken.model.ts @@ -27,6 +27,8 @@ export class EsdtToken implements IEsdtToken { volumeUSD24h?: string; previous24hVolume?: string; liquidityUSD?: string; + swapCount24h?: number; + previous24hSwapCount?: number; supply?: string; circulatingSupply?: string; assets?: AssetsModel; diff --git a/src/modules/tokens/models/tokens.filter.args.ts b/src/modules/tokens/models/tokens.filter.args.ts index 6f7c57697..9f3b28b68 100644 --- a/src/modules/tokens/models/tokens.filter.args.ts +++ b/src/modules/tokens/models/tokens.filter.args.ts @@ -8,6 +8,7 @@ export enum TokensSortableFields { PREVIOUS_7D_PRICE = 'previous_7d_price', PREVIOUS_24H_VOLUME = 'previous_24h_volume', LIQUIDITY = 'liquidity', + TRADES_COUNT = 'trades_count', } registerEnumType(TokensSortableFields, { name: 'TokensSortableFields' }); @@ -30,6 +31,8 @@ export class TokensFilter { type?: string; @Field(() => Boolean, { defaultValue: false }) enabledSwaps: boolean; + @Field({ nullable: true }) + searchToken?: string; } @InputType() diff --git a/src/modules/tokens/services/token.compute.service.ts b/src/modules/tokens/services/token.compute.service.ts index 644102c2b..91ae1caa8 100644 --- a/src/modules/tokens/services/token.compute.service.ts +++ b/src/modules/tokens/services/token.compute.service.ts @@ -17,12 +17,27 @@ import { ErrorLoggerAsync } from '@multiversx/sdk-nestjs-common'; import { GetOrSetCache } from 'src/helpers/decorators/caching.decorator'; import { CacheTtlInfo } from 'src/services/caching/cache.ttl.info'; import { AnalyticsQueryService } from 'src/services/analytics/services/analytics.query.service'; -import { ElasticQuery, QueryType } from '@multiversx/sdk-nestjs-elastic'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { + ElasticQuery, + ElasticService, + QueryType, +} from '@multiversx/sdk-nestjs-elastic'; import moment from 'moment'; +import { ESLogsService } from 'src/services/elastic-search/services/es.logs.service'; +import { PendingExecutor } from 'src/utils/pending.executor'; +import { CacheService } from '@multiversx/sdk-nestjs-cache'; @Injectable() export class TokenComputeService implements ITokenComputeService { + private swapCountExecutor: PendingExecutor< + null, + { tokenID: string; swapsCount: number }[] + >; + private swapCountPrevious24hExecutor: PendingExecutor< + null, + { tokenID: string; swapsCount: number }[] + >; + constructor( private readonly pairAbi: PairAbiService, @Inject(forwardRef(() => PairComputeService)) @@ -33,7 +48,16 @@ export class TokenComputeService implements ITokenComputeService { private readonly dataApi: MXDataApiService, private readonly analyticsQuery: AnalyticsQueryService, private readonly elasticService: ElasticService, - ) {} + private readonly logsElasticService: ESLogsService, + private readonly cachingService: CacheService, + ) { + this.swapCountExecutor = new PendingExecutor( + async () => await this.allTokensSwapsCount(), + ); + this.swapCountPrevious24hExecutor = new PendingExecutor( + async () => await this.allTokensSwapsCountPrevious24h(), + ); + } async getEgldPriceInUSD(): Promise { return await this.pairCompute.firstTokenPrice(scAddress.WEGLD_USDC); @@ -405,10 +429,116 @@ export class TokenComputeService implements ITokenComputeService { ); if (tokens.length > 0) { - const createdAtTimestamp = tokens[0]._source.timestamp; + const createdAtTimestamp = tokens[0].timestamp; return createdAtTimestamp.toString(); } return undefined; } + + @ErrorLoggerAsync({ + logArgs: true, + }) + async tokenSwapCount(tokenID: string): Promise { + const allSwapsCount = await this.swapCountExecutor.execute(null); + + const currentTokenSwapCount = allSwapsCount.find( + (elem) => elem.tokenID === tokenID, + ); + + return currentTokenSwapCount ? currentTokenSwapCount.swapsCount : 0; + } + + @ErrorLoggerAsync({ + logArgs: true, + }) + async tokenPrevious24hSwapCount(tokenID: string): Promise { + const allSwapsCount = await this.swapCountPrevious24hExecutor.execute( + null, + ); + + const currentTokenSwapCount = allSwapsCount.find( + (elem) => elem.tokenID === tokenID, + ); + + return currentTokenSwapCount ? currentTokenSwapCount.swapsCount : 0; + } + + @ErrorLoggerAsync({ + logArgs: true, + }) + async allTokensSwapsCount(): Promise< + { tokenID: string; swapsCount: number }[] + > { + const cacheKey = 'token.allTokensSwapsCount'; + const cachedValue = await this.cachingService.get< + { tokenID: string; swapsCount: number }[] + >(cacheKey); + if (cachedValue && cachedValue !== undefined) { + return cachedValue; + } + + const end = moment.utc().unix(); + const start = moment.unix(end).subtract(1, 'day').unix(); + + const swapsCount = await this.computeAllTokensSwapsCount(start, end); + await this.cachingService.set( + cacheKey, + swapsCount, + CacheTtlInfo.Token.remoteTtl, + CacheTtlInfo.Token.localTtl, + ); + return swapsCount; + } + + @ErrorLoggerAsync({ + logArgs: true, + }) + async allTokensSwapsCountPrevious24h(): Promise< + { tokenID: string; swapsCount: number }[] + > { + const cacheKey = 'token.allTokensSwapsCountPrevious24h'; + const cachedValue = await this.cachingService.get< + { tokenID: string; swapsCount: number }[] + >(cacheKey); + if (cachedValue && cachedValue !== undefined) { + return cachedValue; + } + + const end = moment.utc().subtract(1, 'day').unix(); + const start = moment.utc().subtract(2, 'days').unix(); + + const swapsCount = await this.computeAllTokensSwapsCount(start, end); + await this.cachingService.set( + cacheKey, + swapsCount, + CacheTtlInfo.Token.remoteTtl, + CacheTtlInfo.Token.localTtl, + ); + return swapsCount; + } + + async computeAllTokensSwapsCount( + start: number, + end: number, + ): Promise<{ tokenID: string; swapsCount: number }[]> { + const pairAddresses = await this.routerAbi.pairsAddress(); + + const allSwapsCount = await this.logsElasticService.getTokenSwapsCount( + start, + end, + pairAddresses, + ); + + const result = []; + + for (const entry of allSwapsCount.entries()) { + result.push({ + tokenID: entry[0], + swapsCount: entry[1], + }); + } + + return result; + } } diff --git a/src/modules/tokens/services/token.filtering.service.ts b/src/modules/tokens/services/token.filtering.service.ts index 6ca532415..b30917b29 100644 --- a/src/modules/tokens/services/token.filtering.service.ts +++ b/src/modules/tokens/services/token.filtering.service.ts @@ -1,6 +1,7 @@ import { Inject, Injectable, forwardRef } from '@nestjs/common'; import { TokenService } from './token.service'; import { TokensFilter } from '../models/tokens.filter.args'; +import { EsdtToken } from '../models/esdtToken.model'; @Injectable() export class TokenFilteringService { @@ -43,4 +44,31 @@ export class TokenFilteringService { } return filteredIDs; } + + async tokensBySearchTerm( + tokensFilter: TokensFilter, + tokens: EsdtToken[], + ): Promise { + if ( + !tokensFilter.searchToken || + tokensFilter.searchToken.trim().length < 3 + ) { + return tokens; + } + + const searchTerm = tokensFilter.searchToken.toUpperCase().trim(); + + const filteredTokens: EsdtToken[] = []; + for (const token of tokens) { + if ( + token.name.toUpperCase().includes(searchTerm) || + token.identifier.toUpperCase().includes(searchTerm) || + token.ticker.toUpperCase().includes(searchTerm) + ) { + filteredTokens.push(token); + } + } + + return filteredTokens; + } } diff --git a/src/modules/tokens/services/token.service.ts b/src/modules/tokens/services/token.service.ts index 9913735b8..814c0a637 100644 --- a/src/modules/tokens/services/token.service.ts +++ b/src/modules/tokens/services/token.service.ts @@ -76,14 +76,19 @@ export class TokenService { tokenIDs, ); + let tokens = await Promise.all( + tokenIDs.map((tokenID) => this.getTokenMetadata(tokenID)), + ); + + tokens = await this.tokenFilteringService.tokensBySearchTerm( + filters, + tokens, + ); + if (sorting) { tokenIDs = await this.sortTokens(tokenIDs, sorting); } - const tokens = await Promise.all( - tokenIDs.map((tokenID) => this.getTokenMetadata(tokenID)), - ); - return new CollectionType({ count: tokens.length, items: tokens.slice( @@ -239,6 +244,13 @@ export class TokenService { ), ); break; + case TokensSortableFields.TRADES_COUNT: + sortFieldData = await Promise.all( + tokenIDs.map((tokenID) => + this.tokenCompute.tokenSwapCount(tokenID), + ), + ); + break; default: break; diff --git a/src/modules/tokens/services/token.setter.service.ts b/src/modules/tokens/services/token.setter.service.ts index 37df8082d..00f90a436 100644 --- a/src/modules/tokens/services/token.setter.service.ts +++ b/src/modules/tokens/services/token.setter.service.ts @@ -106,6 +106,28 @@ export class TokenSetterService extends GenericSetterService { ); } + async setAllTokensSwapsCount( + value: { tokenID: string; swapsCount: number }[], + ): Promise { + return await this.setData( + 'token.allTokensSwapsCount', + value, + CacheTtlInfo.Token.remoteTtl, + CacheTtlInfo.Token.localTtl, + ); + } + + async setAllTokensPrevious24hSwapsCount( + value: { tokenID: string; swapsCount: number }[], + ): Promise { + return await this.setData( + 'token.allTokensSwapsCountPrevious24h', + value, + CacheTtlInfo.Token.remoteTtl, + CacheTtlInfo.Token.localTtl, + ); + } + private getTokenCacheKey(tokenID: string, ...args: any): string { return generateCacheKeyFromParams('token', tokenID, args); } diff --git a/src/modules/tokens/specs/token.compute.service.spec.ts b/src/modules/tokens/specs/token.compute.service.spec.ts index f88835f4c..9e7d9875f 100644 --- a/src/modules/tokens/specs/token.compute.service.spec.ts +++ b/src/modules/tokens/specs/token.compute.service.spec.ts @@ -16,7 +16,7 @@ import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { AnalyticsQueryServiceProvider } from 'src/services/analytics/mocks/analytics.query.service.mock'; import { MXApiServiceProvider } from 'src/services/multiversx-communication/mx.api.service.mock'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('TokenComputeService', () => { let module: TestingModule; @@ -29,6 +29,7 @@ describe('TokenComputeService', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ PairAbiServiceProvider, @@ -43,7 +44,6 @@ describe('TokenComputeService', () => { ApiConfigService, AnalyticsQueryServiceProvider, MXApiServiceProvider, - ElasticService, ], }).compile(); }); diff --git a/src/modules/tokens/token.module.ts b/src/modules/tokens/token.module.ts index d0a3cc491..293d362b0 100644 --- a/src/modules/tokens/token.module.ts +++ b/src/modules/tokens/token.module.ts @@ -15,6 +15,8 @@ import { NftTokenResolver } from './nftToken.resolver'; import { AnalyticsModule } from 'src/services/analytics/analytics.module'; import { ElasticService } from 'src/helpers/elastic.service'; import { TokenFilteringService } from './services/token.filtering.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; +import { ESLogsService } from 'src/services/elastic-search/services/es.logs.service'; @Module({ imports: [ @@ -26,6 +28,7 @@ import { TokenFilteringService } from './services/token.filtering.service'; { name: EsdtTokenDbModel.name, schema: EsdtTokenSchema }, ]), AnalyticsModule, + ElasticSearchModule, ], providers: [ TokenService, @@ -38,6 +41,7 @@ import { TokenFilteringService } from './services/token.filtering.service'; NftTokenResolver, ElasticService, TokenFilteringService, + ESLogsService, ], exports: [ TokenRepositoryService, diff --git a/src/modules/tokens/token.resolver.ts b/src/modules/tokens/token.resolver.ts index 80724d913..026f26e0a 100644 --- a/src/modules/tokens/token.resolver.ts +++ b/src/modules/tokens/token.resolver.ts @@ -108,6 +108,20 @@ export class TokensResolver extends GenericResolver { ); } + @ResolveField(() => Number, { nullable: true }) + async swapCount24h(@Parent() parent: EsdtToken): Promise { + return await this.genericFieldResolver(() => + this.tokenCompute.tokenSwapCount(parent.identifier), + ); + } + + @ResolveField(() => Number, { nullable: true }) + async previous24hSwapCount(@Parent() parent: EsdtToken): Promise { + return await this.genericFieldResolver(() => + this.tokenCompute.tokenPrevious24hSwapCount(parent.identifier), + ); + } + @Query(() => [EsdtToken]) async tokens(@Args() filters: TokensFiltersArgs): Promise { try { diff --git a/src/modules/user/specs/user.energy.compute.service.spec.ts b/src/modules/user/specs/user.energy.compute.service.spec.ts index 8619e7811..8bb9f48a7 100644 --- a/src/modules/user/specs/user.energy.compute.service.spec.ts +++ b/src/modules/user/specs/user.energy.compute.service.spec.ts @@ -66,7 +66,7 @@ import { ApiConfigService } from 'src/helpers/api.config.service'; import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { AnalyticsQueryServiceProvider } from 'src/services/analytics/mocks/analytics.query.service.mock'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('UserEnergyComputeService', () => { let module: TestingModule; @@ -133,7 +133,6 @@ describe('UserEnergyComputeService', () => { AbiLockedAssetServiceProvider, AnalyticsQueryServiceProvider, ApiConfigService, - ElasticService, ], imports: [ WinstonModule.forRoot({ @@ -141,6 +140,7 @@ describe('UserEnergyComputeService', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], }).compile(); }); diff --git a/src/private.app.module.ts b/src/private.app.module.ts index b5fe54fcd..d41588c36 100644 --- a/src/private.app.module.ts +++ b/src/private.app.module.ts @@ -1,7 +1,6 @@ import { Module } from '@nestjs/common'; import { CommonAppModule } from './common.app.module'; import { MetricsController } from './endpoints/metrics/metrics.controller'; -import { MetricsService } from './endpoints/metrics/metrics.service'; import { ElasticService } from './helpers/elastic.service'; import { PairModule } from './modules/pair/pair.module'; import { RemoteConfigController } from './modules/remote-config/remote-config.controller'; @@ -9,6 +8,7 @@ import { RemoteConfigModule } from './modules/remote-config/remote-config.module import { TokenController } from './modules/tokens/token.controller'; import { TokenModule } from './modules/tokens/token.module'; import { DynamicModuleUtils } from './utils/dynamic.module.utils'; +import { ESTransactionsService } from './services/elastic-search/services/es.transactions.service'; @Module({ imports: [ @@ -19,6 +19,6 @@ import { DynamicModuleUtils } from './utils/dynamic.module.utils'; DynamicModuleUtils.getCacheModule(), ], controllers: [MetricsController, TokenController, RemoteConfigController], - providers: [MetricsService, ElasticService], + providers: [ElasticService, ESTransactionsService], }) export class PrivateAppModule {} diff --git a/src/services/crons/tokens.cache.warmer.service.ts b/src/services/crons/tokens.cache.warmer.service.ts index 319b1528b..1dd640bb7 100644 --- a/src/services/crons/tokens.cache.warmer.service.ts +++ b/src/services/crons/tokens.cache.warmer.service.ts @@ -9,6 +9,7 @@ import { TokenService } from 'src/modules/tokens/services/token.service'; import { PerformanceProfiler } from 'src/utils/performance.profiler'; import { TokenComputeService } from 'src/modules/tokens/services/token.compute.service'; import { TokenSetterService } from 'src/modules/tokens/services/token.setter.service'; +import moment from 'moment'; @Injectable() export class TokensCacheWarmerService { @@ -67,6 +68,50 @@ export class TokensCacheWarmerService { this.logger.info(`Finish refresh tokens data in ${profiler.duration}`); } + @Cron(CronExpression.EVERY_MINUTE) + @Lock({ name: 'cacheTokensSwapsCount', verbose: true }) + async cacheTokensSwapsCount(): Promise { + this.logger.info('Start refresh cached tokens swaps count', { + context: 'CacheTokens', + }); + + const profiler = new PerformanceProfiler(); + + const nowTimestamp = moment.utc().unix(); + const oneDayAgoTimestamp = moment + .unix(nowTimestamp) + .subtract(1, 'day') + .unix(); + const twoDaysyAgoTimestamp = moment + .unix(nowTimestamp) + .subtract(2, 'days') + .unix(); + + const [swapsCount, previous24hSwapsCount] = await Promise.all([ + this.tokenComputeService.computeAllTokensSwapsCount( + oneDayAgoTimestamp, + nowTimestamp, + ), + this.tokenComputeService.computeAllTokensSwapsCount( + twoDaysyAgoTimestamp, + oneDayAgoTimestamp, + ), + ]); + + const cachedKeys = await Promise.all([ + this.tokenSetterService.setAllTokensSwapsCount(swapsCount), + this.tokenSetterService.setAllTokensPrevious24hSwapsCount( + previous24hSwapsCount, + ), + ]); + await this.deleteCacheKeys(cachedKeys); + + profiler.stop(); + this.logger.info( + `Finish refresh tokens swaps count data in ${profiler.duration}`, + ); + } + private async deleteCacheKeys(invalidatedKeys: string[]) { await this.pubSub.publish('deleteCacheKeys', invalidatedKeys); } diff --git a/src/services/elastic-search/elastic.search.module.ts b/src/services/elastic-search/elastic.search.module.ts new file mode 100644 index 000000000..7378c1843 --- /dev/null +++ b/src/services/elastic-search/elastic.search.module.ts @@ -0,0 +1,16 @@ +import { Module } from '@nestjs/common'; +import { ESTransactionsService } from './services/es.transactions.service'; +import { ESLogsService } from './services/es.logs.service'; +import { CommonAppModule } from 'src/common.app.module'; +import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; + +@Module({ + imports: [ + CommonAppModule, + DynamicModuleUtils.getApiModule(), + DynamicModuleUtils.getElasticModule(), + ], + providers: [ESTransactionsService, ESLogsService], + exports: [ESTransactionsService, ESLogsService], +}) +export class ElasticSearchModule {} diff --git a/src/services/elastic-search/services/es.logs.service.ts b/src/services/elastic-search/services/es.logs.service.ts new file mode 100644 index 000000000..b4a0b29bf --- /dev/null +++ b/src/services/elastic-search/services/es.logs.service.ts @@ -0,0 +1,143 @@ +import { SwapEvent } from '@multiversx/sdk-exchange'; +import { + ElasticQuery, + ElasticService, + ElasticSortOrder, + QueryType, +} from '@multiversx/sdk-nestjs-elastic'; +import { Inject, Injectable } from '@nestjs/common'; +import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; +import { Logger } from 'winston'; + +@Injectable() +export class ESLogsService { + constructor( + private readonly elasticService: ElasticService, + @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, + ) {} + + async getTokenSwapsCount( + startTimestamp: number, + endTimestamp: number, + pairAddresses: string[], + ): Promise> { + const swapEvents: SwapEvent[] = []; + const tokensSwapCountMap: Map = new Map(); + + const processLogsAction = async (items: any[]): Promise => { + for (const transactionLogs of items) { + swapEvents.push( + ...this.processSwapEvents( + transactionLogs.events, + pairAddresses, + ), + ); + } + }; + + await Promise.all([ + this.getTransactionsLogs( + 'swapTokensFixedInput', + startTimestamp, + endTimestamp, + processLogsAction, + ), + this.getTransactionsLogs( + 'swapTokensFixedOutput', + startTimestamp, + endTimestamp, + processLogsAction, + ), + ]); + + for (const swapEvent of swapEvents) { + const eventTopics = swapEvent.getTopics(); + + if (tokensSwapCountMap.has(eventTopics.firstTokenID)) { + const currentCount = tokensSwapCountMap.get( + eventTopics.firstTokenID, + ); + tokensSwapCountMap.set( + eventTopics.firstTokenID, + currentCount + 1, + ); + } else { + tokensSwapCountMap.set(eventTopics.firstTokenID, 1); + } + + if (tokensSwapCountMap.has(eventTopics.secondTokenID)) { + const currentCount = tokensSwapCountMap.get( + eventTopics.secondTokenID, + ); + tokensSwapCountMap.set( + eventTopics.secondTokenID, + currentCount + 1, + ); + } else { + tokensSwapCountMap.set(eventTopics.secondTokenID, 1); + } + } + + return tokensSwapCountMap; + } + + private async getTransactionsLogs( + eventName: string, + startTimestamp: number, + endTimestamp: number, + action: (items: any[]) => Promise, + ): Promise { + const elasticQueryAdapter: ElasticQuery = new ElasticQuery(); + elasticQueryAdapter.condition.must = [ + QueryType.Nested('events', [ + QueryType.Match('events.identifier', eventName), + ]), + ]; + + elasticQueryAdapter.filter = [ + QueryType.Range( + 'timestamp', + { + key: 'gte', + value: startTimestamp, + }, + { + key: 'lte', + value: endTimestamp, + }, + ), + ]; + + elasticQueryAdapter.sort = [ + { name: 'timestamp', order: ElasticSortOrder.ascending }, + ]; + + await this.elasticService.getScrollableList( + 'logs', + '', + elasticQueryAdapter, + action, + ); + } + + private processSwapEvents( + events: any[], + pairAddresses: string[], + ): SwapEvent[] { + const esdtSwapEvents: SwapEvent[] = []; + + for (const event of events) { + if (!pairAddresses.includes(event.address)) { + continue; + } + if ( + event.identifier === 'swapTokensFixedInput' || + event.identifier === 'swapTokensFixedOutput' + ) { + esdtSwapEvents.push(new SwapEvent(event)); + } + } + + return esdtSwapEvents; + } +} diff --git a/src/endpoints/metrics/metrics.service.ts b/src/services/elastic-search/services/es.transactions.service.ts similarity index 95% rename from src/endpoints/metrics/metrics.service.ts rename to src/services/elastic-search/services/es.transactions.service.ts index 22290f039..a7f91f5cc 100644 --- a/src/endpoints/metrics/metrics.service.ts +++ b/src/services/elastic-search/services/es.transactions.service.ts @@ -1,12 +1,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; -import { QueryType } from '@multiversx/sdk-nestjs-elastic'; +import { ElasticService, QueryType } from '@multiversx/sdk-nestjs-elastic'; import { ElasticQuery } from '@multiversx/sdk-nestjs-elastic'; -import { ElasticService } from 'src/helpers/elastic.service'; @Injectable() -export class MetricsService { +export class ESTransactionsService { constructor( private readonly elasticService: ElasticService, @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, @@ -116,7 +115,7 @@ export class MetricsService { const uniqueUsersMap = new Map(); for (const transaction of transactions) { - const sender = transaction._source.sender; + const sender = transaction.sender; if (!uniqueUsersMap.has(sender)) { uniqueUsersMap.set(sender, 1); } else { diff --git a/src/submodules/weekly-rewards-splitting/specs/weekly-rewards-splitting.compute.service.spec.ts b/src/submodules/weekly-rewards-splitting/specs/weekly-rewards-splitting.compute.service.spec.ts index 2944ea266..3015cfc58 100644 --- a/src/submodules/weekly-rewards-splitting/specs/weekly-rewards-splitting.compute.service.spec.ts +++ b/src/submodules/weekly-rewards-splitting/specs/weekly-rewards-splitting.compute.service.spec.ts @@ -23,7 +23,7 @@ import winston from 'winston'; import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; import { AnalyticsQueryServiceProvider } from 'src/services/analytics/mocks/analytics.query.service.mock'; import { MXApiServiceProvider } from 'src/services/multiversx-communication/mx.api.service.mock'; -import { ElasticService } from 'src/helpers/elastic.service'; +import { ElasticSearchModule } from 'src/services/elastic-search/elastic.search.module'; describe('WeeklyRewardsSplittingComputeService', () => { let module: TestingModule; @@ -36,6 +36,7 @@ describe('WeeklyRewardsSplittingComputeService', () => { }), ConfigModule.forRoot({}), DynamicModuleUtils.getCacheModule(), + ElasticSearchModule, ], providers: [ WeeklyRewardsSplittingComputeService, @@ -53,7 +54,6 @@ describe('WeeklyRewardsSplittingComputeService', () => { AnalyticsQueryServiceProvider, ApiConfigService, MXApiServiceProvider, - ElasticService, ], }).compile(); }); diff --git a/src/utils/dynamic.module.utils.ts b/src/utils/dynamic.module.utils.ts index 7dc8d48bf..a1c74bf60 100644 --- a/src/utils/dynamic.module.utils.ts +++ b/src/utils/dynamic.module.utils.ts @@ -2,6 +2,11 @@ import { CacheModule, RedisCacheModuleOptions, } from '@multiversx/sdk-nestjs-cache'; +import { + ElasticModule, + ElasticModuleOptions, +} from '@multiversx/sdk-nestjs-elastic'; +import { ApiModule, ApiModuleOptions } from '@multiversx/sdk-nestjs-http'; import { DynamicModule } from '@nestjs/common'; import { CommonAppModule } from 'src/common.app.module'; import { mxConfig } from 'src/config'; @@ -25,4 +30,32 @@ export class DynamicModuleUtils { }, ); } + + static getElasticModule(): DynamicModule { + return ElasticModule.forRootAsync({ + imports: [CommonAppModule], + inject: [ApiConfigService], + useFactory: (configService: ApiConfigService) => + new ElasticModuleOptions({ + url: configService.getElasticSearchUrl(), + }), + }); + } + + static getApiModule(): DynamicModule { + return ApiModule.forRootAsync({ + imports: [CommonAppModule], + inject: [ApiConfigService], + useFactory: (configService: ApiConfigService) => + new ApiModuleOptions({ + axiosTimeout: + configService.getKeepAliveTimeoutDownstream() ?? 61000, + rateLimiterSecret: + configService.getRateLimiterSecret() ?? '', + serverTimeout: + configService.getKeepAliveTimeoutDownstream() ?? 60000, + useKeepAliveAgent: mxConfig.keepAlive, + }), + }); + } }