diff --git a/package.json b/package.json index ea5ff900b..31d3690a1 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "fs-extra": "^10.0.1", "inquirer": "^8.2.2", "lodash": "^4.17.21", + "murmurhash-js": "^1.0.0", "rimraf": "^3.0.2" }, "devDependencies": { @@ -53,7 +54,9 @@ "@types/inquirer": "^8.2.0", "@types/jest": "^27.4.1", "@types/lodash": "^4.14.180", + "@types/murmurhash-js": "^1.0.3", "@types/node": "16.11.7", + "@types/qs": "^6.9.7", "@typescript-eslint/eslint-plugin": "^5.16.0", "@typescript-eslint/parser": "^5.16.0", "axios": "^0.26.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 223635a77..d4464d5c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,7 +23,9 @@ specifiers: '@types/inquirer': ^8.2.0 '@types/jest': ^27.4.1 '@types/lodash': ^4.14.180 + '@types/murmurhash-js': ^1.0.3 '@types/node': 16.11.7 + '@types/qs': ^6.9.7 '@typescript-eslint/eslint-plugin': ^5.16.0 '@typescript-eslint/parser': ^5.16.0 axios: ^0.26.1 @@ -53,6 +55,7 @@ specifiers: jest: ^27.5.1 lodash: ^4.17.21 moment: ^2.29.2 + murmurhash-js: ^1.0.0 nodemon: ^2.0.15 prettier: ^2.6.0 qs: ^6.10.3 @@ -84,6 +87,7 @@ dependencies: fs-extra: 10.0.1 inquirer: 8.2.2 lodash: 4.17.21 + murmurhash-js: 1.0.0 rimraf: 3.0.2 devDependencies: @@ -107,7 +111,9 @@ devDependencies: '@types/inquirer': 8.2.0 '@types/jest': 27.4.1 '@types/lodash': 4.14.180 + '@types/murmurhash-js': 1.0.3 '@types/node': 16.11.7 + '@types/qs': 6.9.7 '@typescript-eslint/eslint-plugin': 5.16.0_h7wskcyrkgkbjjgh2usgrxll6u '@typescript-eslint/parser': 5.16.0_ynv3edxl3ah44xwgrna2g2yine axios: 0.26.1 @@ -1234,7 +1240,6 @@ packages: uuid: 8.3.2 transitivePeerDependencies: - debug - dev: true /@nestjs/config/1.2.1_6d336j5z3wdgfwg6g6i43w4msm: resolution: {integrity: sha512-EgaGTXvG4unD5lGWmdSrUFrkGpX32lQGE/8qS60EnL82sIZV7HT1ZL7ib5S86P1nB+DnFDbDhDqTaZ3mivTyOg==} @@ -1283,7 +1288,6 @@ packages: uuid: 8.3.2 transitivePeerDependencies: - encoding - dev: true /@nestjs/mapped-types/1.0.1_xluz7cqyskci5bcbv7rvfyu5ra: resolution: {integrity: sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==} @@ -1319,7 +1323,6 @@ packages: tslib: 2.3.1 transitivePeerDependencies: - supports-color - dev: false /@nestjs/schematics/8.0.8_ezuyfu3uj65g35wdjb6342atpm: resolution: {integrity: sha512-xIIb5YnMQN/OJQ68+MCapy2bXvTxSWgINoqQbyZWkLL/yTIuROvZCdtV850NPGyr7f7l93VBP0ZPitbFIexy3Q==} @@ -1393,7 +1396,6 @@ packages: node-fetch: 2.6.7 transitivePeerDependencies: - encoding - dev: true /@oclif/color/1.0.1: resolution: {integrity: sha512-qjYr+izgWdIVOroiBKqTzQgc1r5Wd9QB1J7yGM2EeelqhBARiiVLRZL45vhV4zdyTRdDkZS0EBzFwQap+nliLA==} @@ -1708,6 +1710,10 @@ packages: '@types/node': 16.11.33 dev: true + /@types/murmurhash-js/1.0.3: + resolution: {integrity: sha512-PxJwTlcFOBRPqv9pSoC3O1FpKN8GnM5hMJIkG6U3omH8b4GAh28fO1c+TMR4oxj0BG43/ICbrIK3KBfzad2heg==} + dev: true + /@types/node/12.20.50: resolution: {integrity: sha512-+9axpWx2b2JCVovr7Ilgt96uc6C1zBKOQMpGtRbWT9IoR/8ue32GGMfGA4woP8QyP2gBs6GQWEVM3tCybGCxDA==} dev: true @@ -2211,7 +2217,6 @@ packages: /append-field/1.0.0: resolution: {integrity: sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=} - dev: false /arg/4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -2306,7 +2311,6 @@ packages: /async/3.2.0: resolution: {integrity: sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==} - dev: true /asynckit/0.4.0: resolution: {integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k=} @@ -2336,7 +2340,6 @@ packages: follow-redirects: 1.14.9 transitivePeerDependencies: - debug - dev: true /babel-jest/27.5.1_@babel+core@7.17.9: resolution: {integrity: sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==} @@ -2656,7 +2659,6 @@ packages: dependencies: dicer: 0.2.5 readable-stream: 1.1.14 - dev: false /bytes/3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} @@ -2668,7 +2670,6 @@ packages: async: 3.2.0 lodash: 4.17.21 lru-cache: 6.0.0 - dev: true /cacheable-request/6.1.0: resolution: {integrity: sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==} @@ -2814,14 +2815,12 @@ packages: /class-transformer/0.5.1: resolution: {integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==} - dev: true /class-validator/0.13.2: resolution: {integrity: sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==} dependencies: libphonenumber-js: 1.9.50 validator: 13.7.0 - dev: true /clean-stack/3.0.1: resolution: {integrity: sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==} @@ -2977,7 +2976,6 @@ packages: inherits: 2.0.4 readable-stream: 2.3.7 typedarray: 0.0.6 - dev: false /configstore/5.0.1: resolution: {integrity: sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==} @@ -2993,7 +2991,6 @@ packages: /consola/2.15.3: resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} - dev: true /content-disposition/0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} @@ -3347,7 +3344,6 @@ packages: dependencies: readable-stream: 1.1.14 streamsearch: 0.1.2 - dev: false /diff-sequences/27.5.1: resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} @@ -3555,7 +3551,6 @@ packages: cpu: [x64] os: [android] requiresBuild: true - dev: false optional: true /esbuild-android-arm64/0.14.27: @@ -3564,7 +3559,6 @@ packages: cpu: [arm64] os: [android] requiresBuild: true - dev: false optional: true /esbuild-darwin-64/0.14.27: @@ -3573,7 +3567,6 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true - dev: false optional: true /esbuild-darwin-arm64/0.14.27: @@ -3582,7 +3575,6 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true - dev: false optional: true /esbuild-freebsd-64/0.14.27: @@ -3591,7 +3583,6 @@ packages: cpu: [x64] os: [freebsd] requiresBuild: true - dev: false optional: true /esbuild-freebsd-arm64/0.14.27: @@ -3600,7 +3591,6 @@ packages: cpu: [arm64] os: [freebsd] requiresBuild: true - dev: false optional: true /esbuild-linux-32/0.14.27: @@ -3609,7 +3599,6 @@ packages: cpu: [ia32] os: [linux] requiresBuild: true - dev: false optional: true /esbuild-linux-64/0.14.27: @@ -3618,7 +3607,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: false optional: true /esbuild-linux-arm/0.14.27: @@ -3627,7 +3615,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: false optional: true /esbuild-linux-arm64/0.14.27: @@ -3636,7 +3623,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: false optional: true /esbuild-linux-mips64le/0.14.27: @@ -3645,7 +3631,6 @@ packages: cpu: [mips64el] os: [linux] requiresBuild: true - dev: false optional: true /esbuild-linux-ppc64le/0.14.27: @@ -3654,7 +3639,6 @@ packages: cpu: [ppc64] os: [linux] requiresBuild: true - dev: false optional: true /esbuild-linux-riscv64/0.14.27: @@ -3663,7 +3647,6 @@ packages: cpu: [riscv64] os: [linux] requiresBuild: true - dev: false optional: true /esbuild-linux-s390x/0.14.27: @@ -3672,7 +3655,6 @@ packages: cpu: [s390x] os: [linux] requiresBuild: true - dev: false optional: true /esbuild-netbsd-64/0.14.27: @@ -3681,7 +3663,6 @@ packages: cpu: [x64] os: [netbsd] requiresBuild: true - dev: false optional: true /esbuild-openbsd-64/0.14.27: @@ -3690,7 +3671,6 @@ packages: cpu: [x64] os: [openbsd] requiresBuild: true - dev: false optional: true /esbuild-runner/2.2.1_esbuild@0.14.27: @@ -3710,7 +3690,6 @@ packages: cpu: [x64] os: [sunos] requiresBuild: true - dev: false optional: true /esbuild-windows-32/0.14.27: @@ -3719,7 +3698,6 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true - dev: false optional: true /esbuild-windows-64/0.14.27: @@ -3728,7 +3706,6 @@ packages: cpu: [x64] os: [win32] requiresBuild: true - dev: false optional: true /esbuild-windows-arm64/0.14.27: @@ -3737,7 +3714,6 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true - dev: false optional: true /esbuild/0.14.27: @@ -3766,7 +3742,6 @@ packages: esbuild-windows-32: 0.14.27 esbuild-windows-64: 0.14.27 esbuild-windows-arm64: 0.14.27 - dev: false /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} @@ -4311,7 +4286,6 @@ packages: /fast-safe-stringify/2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - dev: true /fastq/1.13.0: resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} @@ -4415,7 +4389,6 @@ packages: peerDependenciesMeta: debug: optional: true - dev: true /foreach/2.0.5: resolution: {integrity: sha1-C+4AUBiusmDQo6865ljdATbsG5k=} @@ -5382,7 +5355,6 @@ packages: /iterare/1.2.1: resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==} engines: {node: '>=6'} - dev: true /jake/10.8.4: resolution: {integrity: sha512-MtWeTkl1qGsWUtbl/Jsca/8xSoK3x0UmS82sNbjqxxG/de/M/3b1DntdjHgPMC50enlTNwXOCRqPXLLt5cCfZA==} @@ -6076,7 +6048,6 @@ packages: /libphonenumber-js/1.9.50: resolution: {integrity: sha512-cCzQPChw2XbordcO2LKiw5Htx5leHVfFk/EXkxNHqJfFo7Fndcb1kF5wPJpc316vCJhhikedYnVysMh3Sc7Ocw==} - dev: true /lines-and-columns/1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -6150,7 +6121,6 @@ packages: engines: {node: '>=10'} dependencies: yallist: 4.0.0 - dev: true /macos-release/2.5.0: resolution: {integrity: sha512-EIgv+QZ9r+814gjJj0Bt5vSLJLzswGmSUbUpbi9AIr/fsN2IWFBl2NucV9PAiek+U1STK468tEkxmVYUtuAN3g==} @@ -6344,7 +6314,6 @@ packages: on-finished: 2.4.1 type-is: 1.6.18 xtend: 4.0.2 - dev: false /multibase/0.6.1: resolution: {integrity: sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==} @@ -6385,6 +6354,10 @@ packages: varint: 5.0.2 dev: true + /murmurhash-js/1.0.0: + resolution: {integrity: sha1-sGJ44h/Gw3+lMTcysEEry2rhX1E=} + dev: false + /mute-stream/0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} @@ -6441,7 +6414,6 @@ packages: optional: true dependencies: whatwg-url: 5.0.0 - dev: true /node-gyp-build/4.4.0: resolution: {integrity: sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==} @@ -6528,7 +6500,6 @@ packages: /object-hash/3.0.0: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} - dev: true /object-inspect/1.12.0: resolution: {integrity: sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==} @@ -6580,7 +6551,6 @@ packages: engines: {node: '>= 0.8'} dependencies: ee-first: 1.1.1 - dev: false /once/1.4.0: resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} @@ -6800,7 +6770,6 @@ packages: /path-to-regexp/3.2.0: resolution: {integrity: sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==} - dev: true /path-type/4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} @@ -7061,7 +7030,6 @@ packages: inherits: 2.0.4 isarray: 0.0.1 string_decoder: 0.10.31 - dev: false /readable-stream/2.3.7: resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} @@ -7119,7 +7087,6 @@ packages: /reflect-metadata/0.1.13: resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==} - dev: true /regexpp/3.2.0: resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} @@ -7550,7 +7517,6 @@ packages: /streamsearch/0.1.2: resolution: {integrity: sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=} engines: {node: '>=0.8.0'} - dev: false /strict-uri-encode/1.1.0: resolution: {integrity: sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=} @@ -7878,7 +7844,6 @@ packages: /tr46/0.0.3: resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=} - dev: true /tr46/2.1.0: resolution: {integrity: sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==} @@ -8156,7 +8121,6 @@ packages: /typedarray/0.0.6: resolution: {integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=} - dev: false /typescript/4.6.2: resolution: {integrity: sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==} @@ -8304,7 +8268,6 @@ packages: /uuid/8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true - dev: true /v8-compile-cache-lib/3.0.0: resolution: {integrity: sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==} @@ -8326,7 +8289,6 @@ packages: /validator/13.7.0: resolution: {integrity: sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==} engines: {node: '>= 0.10'} - dev: true /varint/5.0.2: resolution: {integrity: sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==} @@ -8638,7 +8600,6 @@ packages: /webidl-conversions/3.0.1: resolution: {integrity: sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=} - dev: true /webidl-conversions/5.0.0: resolution: {integrity: sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==} @@ -8729,7 +8690,6 @@ packages: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: true /whatwg-url/8.7.0: resolution: {integrity: sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==} @@ -8920,7 +8880,6 @@ packages: /yallist/4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true /yaml/1.10.2: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} diff --git a/src/position/position-source/position-source.api.ts b/src/position/position-source/position-source.api.ts index 17832de81..a79e1aa47 100644 --- a/src/position/position-source/position-source.api.ts +++ b/src/position/position-source/position-source.api.ts @@ -1,10 +1,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import Axios, { AxiosInstance } from 'axios'; +import DataLoader from 'dataloader'; import qs from 'qs'; import { ContractType } from '~position/contract.interface'; -import { AbstractPosition } from '~position/position.interface'; +import { AbstractPosition, AppTokenPosition, ContractPosition } from '~position/position.interface'; import { AppGroupsDefinition } from '~position/position.service'; import { PositionSource } from './position-source.interface'; @@ -12,12 +13,44 @@ import { PositionSource } from './position-source.interface'; @Injectable() export class ApiPositionSource implements PositionSource { private readonly axios: AxiosInstance; + private readonly tokensDataLoader: DataLoader; + private readonly positionsDataLoader: DataLoader; constructor(@Inject(ConfigService) private readonly configService: ConfigService) { this.axios = Axios.create({ baseURL: this.configService.get('zapperApi.url'), params: { api_key: this.configService.get('zapperApi.key') }, }); + + const buildBatchFn = + (contractType: ContractType) => + async (definitions: AppGroupsDefinition[]) => { + const pathParam = contractType === ContractType.APP_TOKEN ? 'tokens' : 'contract-positions'; + const query = qs.stringify({ definitions }); + const { data } = await this.axios.get(`/v1/positions/${pathParam}?${query}`); + + // Re-group the results + const result = definitions.map(def => + data.filter( + ({ appId, groupId, network }) => + def.appId === appId && def.network === network && def.groupIds.includes(groupId), + ), + ); + + return result; + }; + + // The dataloaders will batch together requests for app groups, and cache them in memory + // Note: There is no TTL; these caches are evicted on restarting the dev server + this.tokensDataLoader = new DataLoader( + buildBatchFn(ContractType.APP_TOKEN), + { cacheKeyFn: v => `tokens:${v.network}:${v.appId}:${v.groupIds.join(',')}` }, + ); + + this.positionsDataLoader = new DataLoader( + buildBatchFn(ContractType.POSITION), + { cacheKeyFn: v => `contract-positions:${v.network}:${v.appId}:${v.groupIds.join(',')}` }, + ); } async getPositions>( @@ -25,11 +58,8 @@ export class ApiPositionSource implements PositionSource { contractType: ContractType, ): Promise { if (!definitions.length) return []; - - const pathParam = contractType === ContractType.APP_TOKEN ? 'tokens' : 'contract-positions'; - const query = qs.stringify({ definitions }); - const { data: positions } = await this.axios.get(`/v1/positions/${pathParam}?${query}`); - - return positions; + const loader = contractType === ContractType.APP_TOKEN ? this.tokensDataLoader : this.positionsDataLoader; + const results = await Promise.all(definitions.map(v => loader.load(v))).then(v => v.flat()); + return results as any as T[]; } } diff --git a/src/position/position.interface.ts b/src/position/position.interface.ts index de7b4a947..d0e62f10f 100644 --- a/src/position/position.interface.ts +++ b/src/position/position.interface.ts @@ -19,7 +19,7 @@ export interface AbstractPosition extends Contract { key?: string; } -export interface ContractPosition> extends AbstractPosition { +export interface ContractPosition extends AbstractPosition { type: ContractType.POSITION; } diff --git a/src/token/token.service.ts b/src/token/token.service.ts index 3141f7280..5c4b9c5f4 100644 --- a/src/token/token.service.ts +++ b/src/token/token.service.ts @@ -19,7 +19,7 @@ export class TokenService { @Cache({ key: (network: Network) => `token-prices:${network}`, ttl: 60 }) async getTokenPrices(network: Network) { - const { data: tokenPrices } = await this.axios.get('/v1/prices-v3', { params: { network } }); + const { data: tokenPrices } = await this.axios.get('/v1/prices', { params: { network } }); return tokenPrices; }