diff --git a/assets/svg/brand/logo-only.svg b/assets/svg/brand/logo-only.svg new file mode 100644 index 0000000000..425cafe979 --- /dev/null +++ b/assets/svg/brand/logo-only.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/Text/Heading.tsx b/components/Text/Heading.tsx index 8252cef5d1..620677b20e 100644 --- a/components/Text/Heading.tsx +++ b/components/Text/Heading.tsx @@ -20,7 +20,7 @@ const StyledHeading = styled.h1<{ line-height: 1.2; margin: 0; ${(props) => css` - color: ${props.theme.colors.common.primaryWhite}; + color: ${props.theme.colors.selectedTheme.text.value}; font-size: ${props.$fontSize ?? sizes[props.$variant]}px; `} `; diff --git a/hooks/useStatsData.ts b/hooks/useStatsData.ts index db035fc557..7485b01861 100644 --- a/hooks/useStatsData.ts +++ b/hooks/useStatsData.ts @@ -6,7 +6,7 @@ import { selectMarkPrices, selectMarkets } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; import { selectMinTimestamp } from 'state/stats/selectors'; -export type StatsTimeframe = '1M' | '1Y' | 'MAX'; +export type StatsTimeframe = '4H' | '1D' | '1W' | '1M' | '1Y' | 'MAX'; export type DailyStat = { timestamp: number; diff --git a/package-lock.json b/package-lock.json index 24cc446cb4..4b952580d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "kwenta", - "version": "6.2.3", + "version": "6.2.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "kwenta", - "version": "6.2.3", + "version": "6.2.5", "hasInstallScript": true, "dependencies": { "@artsy/fresnel": "1.7.0", @@ -16,13 +16,13 @@ "@kwenta/synthswap": "^1.0.3", "@material-ui/core": "^4.12.3", "@metamask/detect-provider": "2.0.0", - "@pythnetwork/pyth-evm-js": "^1.0.1", + "@pythnetwork/pyth-evm-js": "1.10.0", "@rainbow-me/rainbowkit": "0.8.1", "@reach/dialog": "0.15.0", "@reduxjs/toolkit": "^1.8.5", - "@sentry/browser": "^7.37.0", - "@sentry/tracing": "^7.37.0", - "@socket.tech/plugin": "^1.0.3", + "@sentry/browser": "7.43.0", + "@sentry/tracing": "7.43.0", + "@socket.tech/plugin": "1.0.3", "@synthetixio/optimism-networks": "2.74.6", "@synthetixio/providers": "2.74.10", "@synthetixio/transaction-notifier": "2.74.12", @@ -43,7 +43,7 @@ "imagemin-mozjpeg": "^10.0.0", "intercept-stdout": "^0.1.2", "isomorphic-dompurify": "^0.26.0", - "lightweight-charts": "^3.8.0", + "lightweight-charts": "4.0.1", "lodash": "4.17.21", "moment-business-time": "2.0.0", "next": "12.2.4", @@ -64,6 +64,7 @@ "react-slick": "0.29.0", "react-table": "7.7.0", "react-toastify": "^9.0.4", + "recharts": "^2.5.0", "redux-logger": "^3.0.6", "redux-persist": "^6.0.0", "slick-carousel": "1.8.1", @@ -74,7 +75,7 @@ }, "devDependencies": { "@microsoft/eslint-formatter-sarif": "2.1.7", - "@next/eslint-plugin-next": "^12.1.6", + "@next/eslint-plugin-next": "12.3.4", "@storybook/addon-actions": "^6.4.13", "@storybook/addon-essentials": "6.5.13", "@storybook/addon-links": "^6.4.13", @@ -133,7 +134,7 @@ "postcss": "^8.4.20", "prettier": "2.0.5", "react-test-renderer": "17.0.1", - "typechain": "^8.1.0", + "typechain": "8.1.1", "typescript": "4.7.4", "url-loader": "4.1.0", "webp-loader": "0.6.0" @@ -6182,9 +6183,9 @@ "integrity": "sha512-/gApFXWk5CCLFQJL5IYJXxPQuG5tz5nPX4l27A9Zm/+wJxiwFrRSP54AopDxIv4JRp/rGwcgk/lZS/0Clw8jYA==" }, "node_modules/@next/eslint-plugin-next": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.1.tgz", - "integrity": "sha512-sw+lTf6r6P0j+g/n9y4qdWWI2syPqZx+uc0+B/fRENqfR3KpSid6MIKqc9gNwGhJASazEQ5b3w8h4cAET213jw==", + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.4.tgz", + "integrity": "sha512-BFwj8ykJY+zc1/jWANsDprDIu2MgwPOIKxNVnrKvPs+f5TPegrVnem8uScND+1veT4B7F6VeqgaNLFW1Hzl9Og==", "dev": true, "dependencies": { "glob": "7.1.7" @@ -6695,21 +6696,21 @@ "async-limiter": "~1.0.0" } }, - "node_modules/@pythnetwork/pyth-common-js": { + "node_modules/@pythnetwork/price-service-client": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-common-js/-/pyth-common-js-1.4.0.tgz", - "integrity": "sha512-ilK+0/+tivMVPMIFmup+UfUHklhsS2fqofZxS2+XCn4WBJfI0lIKtiAaBVjV7WmzmC2mDjujcTCDn4RbqpLVqg==", + "resolved": "https://registry.npmjs.org/@pythnetwork/price-service-client/-/price-service-client-1.4.0.tgz", + "integrity": "sha512-ibFxczDll/GdXX3jT7YB7+tbxyoXisop7EWXebaBjJqvc+OTctVNmJHCjlz4goDy5l1IDDsxEEYJyjckGsLjVA==", "dependencies": { - "@pythnetwork/pyth-sdk-js": "^1.2.0", + "@pythnetwork/price-service-sdk": "*", "@types/ws": "^8.5.3", - "axios": "^0.26.1", - "axios-retry": "^3.2.4", + "axios": "^1.2.5", + "axios-retry": "^3.4.0", "isomorphic-ws": "^4.0.1", "ts-log": "^2.2.4", "ws": "^8.6.0" } }, - "node_modules/@pythnetwork/pyth-common-js/node_modules/@types/ws": { + "node_modules/@pythnetwork/price-service-client/node_modules/@types/ws": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", @@ -6717,18 +6718,38 @@ "@types/node": "*" } }, - "node_modules/@pythnetwork/pyth-common-js/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "node_modules/@pythnetwork/price-service-client/node_modules/axios": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", "dependencies": { - "follow-redirects": "^1.14.8" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, - "node_modules/@pythnetwork/pyth-common-js/node_modules/ws": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", - "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", + "node_modules/@pythnetwork/price-service-client/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/@pythnetwork/price-service-client/node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/@pythnetwork/price-service-client/node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "engines": { "node": ">=10.0.0" }, @@ -6745,12 +6766,17 @@ } } }, + "node_modules/@pythnetwork/price-service-sdk": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@pythnetwork/price-service-sdk/-/price-service-sdk-1.2.0.tgz", + "integrity": "sha512-h4HcUwBPFEZwa5nLMTz9YnwdLE5m+Bfctzqbj09vpSJo2DyPHCyEXScFUuizWBbfofxB/pF+OnZXjU3pJxtm/w==" + }, "node_modules/@pythnetwork/pyth-evm-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-evm-js/-/pyth-evm-js-1.1.0.tgz", - "integrity": "sha512-cfxzJ6u6THJ4pyAlfdJ4pw1MbXPAaRqTPPzpjopiuUmme8M3m7HK7wKP9TIxHEnGyCqTw3MnWG1r+TS2zbO13g==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-evm-js/-/pyth-evm-js-1.10.0.tgz", + "integrity": "sha512-trop6n+JOR2AAjDKskI0FU/XWZ/b8DD/v5RsARTlKTfFmBKu/n4Km8LiXH8Llq3vsl4xUQ7/y+locj0defQ0JA==", "dependencies": { - "@pythnetwork/pyth-common-js": "^1.2.0", + "@pythnetwork/price-service-client": "*", "buffer": "^6.0.3" } }, @@ -6777,11 +6803,6 @@ "ieee754": "^1.2.1" } }, - "node_modules/@pythnetwork/pyth-sdk-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-js/-/pyth-sdk-js-1.2.0.tgz", - "integrity": "sha512-grh6YCkp/nH73ACNu+Mew64lLVgz6egVBJm8JvdNkRggWkUn1PE4ZvV/6ceTIui5OhI369qzMCkldiAlIMBjnQ==" - }, "node_modules/@rainbow-me/rainbowkit": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@rainbow-me/rainbowkit/-/rainbowkit-0.8.1.tgz", @@ -6856,26 +6877,26 @@ } }, "node_modules/@react-spring/animated": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.6.1.tgz", - "integrity": "sha512-ls/rJBrAqiAYozjLo5EPPLLOb1LM0lNVQcXODTC1SMtS6DbuBCPaKco5svFUQFMP2dso3O+qcC4k9FsKc0KxMQ==", + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.1.tgz", + "integrity": "sha512-EX5KAD9y7sD43TnLeTNG1MgUVpuRO1YaSJRPawHNRgUWYfILge3s85anny4S4eTJGpdp5OoFV2kx9fsfeo0qsw==", "dependencies": { - "@react-spring/shared": "~9.6.1", - "@react-spring/types": "~9.6.1" + "@react-spring/shared": "~9.7.1", + "@react-spring/types": "~9.7.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/@react-spring/core": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.6.1.tgz", - "integrity": "sha512-3HAAinAyCPessyQNNXe5W0OHzRfa8Yo5P748paPcmMowZ/4sMfaZ2ZB6e5x5khQI8NusOHj8nquoutd6FRY5WQ==", + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.1.tgz", + "integrity": "sha512-8K9/FaRn5VvMa24mbwYxwkALnAAyMRdmQXrARZLcBW2vxLJ6uw9Cy3d06Z8M12kEqF2bDlccaCSDsn2bSz+Q4A==", "dependencies": { - "@react-spring/animated": "~9.6.1", - "@react-spring/rafz": "~9.6.1", - "@react-spring/shared": "~9.6.1", - "@react-spring/types": "~9.6.1" + "@react-spring/animated": "~9.7.1", + "@react-spring/rafz": "~9.7.1", + "@react-spring/shared": "~9.7.1", + "@react-spring/types": "~9.7.1" }, "funding": { "type": "opencollective", @@ -6886,36 +6907,36 @@ } }, "node_modules/@react-spring/rafz": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.6.1.tgz", - "integrity": "sha512-v6qbgNRpztJFFfSE3e2W1Uz+g8KnIBs6SmzCzcVVF61GdGfGOuBrbjIcp+nUz301awVmREKi4eMQb2Ab2gGgyQ==" + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.1.tgz", + "integrity": "sha512-JSsrRfbEJvuE3w/uvU3mCTuWwpQcBXkwoW14lBgzK9XJhuxmscGo59AgJUpFkGOiGAVXFBGB+nEXtSinFsopgw==" }, "node_modules/@react-spring/shared": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.6.1.tgz", - "integrity": "sha512-PBFBXabxFEuF8enNLkVqMC9h5uLRBo6GQhRMQT/nRTnemVENimgRd+0ZT4yFnAQ0AxWNiJfX3qux+bW2LbG6Bw==", + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.1.tgz", + "integrity": "sha512-R2kZ+VOO6IBeIAYTIA3C1XZ0ZVg/dDP5FKtWaY8k5akMer9iqf5H9BU0jyt3Qtxn0qQY7whQdf6MTcWtKeaawg==", "dependencies": { - "@react-spring/rafz": "~9.6.1", - "@react-spring/types": "~9.6.1" + "@react-spring/rafz": "~9.7.1", + "@react-spring/types": "~9.7.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/@react-spring/types": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.6.1.tgz", - "integrity": "sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q==" + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.1.tgz", + "integrity": "sha512-yBcyfKUeZv9wf/ZFrQszvhSPuDx6Py6yMJzpMnS+zxcZmhXPeOCKZSHwqrUz1WxvuRckUhlgb7eNI/x5e1e8CA==" }, "node_modules/@react-spring/web": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.6.1.tgz", - "integrity": "sha512-X2zR6q2Z+FjsWfGAmAXlQaoUHbPmfuCaXpuM6TcwXPpLE1ZD4A1eys/wpXboFQmDkjnrlTmKvpVna1MjWpZ5Hw==", + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.1.tgz", + "integrity": "sha512-6uUE5MyKqdrJnIJqlDN/AXf3i8PjOQzUuT26nkpsYxUGOk7c+vZVPcfrExLSoKzTb9kF0i66DcqzO5fXz/Z1AA==", "dependencies": { - "@react-spring/animated": "~9.6.1", - "@react-spring/core": "~9.6.1", - "@react-spring/shared": "~9.6.1", - "@react-spring/types": "~9.6.1" + "@react-spring/animated": "~9.7.1", + "@react-spring/core": "~9.7.1", + "@react-spring/shared": "~9.7.1", + "@react-spring/types": "~9.7.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0", @@ -6946,14 +6967,14 @@ } }, "node_modules/@sentry/browser": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.37.0.tgz", - "integrity": "sha512-EMlSo4Ebtryd5id2nC31dwcLigwYPWjrAYt36vUJ/L47oXetaH4dndK6wqYyxR2sl8uP2GlsQUnWpGLHKyG3ww==", - "dependencies": { - "@sentry/core": "7.37.0", - "@sentry/replay": "7.37.0", - "@sentry/types": "7.37.0", - "@sentry/utils": "7.37.0", + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.43.0.tgz", + "integrity": "sha512-NlRkBYKb9o5IQdGY8Ktps19Hz9RdSuqS1tlLC7Sjr+MqZqSHmhKq8MWJKciRynxBeMbeGt0smExi9BqpVQdCEg==", + "dependencies": { + "@sentry/core": "7.43.0", + "@sentry/replay": "7.43.0", + "@sentry/types": "7.43.0", + "@sentry/utils": "7.43.0", "tslib": "^1.9.3" }, "engines": { @@ -6966,12 +6987,12 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/core": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.37.0.tgz", - "integrity": "sha512-2M6aZKIG/1HgfE0hobQ9tKSo6ZsyBrSQqjtQhMVFwVzZJyFw3m1AqcrB+f0myi+1ay2MMPbJ+HhYtBPR3e4EvA==", + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.43.0.tgz", + "integrity": "sha512-zvMZgEi7ptLBwDnd+xR/u4zdSe5UzS4S3ZhoemdQrn1PxsaVySD/ptyzLoGSZEABqlRxGHnQrZ78MU1hUDvKuQ==", "dependencies": { - "@sentry/types": "7.37.0", - "@sentry/utils": "7.37.0", + "@sentry/types": "7.43.0", + "@sentry/utils": "7.43.0", "tslib": "^1.9.3" }, "engines": { @@ -6984,26 +7005,26 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/replay": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.37.0.tgz", - "integrity": "sha512-uGqPjEz3dprahRNslK35tR2N5RGULMH5uL/1InU65O5XUgq/wTyQ7ZH0qy743J8U6dBo/2n7V/RQdB9lA2sLBw==", + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.43.0.tgz", + "integrity": "sha512-2dGJS6p8uG1JZ7x/A3FyqnILTkXarbvfR+o1lC7z9lu34Wx0ZBeU2in/S2YHNGAE6XvfsePq3ya/s7LaNkk4qQ==", "dependencies": { - "@sentry/core": "7.37.0", - "@sentry/types": "7.37.0", - "@sentry/utils": "7.37.0" + "@sentry/core": "7.43.0", + "@sentry/types": "7.43.0", + "@sentry/utils": "7.43.0" }, "engines": { "node": ">=12" } }, "node_modules/@sentry/tracing": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.37.0.tgz", - "integrity": "sha512-DvFEwsXNsroVPNFOAblKwzKoO75dLhYw0XVmm+OlXTTQriJG5YkzcqazJ9pJ0l+f9ttswElGr3gLHMn797vsMA==", + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.43.0.tgz", + "integrity": "sha512-Mld2AyV8xYnRLYbDWvDy8PlGcln3h5JsUx6ScQGOxnFTmCQR50Tldtzq50VDs2fv6xH0+YrL/UIyjxCDc7EXzQ==", "dependencies": { - "@sentry/core": "7.37.0", - "@sentry/types": "7.37.0", - "@sentry/utils": "7.37.0", + "@sentry/core": "7.43.0", + "@sentry/types": "7.43.0", + "@sentry/utils": "7.43.0", "tslib": "^1.9.3" }, "engines": { @@ -7016,19 +7037,19 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/types": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.37.0.tgz", - "integrity": "sha512-p8iw5oGvWLIk7osMgXhxshUpebJD0riiuT3ihBP0DV+Gs8r0qdQ5gtcStl7Cn0D4013p4j/f3T5q85Z9ENE6fA==", + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.43.0.tgz", + "integrity": "sha512-5XxCWqYWJNoS+P6Ie2ZpUDxLRCt7FTEzmlQkCdjW6MFWOX26hAbF/wEuOTYAFKZXMIXOz0Egofik1e8v1Cg6/A==", "engines": { "node": ">=8" } }, "node_modules/@sentry/utils": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.37.0.tgz", - "integrity": "sha512-CN86EKQ07+SgqfgGehMJsgrCEjc0sl1YDcj2xf9dA0Bn3ma2MTDkCyutxVcRfc2IVWfqAN1rn/L8/BH2v2+eqA==", + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.43.0.tgz", + "integrity": "sha512-f78YfMLcgNU7+suyWFCuQhQlneXXMS+egb0EFZh7iU7kANUPRX5T4b+0C+fwaPm5gA6XfGYskr4ZnzQJLOlSqg==", "dependencies": { - "@sentry/types": "7.37.0", + "@sentry/types": "7.43.0", "tslib": "^1.9.3" }, "engines": { @@ -7095,9 +7116,9 @@ } }, "node_modules/@socket.tech/ll-core": { - "version": "0.1.26", - "resolved": "https://registry.npmjs.org/@socket.tech/ll-core/-/ll-core-0.1.26.tgz", - "integrity": "sha512-TeHS1ZeGAg73xqM25/gfguM7A8fv1BRMoYha2qHBpApAenl5TH0hSfPe0yBNg/ASZ7waeXNzGUConj/RA/OPlg==" + "version": "0.1.29", + "resolved": "https://registry.npmjs.org/@socket.tech/ll-core/-/ll-core-0.1.29.tgz", + "integrity": "sha512-Tt3NenGOPvifyOKBkyCN3NdxI2x6hSm2PaNY+JOrBMLfBaxolEkvamgtISst+pfvvo5WDQKI/7VZf7IOrdbAqg==" }, "node_modules/@socket.tech/plugin": { "version": "1.0.3", @@ -7119,9 +7140,9 @@ } }, "node_modules/@socket.tech/socket-v2-sdk": { - "version": "1.21.5", - "resolved": "https://registry.npmjs.org/@socket.tech/socket-v2-sdk/-/socket-v2-sdk-1.21.5.tgz", - "integrity": "sha512-ufYyJSN9C32G1I2KB7srczgwXBPyZJ42BAmjblMHrOosDR9XynQ3tKu/inKxOSV9jG31bH0zp3EOBssokVWmoA==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/@socket.tech/socket-v2-sdk/-/socket-v2-sdk-1.21.6.tgz", + "integrity": "sha512-tzx6Be1Nt26j+JPndj618LjUcJItfnaA004k1fVpSHMg8QalJs6PxbAUflDQuqccQT4VuMXwwuOVJWSsb16pVw==", "dependencies": { "@socket.tech/ll-core": "^0.1.14", "axios": "^0.27.2", @@ -21443,6 +21464,60 @@ "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", "dev": true }, + "node_modules/@types/d3-array": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.4.tgz", + "integrity": "sha512-nwvEkG9vYOc0Ic7G7kwgviY4AQlTfYGIZ0fqB7CQHXGyYM6nO7kJh5EguSNA3jfh4rq7Sb7eMVq8isuvg2/miQ==" + }, + "node_modules/@types/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.0.tgz", + "integrity": "sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.0.tgz", + "integrity": "sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.3.tgz", + "integrity": "sha512-PATBiMCpvHJSMtZAMEhc2WyL+hnzarKzI6wAHYjhsonjWJYGq5BXTzQjv4l8m2jO183/4wZ90rKvSeT7o72xNQ==", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.1.tgz", + "integrity": "sha512-6Uh86YFF7LGg4PQkuO2oG6EMBRLuW9cbavUW46zkIO5kuS2PfTqo2o9SkgtQzguBHbLgNnU90UNsITpsX1My+A==", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.0.tgz", + "integrity": "sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.0.tgz", + "integrity": "sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==" + }, "node_modules/@types/date-fns": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@types/date-fns/-/date-fns-2.6.0.tgz", @@ -30486,6 +30561,11 @@ "node": ">=8.0.0" } }, + "node_modules/css-unit-converter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", + "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==" + }, "node_modules/css-vendor": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", @@ -30809,6 +30889,116 @@ "type": "^1.0.1" } }, + "node_modules/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -30913,6 +31103,11 @@ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.2.tgz", "integrity": "sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==" }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + }, "node_modules/decode-uri-component": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", @@ -34810,9 +35005,9 @@ } }, "node_modules/fancy-canvas": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/fancy-canvas/-/fancy-canvas-0.2.2.tgz", - "integrity": "sha512-50qi8xA0QkHbjmb8h7XQ6k2fvD7y/yMfiUw9YTarJ7rWrq6o5/3CCXPouYk+XSLASvvxtjyiQLRBFt3qkE3oyA==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fancy-canvas/-/fancy-canvas-2.1.0.tgz", + "integrity": "sha512-nifxXJ95JNLFR2NgRV4/MxVP45G9909wJTEKz5fg/TZS20JJZA6hfgRVh/bC9bwl2zBtBNcYPjiBE4njQHVBwQ==" }, "node_modules/fast-check": { "version": "3.1.1", @@ -34842,6 +35037,11 @@ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "dev": true }, + "node_modules/fast-equals": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz", + "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==" + }, "node_modules/fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", @@ -38301,6 +38501,14 @@ "node": ">= 0.4" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, "node_modules/interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", @@ -43680,11 +43888,11 @@ } }, "node_modules/lightweight-charts": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/lightweight-charts/-/lightweight-charts-3.8.0.tgz", - "integrity": "sha512-7yFGnYuE1RjRJG9RwUTBz5wvF1QtjBOSW4FFlikr8Dh+/TDNt4ci+HsWSYmStgQUpawpvkCJ3j5/W25GppGj9Q==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lightweight-charts/-/lightweight-charts-4.0.1.tgz", + "integrity": "sha512-p+j6w41PVzf9Vn7IrmpmCJacunpN0kKsl0IZoxMOySSkDcSagZ7Is9pb6pclIfN/usHdta0aYm9FktkYpAQe0g==", "dependencies": { - "fancy-canvas": "0.2.2" + "fancy-canvas": "2.1.0" } }, "node_modules/lilconfig": { @@ -49330,6 +49538,11 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, "node_modules/react-query": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.35.0.tgz", @@ -49447,6 +49660,18 @@ } } }, + "node_modules/react-resize-detector": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-8.0.4.tgz", + "integrity": "sha512-ln9pMAob8y8mc9UI4aZuuWFiyMqBjnTs/sxe9Vs9dPXUjwCTeKK1FP8I75ufnb/2mEEZXG6wOo/fjMcBRRuAXw==", + "dependencies": { + "lodash": "^4.17.21" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-rnd": { "version": "10.3.7", "resolved": "https://registry.npmjs.org/react-rnd/-/react-rnd-10.3.7.tgz", @@ -49513,6 +49738,43 @@ "react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-smooth": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-2.0.2.tgz", + "integrity": "sha512-pgqSp1q8rAGtF1bXQE0m3CHGLNfZZh5oA5o1tsPLXRHnKtkujMIJ8Ws5nO1mTySZf1c4vgwlEk+pHi3Ln6eYLw==", + "dependencies": { + "fast-equals": "^4.0.3", + "react-transition-group": "2.9.0" + }, + "peerDependencies": { + "prop-types": "^15.6.0", + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-smooth/node_modules/dom-helpers": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", + "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", + "dependencies": { + "@babel/runtime": "^7.1.2" + } + }, + "node_modules/react-smooth/node_modules/react-transition-group": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", + "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", + "dependencies": { + "dom-helpers": "^3.4.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0", + "react-dom": ">=15.0.0" + } + }, "node_modules/react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -49759,6 +50021,43 @@ "node": ">=8.10.0" } }, + "node_modules/recharts": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.5.0.tgz", + "integrity": "sha512-0EQYz3iA18r1Uq8VqGZ4dABW52AKBnio37kJgnztIqprELJXpOEsa0SzkqU1vjAhpCXCv52Dx1hiL9119xsqsQ==", + "dependencies": { + "classnames": "^2.2.5", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.19", + "react-is": "^16.10.2", + "react-resize-detector": "^8.0.4", + "react-smooth": "^2.0.2", + "recharts-scale": "^0.4.4", + "reduce-css-calc": "^2.1.8", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "prop-types": "^15.6.0", + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, + "node_modules/recharts/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -49772,6 +50071,20 @@ "node": ">=8" } }, + "node_modules/reduce-css-calc": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz", + "integrity": "sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==", + "dependencies": { + "css-unit-converter": "^1.1.1", + "postcss-value-parser": "^3.3.0" + } + }, + "node_modules/reduce-css-calc/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, "node_modules/reduce-flatten": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", @@ -55144,9 +55457,9 @@ } }, "node_modules/typechain": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.1.0.tgz", - "integrity": "sha512-5jToLgKTjHdI1VKqs/K8BLYy42Sr3o8bV5ojh4MnR9ExHO83cyyUdw+7+vMJCpKXUiVUvARM4qmHTFuyaCMAZQ==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.1.1.tgz", + "integrity": "sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ==", "dev": true, "dependencies": { "@types/prettier": "^2.1.1", @@ -56293,6 +56606,27 @@ "node": ">=4" } }, + "node_modules/victory-vendor": { + "version": "36.6.8", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.6.8.tgz", + "integrity": "sha512-H3kyQ+2zgjMPvbPqAl7Vwm2FD5dU7/4bCTQakFQnpIsfDljeOMDojRsrmJfwh4oAlNnWhpAf+mbAoLh8u7dwyQ==", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, "node_modules/vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -63593,9 +63927,9 @@ "integrity": "sha512-/gApFXWk5CCLFQJL5IYJXxPQuG5tz5nPX4l27A9Zm/+wJxiwFrRSP54AopDxIv4JRp/rGwcgk/lZS/0Clw8jYA==" }, "@next/eslint-plugin-next": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.1.tgz", - "integrity": "sha512-sw+lTf6r6P0j+g/n9y4qdWWI2syPqZx+uc0+B/fRENqfR3KpSid6MIKqc9gNwGhJASazEQ5b3w8h4cAET213jw==", + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.4.tgz", + "integrity": "sha512-BFwj8ykJY+zc1/jWANsDprDIu2MgwPOIKxNVnrKvPs+f5TPegrVnem8uScND+1veT4B7F6VeqgaNLFW1Hzl9Og==", "dev": true, "requires": { "glob": "7.1.7" @@ -63916,15 +64250,15 @@ } } }, - "@pythnetwork/pyth-common-js": { + "@pythnetwork/price-service-client": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-common-js/-/pyth-common-js-1.4.0.tgz", - "integrity": "sha512-ilK+0/+tivMVPMIFmup+UfUHklhsS2fqofZxS2+XCn4WBJfI0lIKtiAaBVjV7WmzmC2mDjujcTCDn4RbqpLVqg==", + "resolved": "https://registry.npmjs.org/@pythnetwork/price-service-client/-/price-service-client-1.4.0.tgz", + "integrity": "sha512-ibFxczDll/GdXX3jT7YB7+tbxyoXisop7EWXebaBjJqvc+OTctVNmJHCjlz4goDy5l1IDDsxEEYJyjckGsLjVA==", "requires": { - "@pythnetwork/pyth-sdk-js": "^1.2.0", + "@pythnetwork/price-service-sdk": "*", "@types/ws": "^8.5.3", - "axios": "^0.26.1", - "axios-retry": "^3.2.4", + "axios": "^1.2.5", + "axios-retry": "^3.4.0", "isomorphic-ws": "^4.0.1", "ts-log": "^2.2.4", "ws": "^8.6.0" @@ -63939,26 +64273,48 @@ } }, "axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", "requires": { - "follow-redirects": "^1.14.8" + "follow-redirects": "^1.15.0", + "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" + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "ws": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", - "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==" + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==" } } }, + "@pythnetwork/price-service-sdk": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@pythnetwork/price-service-sdk/-/price-service-sdk-1.2.0.tgz", + "integrity": "sha512-h4HcUwBPFEZwa5nLMTz9YnwdLE5m+Bfctzqbj09vpSJo2DyPHCyEXScFUuizWBbfofxB/pF+OnZXjU3pJxtm/w==" + }, "@pythnetwork/pyth-evm-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-evm-js/-/pyth-evm-js-1.1.0.tgz", - "integrity": "sha512-cfxzJ6u6THJ4pyAlfdJ4pw1MbXPAaRqTPPzpjopiuUmme8M3m7HK7wKP9TIxHEnGyCqTw3MnWG1r+TS2zbO13g==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-evm-js/-/pyth-evm-js-1.10.0.tgz", + "integrity": "sha512-trop6n+JOR2AAjDKskI0FU/XWZ/b8DD/v5RsARTlKTfFmBKu/n4Km8LiXH8Llq3vsl4xUQ7/y+locj0defQ0JA==", "requires": { - "@pythnetwork/pyth-common-js": "^1.2.0", + "@pythnetwork/price-service-client": "*", "buffer": "^6.0.3" }, "dependencies": { @@ -63973,11 +64329,6 @@ } } }, - "@pythnetwork/pyth-sdk-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-js/-/pyth-sdk-js-1.2.0.tgz", - "integrity": "sha512-grh6YCkp/nH73ACNu+Mew64lLVgz6egVBJm8JvdNkRggWkUn1PE4ZvV/6ceTIui5OhI369qzMCkldiAlIMBjnQ==" - }, "@rainbow-me/rainbowkit": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@rainbow-me/rainbowkit/-/rainbowkit-0.8.1.tgz", @@ -64030,53 +64381,53 @@ } }, "@react-spring/animated": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.6.1.tgz", - "integrity": "sha512-ls/rJBrAqiAYozjLo5EPPLLOb1LM0lNVQcXODTC1SMtS6DbuBCPaKco5svFUQFMP2dso3O+qcC4k9FsKc0KxMQ==", + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.1.tgz", + "integrity": "sha512-EX5KAD9y7sD43TnLeTNG1MgUVpuRO1YaSJRPawHNRgUWYfILge3s85anny4S4eTJGpdp5OoFV2kx9fsfeo0qsw==", "requires": { - "@react-spring/shared": "~9.6.1", - "@react-spring/types": "~9.6.1" + "@react-spring/shared": "~9.7.1", + "@react-spring/types": "~9.7.1" } }, "@react-spring/core": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.6.1.tgz", - "integrity": "sha512-3HAAinAyCPessyQNNXe5W0OHzRfa8Yo5P748paPcmMowZ/4sMfaZ2ZB6e5x5khQI8NusOHj8nquoutd6FRY5WQ==", + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.1.tgz", + "integrity": "sha512-8K9/FaRn5VvMa24mbwYxwkALnAAyMRdmQXrARZLcBW2vxLJ6uw9Cy3d06Z8M12kEqF2bDlccaCSDsn2bSz+Q4A==", "requires": { - "@react-spring/animated": "~9.6.1", - "@react-spring/rafz": "~9.6.1", - "@react-spring/shared": "~9.6.1", - "@react-spring/types": "~9.6.1" + "@react-spring/animated": "~9.7.1", + "@react-spring/rafz": "~9.7.1", + "@react-spring/shared": "~9.7.1", + "@react-spring/types": "~9.7.1" } }, "@react-spring/rafz": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.6.1.tgz", - "integrity": "sha512-v6qbgNRpztJFFfSE3e2W1Uz+g8KnIBs6SmzCzcVVF61GdGfGOuBrbjIcp+nUz301awVmREKi4eMQb2Ab2gGgyQ==" + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.1.tgz", + "integrity": "sha512-JSsrRfbEJvuE3w/uvU3mCTuWwpQcBXkwoW14lBgzK9XJhuxmscGo59AgJUpFkGOiGAVXFBGB+nEXtSinFsopgw==" }, "@react-spring/shared": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.6.1.tgz", - "integrity": "sha512-PBFBXabxFEuF8enNLkVqMC9h5uLRBo6GQhRMQT/nRTnemVENimgRd+0ZT4yFnAQ0AxWNiJfX3qux+bW2LbG6Bw==", + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.1.tgz", + "integrity": "sha512-R2kZ+VOO6IBeIAYTIA3C1XZ0ZVg/dDP5FKtWaY8k5akMer9iqf5H9BU0jyt3Qtxn0qQY7whQdf6MTcWtKeaawg==", "requires": { - "@react-spring/rafz": "~9.6.1", - "@react-spring/types": "~9.6.1" + "@react-spring/rafz": "~9.7.1", + "@react-spring/types": "~9.7.1" } }, "@react-spring/types": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.6.1.tgz", - "integrity": "sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q==" + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.1.tgz", + "integrity": "sha512-yBcyfKUeZv9wf/ZFrQszvhSPuDx6Py6yMJzpMnS+zxcZmhXPeOCKZSHwqrUz1WxvuRckUhlgb7eNI/x5e1e8CA==" }, "@react-spring/web": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.6.1.tgz", - "integrity": "sha512-X2zR6q2Z+FjsWfGAmAXlQaoUHbPmfuCaXpuM6TcwXPpLE1ZD4A1eys/wpXboFQmDkjnrlTmKvpVna1MjWpZ5Hw==", + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.1.tgz", + "integrity": "sha512-6uUE5MyKqdrJnIJqlDN/AXf3i8PjOQzUuT26nkpsYxUGOk7c+vZVPcfrExLSoKzTb9kF0i66DcqzO5fXz/Z1AA==", "requires": { - "@react-spring/animated": "~9.6.1", - "@react-spring/core": "~9.6.1", - "@react-spring/shared": "~9.6.1", - "@react-spring/types": "~9.6.1" + "@react-spring/animated": "~9.7.1", + "@react-spring/core": "~9.7.1", + "@react-spring/shared": "~9.7.1", + "@react-spring/types": "~9.7.1" } }, "@reduxjs/toolkit": { @@ -64091,14 +64442,14 @@ } }, "@sentry/browser": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.37.0.tgz", - "integrity": "sha512-EMlSo4Ebtryd5id2nC31dwcLigwYPWjrAYt36vUJ/L47oXetaH4dndK6wqYyxR2sl8uP2GlsQUnWpGLHKyG3ww==", - "requires": { - "@sentry/core": "7.37.0", - "@sentry/replay": "7.37.0", - "@sentry/types": "7.37.0", - "@sentry/utils": "7.37.0", + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.43.0.tgz", + "integrity": "sha512-NlRkBYKb9o5IQdGY8Ktps19Hz9RdSuqS1tlLC7Sjr+MqZqSHmhKq8MWJKciRynxBeMbeGt0smExi9BqpVQdCEg==", + "requires": { + "@sentry/core": "7.43.0", + "@sentry/replay": "7.43.0", + "@sentry/types": "7.43.0", + "@sentry/utils": "7.43.0", "tslib": "^1.9.3" }, "dependencies": { @@ -64110,12 +64461,12 @@ } }, "@sentry/core": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.37.0.tgz", - "integrity": "sha512-2M6aZKIG/1HgfE0hobQ9tKSo6ZsyBrSQqjtQhMVFwVzZJyFw3m1AqcrB+f0myi+1ay2MMPbJ+HhYtBPR3e4EvA==", + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.43.0.tgz", + "integrity": "sha512-zvMZgEi7ptLBwDnd+xR/u4zdSe5UzS4S3ZhoemdQrn1PxsaVySD/ptyzLoGSZEABqlRxGHnQrZ78MU1hUDvKuQ==", "requires": { - "@sentry/types": "7.37.0", - "@sentry/utils": "7.37.0", + "@sentry/types": "7.43.0", + "@sentry/utils": "7.43.0", "tslib": "^1.9.3" }, "dependencies": { @@ -64127,23 +64478,23 @@ } }, "@sentry/replay": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.37.0.tgz", - "integrity": "sha512-uGqPjEz3dprahRNslK35tR2N5RGULMH5uL/1InU65O5XUgq/wTyQ7ZH0qy743J8U6dBo/2n7V/RQdB9lA2sLBw==", + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.43.0.tgz", + "integrity": "sha512-2dGJS6p8uG1JZ7x/A3FyqnILTkXarbvfR+o1lC7z9lu34Wx0ZBeU2in/S2YHNGAE6XvfsePq3ya/s7LaNkk4qQ==", "requires": { - "@sentry/core": "7.37.0", - "@sentry/types": "7.37.0", - "@sentry/utils": "7.37.0" + "@sentry/core": "7.43.0", + "@sentry/types": "7.43.0", + "@sentry/utils": "7.43.0" } }, "@sentry/tracing": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.37.0.tgz", - "integrity": "sha512-DvFEwsXNsroVPNFOAblKwzKoO75dLhYw0XVmm+OlXTTQriJG5YkzcqazJ9pJ0l+f9ttswElGr3gLHMn797vsMA==", + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.43.0.tgz", + "integrity": "sha512-Mld2AyV8xYnRLYbDWvDy8PlGcln3h5JsUx6ScQGOxnFTmCQR50Tldtzq50VDs2fv6xH0+YrL/UIyjxCDc7EXzQ==", "requires": { - "@sentry/core": "7.37.0", - "@sentry/types": "7.37.0", - "@sentry/utils": "7.37.0", + "@sentry/core": "7.43.0", + "@sentry/types": "7.43.0", + "@sentry/utils": "7.43.0", "tslib": "^1.9.3" }, "dependencies": { @@ -64155,16 +64506,16 @@ } }, "@sentry/types": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.37.0.tgz", - "integrity": "sha512-p8iw5oGvWLIk7osMgXhxshUpebJD0riiuT3ihBP0DV+Gs8r0qdQ5gtcStl7Cn0D4013p4j/f3T5q85Z9ENE6fA==" + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.43.0.tgz", + "integrity": "sha512-5XxCWqYWJNoS+P6Ie2ZpUDxLRCt7FTEzmlQkCdjW6MFWOX26hAbF/wEuOTYAFKZXMIXOz0Egofik1e8v1Cg6/A==" }, "@sentry/utils": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.37.0.tgz", - "integrity": "sha512-CN86EKQ07+SgqfgGehMJsgrCEjc0sl1YDcj2xf9dA0Bn3ma2MTDkCyutxVcRfc2IVWfqAN1rn/L8/BH2v2+eqA==", + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.43.0.tgz", + "integrity": "sha512-f78YfMLcgNU7+suyWFCuQhQlneXXMS+egb0EFZh7iU7kANUPRX5T4b+0C+fwaPm5gA6XfGYskr4ZnzQJLOlSqg==", "requires": { - "@sentry/types": "7.37.0", + "@sentry/types": "7.43.0", "tslib": "^1.9.3" }, "dependencies": { @@ -64227,9 +64578,9 @@ } }, "@socket.tech/ll-core": { - "version": "0.1.26", - "resolved": "https://registry.npmjs.org/@socket.tech/ll-core/-/ll-core-0.1.26.tgz", - "integrity": "sha512-TeHS1ZeGAg73xqM25/gfguM7A8fv1BRMoYha2qHBpApAenl5TH0hSfPe0yBNg/ASZ7waeXNzGUConj/RA/OPlg==" + "version": "0.1.29", + "resolved": "https://registry.npmjs.org/@socket.tech/ll-core/-/ll-core-0.1.29.tgz", + "integrity": "sha512-Tt3NenGOPvifyOKBkyCN3NdxI2x6hSm2PaNY+JOrBMLfBaxolEkvamgtISst+pfvvo5WDQKI/7VZf7IOrdbAqg==" }, "@socket.tech/plugin": { "version": "1.0.3", @@ -64247,9 +64598,9 @@ } }, "@socket.tech/socket-v2-sdk": { - "version": "1.21.5", - "resolved": "https://registry.npmjs.org/@socket.tech/socket-v2-sdk/-/socket-v2-sdk-1.21.5.tgz", - "integrity": "sha512-ufYyJSN9C32G1I2KB7srczgwXBPyZJ42BAmjblMHrOosDR9XynQ3tKu/inKxOSV9jG31bH0zp3EOBssokVWmoA==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/@socket.tech/socket-v2-sdk/-/socket-v2-sdk-1.21.6.tgz", + "integrity": "sha512-tzx6Be1Nt26j+JPndj618LjUcJItfnaA004k1fVpSHMg8QalJs6PxbAUflDQuqccQT4VuMXwwuOVJWSsb16pVw==", "requires": { "@socket.tech/ll-core": "^0.1.14", "axios": "^0.27.2", @@ -75276,6 +75627,60 @@ "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", "dev": true }, + "@types/d3-array": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.4.tgz", + "integrity": "sha512-nwvEkG9vYOc0Ic7G7kwgviY4AQlTfYGIZ0fqB7CQHXGyYM6nO7kJh5EguSNA3jfh4rq7Sb7eMVq8isuvg2/miQ==" + }, + "@types/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==" + }, + "@types/d3-ease": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.0.tgz", + "integrity": "sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==" + }, + "@types/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==", + "requires": { + "@types/d3-color": "*" + } + }, + "@types/d3-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.0.tgz", + "integrity": "sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==" + }, + "@types/d3-scale": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.3.tgz", + "integrity": "sha512-PATBiMCpvHJSMtZAMEhc2WyL+hnzarKzI6wAHYjhsonjWJYGq5BXTzQjv4l8m2jO183/4wZ90rKvSeT7o72xNQ==", + "requires": { + "@types/d3-time": "*" + } + }, + "@types/d3-shape": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.1.tgz", + "integrity": "sha512-6Uh86YFF7LGg4PQkuO2oG6EMBRLuW9cbavUW46zkIO5kuS2PfTqo2o9SkgtQzguBHbLgNnU90UNsITpsX1My+A==", + "requires": { + "@types/d3-path": "*" + } + }, + "@types/d3-time": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.0.tgz", + "integrity": "sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==" + }, + "@types/d3-timer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.0.tgz", + "integrity": "sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==" + }, "@types/date-fns": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@types/date-fns/-/date-fns-2.6.0.tgz", @@ -82639,6 +83044,11 @@ "source-map": "^0.6.1" } }, + "css-unit-converter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", + "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==" + }, "css-vendor": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", @@ -82883,6 +83293,83 @@ "type": "^1.0.1" } }, + "d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==", + "requires": { + "internmap": "1 - 2" + } + }, + "d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==" + }, + "d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==" + }, + "d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==" + }, + "d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "requires": { + "d3-color": "1 - 3" + } + }, + "d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==" + }, + "d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "requires": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + } + }, + "d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "requires": { + "d3-path": "^3.1.0" + } + }, + "d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "requires": { + "d3-array": "2 - 3" + } + }, + "d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "requires": { + "d3-time": "1 - 3" + } + }, + "d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==" + }, "damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -82959,6 +83446,11 @@ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.2.tgz", "integrity": "sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==" }, + "decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + }, "decode-uri-component": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", @@ -86150,9 +86642,9 @@ } }, "fancy-canvas": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/fancy-canvas/-/fancy-canvas-0.2.2.tgz", - "integrity": "sha512-50qi8xA0QkHbjmb8h7XQ6k2fvD7y/yMfiUw9YTarJ7rWrq6o5/3CCXPouYk+XSLASvvxtjyiQLRBFt3qkE3oyA==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fancy-canvas/-/fancy-canvas-2.1.0.tgz", + "integrity": "sha512-nifxXJ95JNLFR2NgRV4/MxVP45G9909wJTEKz5fg/TZS20JJZA6hfgRVh/bC9bwl2zBtBNcYPjiBE4njQHVBwQ==" }, "fast-check": { "version": "3.1.1", @@ -86175,6 +86667,11 @@ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "dev": true }, + "fast-equals": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz", + "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==" + }, "fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", @@ -88843,6 +89340,11 @@ "side-channel": "^1.0.4" } }, + "internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" + }, "interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", @@ -92888,11 +93390,11 @@ } }, "lightweight-charts": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/lightweight-charts/-/lightweight-charts-3.8.0.tgz", - "integrity": "sha512-7yFGnYuE1RjRJG9RwUTBz5wvF1QtjBOSW4FFlikr8Dh+/TDNt4ci+HsWSYmStgQUpawpvkCJ3j5/W25GppGj9Q==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lightweight-charts/-/lightweight-charts-4.0.1.tgz", + "integrity": "sha512-p+j6w41PVzf9Vn7IrmpmCJacunpN0kKsl0IZoxMOySSkDcSagZ7Is9pb6pclIfN/usHdta0aYm9FktkYpAQe0g==", "requires": { - "fancy-canvas": "0.2.2" + "fancy-canvas": "2.1.0" } }, "lilconfig": { @@ -97206,6 +97708,11 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, "react-query": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.35.0.tgz", @@ -97256,6 +97763,14 @@ "tslib": "^2.0.0" } }, + "react-resize-detector": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-8.0.4.tgz", + "integrity": "sha512-ln9pMAob8y8mc9UI4aZuuWFiyMqBjnTs/sxe9Vs9dPXUjwCTeKK1FP8I75ufnb/2mEEZXG6wOo/fjMcBRRuAXw==", + "requires": { + "lodash": "^4.17.21" + } + }, "react-rnd": { "version": "10.3.7", "resolved": "https://registry.npmjs.org/react-rnd/-/react-rnd-10.3.7.tgz", @@ -97309,6 +97824,36 @@ "resize-observer-polyfill": "^1.5.0" } }, + "react-smooth": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-2.0.2.tgz", + "integrity": "sha512-pgqSp1q8rAGtF1bXQE0m3CHGLNfZZh5oA5o1tsPLXRHnKtkujMIJ8Ws5nO1mTySZf1c4vgwlEk+pHi3Ln6eYLw==", + "requires": { + "fast-equals": "^4.0.3", + "react-transition-group": "2.9.0" + }, + "dependencies": { + "dom-helpers": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", + "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", + "requires": { + "@babel/runtime": "^7.1.2" + } + }, + "react-transition-group": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", + "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", + "requires": { + "dom-helpers": "^3.4.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2", + "react-lifecycles-compat": "^3.0.4" + } + } + } + }, "react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -97500,6 +98045,37 @@ "picomatch": "^2.2.1" } }, + "recharts": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.5.0.tgz", + "integrity": "sha512-0EQYz3iA18r1Uq8VqGZ4dABW52AKBnio37kJgnztIqprELJXpOEsa0SzkqU1vjAhpCXCv52Dx1hiL9119xsqsQ==", + "requires": { + "classnames": "^2.2.5", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.19", + "react-is": "^16.10.2", + "react-resize-detector": "^8.0.4", + "react-smooth": "^2.0.2", + "recharts-scale": "^0.4.4", + "reduce-css-calc": "^2.1.8", + "victory-vendor": "^36.6.8" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, + "recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "requires": { + "decimal.js-light": "^2.4.1" + } + }, "redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -97510,6 +98086,22 @@ "strip-indent": "^3.0.0" } }, + "reduce-css-calc": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz", + "integrity": "sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==", + "requires": { + "css-unit-converter": "^1.1.1", + "postcss-value-parser": "^3.3.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + } + } + }, "reduce-flatten": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", @@ -101787,9 +102379,9 @@ } }, "typechain": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.1.0.tgz", - "integrity": "sha512-5jToLgKTjHdI1VKqs/K8BLYy42Sr3o8bV5ojh4MnR9ExHO83cyyUdw+7+vMJCpKXUiVUvARM4qmHTFuyaCMAZQ==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.1.1.tgz", + "integrity": "sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ==", "dev": true, "requires": { "@types/prettier": "^2.1.1", @@ -102633,6 +103225,27 @@ "unist-util-stringify-position": "^2.0.0" } }, + "victory-vendor": { + "version": "36.6.8", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.6.8.tgz", + "integrity": "sha512-H3kyQ+2zgjMPvbPqAl7Vwm2FD5dU7/4bCTQakFQnpIsfDljeOMDojRsrmJfwh4oAlNnWhpAf+mbAoLh8u7dwyQ==", + "requires": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", diff --git a/package.json b/package.json index 74bcfb05ac..ec422132ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kwenta", - "version": "6.2.3", + "version": "6.2.5", "scripts": { "dev": "next", "build": "next build", @@ -32,13 +32,13 @@ "@kwenta/synthswap": "^1.0.3", "@material-ui/core": "^4.12.3", "@metamask/detect-provider": "2.0.0", - "@pythnetwork/pyth-evm-js": "^1.0.1", + "@pythnetwork/pyth-evm-js": "1.10.0", "@rainbow-me/rainbowkit": "0.8.1", "@reach/dialog": "0.15.0", "@reduxjs/toolkit": "^1.8.5", - "@socket.tech/plugin": "^1.0.3", - "@sentry/browser": "^7.37.0", - "@sentry/tracing": "^7.37.0", + "@sentry/browser": "7.43.0", + "@sentry/tracing": "7.43.0", + "@socket.tech/plugin": "1.0.3", "@synthetixio/optimism-networks": "2.74.6", "@synthetixio/providers": "2.74.10", "@synthetixio/transaction-notifier": "2.74.12", @@ -59,7 +59,7 @@ "imagemin-mozjpeg": "^10.0.0", "intercept-stdout": "^0.1.2", "isomorphic-dompurify": "^0.26.0", - "lightweight-charts": "^3.8.0", + "lightweight-charts": "4.0.1", "lodash": "4.17.21", "moment-business-time": "2.0.0", "next": "12.2.4", @@ -80,6 +80,7 @@ "react-slick": "0.29.0", "react-table": "7.7.0", "react-toastify": "^9.0.4", + "recharts": "^2.5.0", "redux-logger": "^3.0.6", "redux-persist": "^6.0.0", "slick-carousel": "1.8.1", @@ -90,7 +91,7 @@ }, "devDependencies": { "@microsoft/eslint-formatter-sarif": "2.1.7", - "@next/eslint-plugin-next": "^12.1.6", + "@next/eslint-plugin-next": "12.3.4", "@storybook/addon-actions": "^6.4.13", "@storybook/addon-essentials": "6.5.13", "@storybook/addon-links": "^6.4.13", @@ -149,7 +150,7 @@ "postcss": "^8.4.20", "prettier": "2.0.5", "react-test-renderer": "17.0.1", - "typechain": "^8.1.0", + "typechain": "8.1.1", "typescript": "4.7.4", "url-loader": "4.1.0", "webp-loader": "0.6.0" diff --git a/queries/futures/useGetFuturesTrades.ts b/queries/futures/useGetFuturesTrades.ts index d1d64b89fa..04be7818d6 100644 --- a/queries/futures/useGetFuturesTrades.ts +++ b/queries/futures/useGetFuturesTrades.ts @@ -72,14 +72,14 @@ const useGetFuturesTrades = ( return notNill(lastPage) && lastPage?.length > 0 ? { minTs: 0, - maxTs: lastPage[lastPage.length - 1].timestamp.toNumber(), + maxTs: lastPage[lastPage.length - 1].timestamp, } : null; }, getPreviousPageParam: (firstPage) => { return notNill(firstPage) && firstPage?.length > 0 ? { - minTs: firstPage[0].timestamp.toNumber(), + minTs: firstPage[0].timestamp, maxTs: MAX_TIMESTAMP, } : null; diff --git a/sdk/constants/period.ts b/sdk/constants/period.ts index 9e1c88e108..61db514a48 100644 --- a/sdk/constants/period.ts +++ b/sdk/constants/period.ts @@ -7,6 +7,15 @@ export enum Period { ONE_YEAR = 'ONE_YEAR', } +export const PERIOD_DISPLAY: Record = { + ONE_HOUR: '1H', + FOUR_HOURS: '4H', + ONE_DAY: '1D', + ONE_WEEK: '1W', + ONE_MONTH: '1M', + ONE_YEAR: '1Y', +}; + export const PERIOD_IN_HOURS: Record = { ONE_HOUR: 1, FOUR_HOURS: 4, @@ -26,3 +35,5 @@ export const PERIOD_IN_SECONDS: Record = { }; export const SECONDS_PER_DAY = 24 * 60 * 60; + +export const MILLISECONDS_PER_DAY = SECONDS_PER_DAY * 1000; diff --git a/sdk/types/futures.ts b/sdk/types/futures.ts index 3a9461f2d9..54409ad0d9 100644 --- a/sdk/types/futures.ts +++ b/sdk/types/futures.ts @@ -345,12 +345,14 @@ export type CrossMarginOrderType = 'market' | 'stop_market' | 'limit'; export type FuturesOrderType = IsolatedMarginOrderType | CrossMarginOrderType; export type FuturesTrade = { + account: string; + margin: T; size: T; - asset: string; + asset: FuturesMarketAsset; price: T; txnHash: string; - timestamp: T; - positionId?: string; + timestamp: number; + positionId: string; positionSize: T; positionClosed: boolean; side: PositionSide; diff --git a/sdk/utils/futures.ts b/sdk/utils/futures.ts index f7657a00df..6cf5a2590f 100644 --- a/sdk/utils/futures.ts +++ b/sdk/utils/futures.ts @@ -505,9 +505,12 @@ export const mapTrades = (futuresTrades: FuturesTradeResult[]): FuturesTrade[] = ({ id, timestamp, + account, + margin, size, price, asset, + positionId, positionSize, positionClosed, pnl, @@ -517,12 +520,15 @@ export const mapTrades = (futuresTrades: FuturesTradeResult[]): FuturesTrade[] = accountType, }) => { return { - asset, + asset: parseBytes32String(asset) as FuturesMarketAsset, + account, accountType, + margin: new Wei(margin, 18, true), size: new Wei(size, 18, true), price: new Wei(price, 18, true), txnHash: id.split('-')[0].toString(), - timestamp: timestamp, + timestamp: timestamp.toNumber(), + positionId, positionSize: new Wei(positionSize, 18, true), positionClosed, side: size.gt(0) ? PositionSide.LONG : PositionSide.SHORT, diff --git a/sections/dashboard/FuturesHistoryTable/FuturesHistoryTable.tsx b/sections/dashboard/FuturesHistoryTable/FuturesHistoryTable.tsx index 06ef231312..9e6a71de0b 100644 --- a/sections/dashboard/FuturesHistoryTable/FuturesHistoryTable.tsx +++ b/sections/dashboard/FuturesHistoryTable/FuturesHistoryTable.tsx @@ -1,5 +1,4 @@ import { wei } from '@synthetixio/wei'; -import { utils as ethersUtils } from 'ethers'; import * as _ from 'lodash/fp'; import Link from 'next/link'; import { FC, useMemo, ReactElement, useState } from 'react'; @@ -22,16 +21,13 @@ import { FuturesMarketAsset, FuturesTrade } from 'sdk/types/futures'; import TradeDrawer from 'sections/futures/MobileTrade/drawers/TradeDrawer'; import PositionType from 'sections/futures/PositionType'; import { TradeStatus } from 'sections/futures/types'; -import { fetchAllTradesForAccount } from 'state/futures/actions'; import { selectAllUsersTrades, - selectFuturesAccount, selectFuturesType, selectQueryStatuses, } from 'state/futures/selectors'; -import { useAppSelector, useFetchAction } from 'state/hooks'; +import { useAppSelector } from 'state/hooks'; import { FetchStatus } from 'state/types'; -import { selectNetwork } from 'state/wallet/selectors'; import { formatShortDateWithoutYear } from 'utils/formatters/date'; import { formatCryptoCurrency, formatDollars } from 'utils/formatters/number'; import { getDisplayAsset, getMarketName, MarketKeyByAsset } from 'utils/futures'; @@ -49,20 +45,12 @@ const FuturesHistoryTable: FC = () => { const { switchToL2 } = useNetworkSwitcher(); const accountType = useAppSelector(selectFuturesType); - const account = useAppSelector(selectFuturesAccount); - const network = useAppSelector(selectNetwork); const trades = useAppSelector(selectAllUsersTrades); const { trades: tradesQueryStatus } = useAppSelector(selectQueryStatuses); - useFetchAction(fetchAllTradesForAccount, { - dependencies: [account, network], - disabled: !account, - }); - const mappedHistoricalTrades = useMemo( () => trades.map((trade) => { - const parsedAsset = ethersUtils.parseBytes32String(trade.asset) as FuturesMarketAsset; const pnl = trade.pnl.div(ETH_UNIT); const feesPaid = trade.feesPaid.div(ETH_UNIT); const netPnl = pnl.sub(feesPaid); @@ -71,13 +59,12 @@ const FuturesHistoryTable: FC = () => { pnl, feesPaid, netPnl, - asset: parsedAsset, - displayAsset: getDisplayAsset(parsedAsset), - market: getMarketName(parsedAsset), + displayAsset: getDisplayAsset(trade.asset), + market: getMarketName(trade.asset), price: Number(trade.price?.div(ETH_UNIT)), size: Number(trade.size.div(ETH_UNIT).abs()), - timestamp: Number(trade.timestamp.mul(1000)), - date: formatShortDateWithoutYear(new Date(trade.timestamp.mul(1000).toNumber())), + timestamp: trade.timestamp * 1000, + date: formatShortDateWithoutYear(new Date(trade.timestamp * 1000)), id: trade.txnHash, status: trade.positionClosed ? TradeStatus.CLOSED : TradeStatus.OPEN, }; @@ -92,6 +79,7 @@ const FuturesHistoryTable: FC = () => { = ({ accessor: 'leverage', Cell: (cellProps: CellProps) => { return ( - {formatNumber(cellProps.row.original.position.leverage ?? 0)}x + {formatNumber(cellProps.row.original.position.leverage ?? 0)}x ); }, width: 90, diff --git a/sections/dashboard/MobileDashboard/MobileDashboard.tsx b/sections/dashboard/MobileDashboard/MobileDashboard.tsx index 7a9be64e6e..dd6c302a89 100644 --- a/sections/dashboard/MobileDashboard/MobileDashboard.tsx +++ b/sections/dashboard/MobileDashboard/MobileDashboard.tsx @@ -17,7 +17,7 @@ const MobileDashboard: FC = ({ exchangeTokens }) => { return (
- + = ({ exchangeTokenBalances }) => { +const Portfolio: FC = () => { const { t } = useTranslation(); return ( @@ -20,7 +15,7 @@ const Portfolio: React.FC = ({ exchangeTokenBalances }) => { {t('dashboard.overview.mobile.portfolio')}
- + ); }; diff --git a/sections/dashboard/Overview/Overview.tsx b/sections/dashboard/Overview/Overview.tsx index 892e01728c..6789cd5729 100644 --- a/sections/dashboard/Overview/Overview.tsx +++ b/sections/dashboard/Overview/Overview.tsx @@ -167,12 +167,7 @@ const Overview: FC = () => { - initial.add(usdBalance), - zeroBN - )} - /> + {POSITIONS_TABS.map(({ name, label, badge, ...rest }) => ( diff --git a/sections/dashboard/PortfolioChart/PortfolioChart.tsx b/sections/dashboard/PortfolioChart/PortfolioChart.tsx index 4841310f87..c19a5f327a 100644 --- a/sections/dashboard/PortfolioChart/PortfolioChart.tsx +++ b/sections/dashboard/PortfolioChart/PortfolioChart.tsx @@ -1,73 +1,305 @@ -import Wei from '@synthetixio/wei'; -import { FC, useMemo } from 'react'; -import styled from 'styled-components'; +import Link from 'next/link'; +import { FC, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { LineChart, Line, XAxis, Tooltip, ResponsiveContainer, Legend } from 'recharts'; +import styled, { useTheme } from 'styled-components'; +import Logo from 'assets/svg/brand/logo-only.svg'; +import Button from 'components/Button'; import Currency from 'components/Currency'; import { MobileHiddenView, MobileOnlyView } from 'components/Media'; -import * as Text from 'components/Text'; -import { selectBalances } from 'state/balances/selectors'; -import { selectFuturesPortfolio } from 'state/futures/selectors'; +import { TableNoResults } from 'components/Table'; +import { Body, NumericValue, Heading } from 'components/Text'; +import { DEFAULT_FUTURES_MARGIN_TYPE } from 'constants/defaults'; +import ROUTES from 'constants/routes'; +import { Period } from 'sdk/constants/period'; +import { + selectBuyingPower, + selectFuturesPortfolio, + selectPortfolioChartData, + selectSelectedPortfolioTimeframe, + selectTotalUnrealizedPnl, +} from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; +import { formatChartDate, formatChartTime, formatShortDateWithTime } from 'utils/formatters/date'; +import { formatDollars, formatPercent, zeroBN } from 'utils/formatters/number'; -type PortfolioChartProps = { - exchangeTokenBalances: Wei; +import { Timeframe } from './Timeframe'; + +type PriceChartProps = { + setHoverValue: (data: number | null) => void; + setHoverTitle: (data: string | null) => void; +}; + +const ChartCTA = () => { + const { t } = useTranslation(); + return ( + + + {t('dashboard.overview.portfolio-chart.welcome')} + {t('dashboard.overview.portfolio-chart.hero')} + + + + + ); }; -const PortfolioChart: FC = ({ exchangeTokenBalances }) => { +const PriceChart: FC = ({ setHoverValue, setHoverTitle }) => { + const theme = useTheme(); + const portfolioTimeframe = useAppSelector(selectSelectedPortfolioTimeframe); + const portfolioData = useAppSelector(selectPortfolioChartData); + + const lineColor = useMemo(() => { + const isNegative = + portfolioData.length > 2 + ? portfolioData[portfolioData.length - 1].total - portfolioData[0].total < 0 + : false; + return isNegative ? theme.colors.selectedTheme.red : theme.colors.selectedTheme.green; + }, [portfolioData, theme]); + + return ( + + { + setHoverValue(null); + setHoverTitle(null); + }} + onMouseMove={(payload) => { + if (payload.activePayload && payload.activePayload.length > 0) { + const newTotal = payload.activePayload[0].payload?.total; + + const formattedDate = formatShortDateWithTime( + payload.activePayload[0].payload?.timestamp + ); + if (newTotal) { + setHoverValue(newTotal); + setHoverTitle(formattedDate); + } else { + setHoverValue(null); + setHoverTitle(null); + } + } else { + setHoverValue(null); + setHoverTitle(null); + } + }} + > + + } /> + (value === 'total' ? 'Isolated Margin' : value)} + /> + + + + ); +}; + +const PortfolioChart: FC = () => { + const { t } = useTranslation(); const portfolio = useAppSelector(selectFuturesPortfolio); - const balances = useAppSelector(selectBalances); + const portfolioData = useAppSelector(selectPortfolioChartData); + const buyingPower = useAppSelector(selectBuyingPower); + const upnl = useAppSelector(selectTotalUnrealizedPnl); + + const [hoverValue, setHoverValue] = useState(null); + const [hoverTitle, setHoverTitle] = useState(null); // TODO: Add back cross margin when relevant - const total = useMemo( - () => portfolio.isolatedMarginFutures.add(balances.totalUSDBalance).add(exchangeTokenBalances), - [portfolio.isolatedMarginFutures, balances.totalUSDBalance, exchangeTokenBalances] - ); + const total = useMemo(() => portfolio.isolatedMarginFutures, [portfolio.isolatedMarginFutures]); + + const changeValue = useMemo(() => { + if (portfolioData.length < 2) { + return { + value: null, + text: '', + }; + } else { + const value = + (hoverValue ?? portfolioData[portfolioData.length - 1].total) - portfolioData[0].total; + const changeValue = portfolioData[0].total > 0 ? value / portfolioData[0].total : 0; + const text = `${value >= 0 ? '+' : ''}${formatDollars(value, { + suggestDecimals: true, + })} (${formatPercent(changeValue)})`; + return { + value, + text, + }; + } + }, [portfolioData, hoverValue]); return ( <> - - Portfolio Value - - + + + + {hoverTitle ? hoverTitle : t('dashboard.overview.portfolio-chart.portfolio-value')} + + + + {changeValue.text}  + + + + {t('dashboard.overview.portfolio-chart.upnl')} + + {upnl.gt(zeroBN) ? '+' : ''} + {formatDollars(upnl, { suggestDecimals: true })} + + + + {t('dashboard.overview.portfolio-chart.buying-power')} + + {formatDollars(buyingPower, { suggestDecimals: true })} + + + {!!total && portfolioData.length >= 2 ? ( + + + + + + + + + ) : ( + + + + )} + - - + {!!total && portfolioData.length >= 2 ? ( + + + Portfolio Value + + + {changeValue.text}  + + + + + + + + + + + + ) : ( + + + + )} ); }; -const Chart = styled.div` - width: 100%; - border: ${(props) => props.theme.colors.selectedTheme.border}; - border-radius: 10px; - height: 200px; +const ChartContainer = styled.div<{ mobile?: boolean }>` + position: relative; + grid-row-end: span 3; + border-left: ${(props) => (props.mobile ? null : props.theme.colors.selectedTheme.border)}; + border-top: ${(props) => (props.mobile ? props.theme.colors.selectedTheme.border : null)}; + border-bottom: ${(props) => (props.mobile ? props.theme.colors.selectedTheme.border : null)}; + padding: 0 8px 0 8px; `; -const PortfolioTitle = styled(Text.Body).attrs({ weight: 'bold' })` +const TopBar = styled.div` + position: absolute; + top: 0; + right: 0; + z-index: 3; + display: flex; + flex-direction: row; + justify-content: end; + align-items: center; + padding: 8px 8px 0 0; +`; + +const StyledPriceChart = styled(PriceChart)``; + +const ChartOverlay = styled.div` + display: flex; + flex-direction: column; + justify-content: start; + gap: 8px; + padding: 16px; +`; + +const GridBox = styled.div` + display: flex; + flex-direction: column; + border-top: ${(props) => props.theme.colors.selectedTheme.border}; + padding: 16px; +`; + +const TimeframeOverlay = styled.div` + max-width: 192px; +`; + +const PortfolioTitle = styled(Body).attrs({ variant: 'bold' })` color: ${(props) => props.theme.colors.selectedTheme.gray}; font-size: 16px; - margin: 26px 0 10px 26px; + margin-bottom: 4px; `; const PortfolioText = styled(Currency.Price)` color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; font-family: ${(props) => props.theme.fonts.monoBold}; letter-spacing: -1.2px; - font-size: 27px; - margin-left: 26px; - margin-top: 0; - margin-bottom: 26px; + font-size: 20px; span { - line-height: 27px; + line-height: 23px; } `; -const MobileChartPlaceholder = styled.div` - border-bottom: ${(props) => props.theme.colors.selectedTheme.border}; +const MobileChartGrid = styled.div` + display: grid; + grid-template-rows: 1fr 5fr; + width: 100%; + border: ${(props) => props.theme.colors.selectedTheme.border}; + border-radius: 0px; + height: 360px; +`; + +const ChartGrid = styled.div` + display: grid; + grid-template-columns: 1fr 3fr; + grid-template-rows: 1fr 1fr 1fr; + grid-auto-flow: column; + width: 100%; + border: ${(props) => props.theme.colors.selectedTheme.border}; + border-radius: 8px; + height: 260px; +`; + +const CTAContainer = styled(TableNoResults)` + height: 100%; `; export default PortfolioChart; diff --git a/sections/dashboard/PortfolioChart/Timeframe.tsx b/sections/dashboard/PortfolioChart/Timeframe.tsx new file mode 100644 index 0000000000..d67b9fbd32 --- /dev/null +++ b/sections/dashboard/PortfolioChart/Timeframe.tsx @@ -0,0 +1,66 @@ +import { FC } from 'react'; +import styled from 'styled-components'; + +import { PERIOD_DISPLAY, Period } from 'sdk/constants/period'; +import { setSelectedPortfolioTimeframe } from 'state/futures/reducer'; +import { selectSelectedPortfolioTimeframe } from 'state/futures/selectors'; +import { useAppDispatch, useAppSelector } from 'state/hooks'; + +const Container = styled.div` + background-color: ${(props) => props.theme.colors.selectedTheme.button.fill}; + display: flex; + justify-content: center; + align-items: baseline; + padding: 3px 5px; + gap: 4px; + border-radius: 100px; +`; + +const StyledBtn = styled.div<{ isActive: boolean }>` + display: flex; + align-items: center; + justify-content: center; + width: 43px; + height: 19px; + border-radius: 100px; + background-color: ${(props) => + props.isActive ? props.theme.colors.selectedTheme.background : ''}; + color: ${(props) => + props.isActive + ? props.theme.colors.selectedTheme.text.value + : props.theme.colors.selectedTheme.gray2}; + font-family: ${(props) => props.theme.fonts.bold}; + font-size: 11px; + text-align: center; + + &:hover, + &:active { + color: ${(props) => props.theme.colors.selectedTheme.gray}; + cursor: pointer; + } + + &:before { + content: unset; + } +`; + +const TIMEFRAMES: Period[] = [Period.ONE_WEEK, Period.ONE_MONTH, Period.ONE_YEAR]; + +export const Timeframe: FC = () => { + const dispatch = useAppDispatch(); + const selectedTimeframe = useAppSelector(selectSelectedPortfolioTimeframe); + + return ( + + {TIMEFRAMES.map((timeframe) => ( + dispatch(setSelectedPortfolioTimeframe(timeframe))} + isActive={selectedTimeframe === timeframe} + > + {PERIOD_DISPLAY[timeframe]} + + ))} + + ); +}; diff --git a/sections/futures/MobileTrade/UserTabs/TradesTab.tsx b/sections/futures/MobileTrade/UserTabs/TradesTab.tsx index bd532131b4..f0948667f7 100644 --- a/sections/futures/MobileTrade/UserTabs/TradesTab.tsx +++ b/sections/futures/MobileTrade/UserTabs/TradesTab.tsx @@ -56,7 +56,7 @@ const TradesTab: React.FC = () => { market: getMarketName(parsedAsset), price: Number(trade.price?.div(ETH_UNIT)), size: Number(trade.size.div(ETH_UNIT).abs()), - timestamp: Number(trade.timestamp.mul(1000)), + timestamp: trade.timestamp * 1000, id: trade.txnHash, status: trade.positionClosed ? TradeStatus.CLOSED : TradeStatus.OPEN, }; diff --git a/sections/futures/MobileTrade/UserTabs/TransfersTab.tsx b/sections/futures/MobileTrade/UserTabs/TransfersTab.tsx index 628af852dc..3d5654afb0 100644 --- a/sections/futures/MobileTrade/UserTabs/TransfersTab.tsx +++ b/sections/futures/MobileTrade/UserTabs/TransfersTab.tsx @@ -6,14 +6,14 @@ import ColoredPrice from 'components/ColoredPrice'; import Table, { TableHeader, TableNoResults } from 'components/Table'; import { Body } from 'components/Text'; import { SectionHeader, SectionTitle } from 'sections/futures/mobile'; -import { selectMarginTransfers, selectQueryStatuses } from 'state/futures/selectors'; +import { selectMarketMarginTransfers, selectQueryStatuses } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; import { FetchStatus } from 'state/types'; import { timePresentation } from 'utils/formatters/date'; import { formatDollars } from 'utils/formatters/number'; const TransfersTab: React.FC = () => { - const marginTransfers = useAppSelector(selectMarginTransfers); + const marginTransfers = useAppSelector(selectMarketMarginTransfers); const { marginTransfers: { status: marginTransfersStatus }, } = useAppSelector(selectQueryStatuses); diff --git a/sections/futures/Trades/Trades.tsx b/sections/futures/Trades/Trades.tsx index 8c0c979bbc..8ee6f4ebce 100644 --- a/sections/futures/Trades/Trades.tsx +++ b/sections/futures/Trades/Trades.tsx @@ -50,7 +50,7 @@ const Trades: React.FC = memo(() => { netPnl, value: Number(trade?.price?.div(ETH_UNIT)), amount: Number(trade?.size.div(ETH_UNIT).abs()), - time: Number(trade?.timestamp.mul(1000)), + time: trade?.timestamp * 1000, id: trade?.txnHash, asset: marketAsset, type: trade?.orderType, diff --git a/sections/futures/Transfers/Transfers.tsx b/sections/futures/Transfers/Transfers.tsx index f9eb41e52f..313cf65830 100644 --- a/sections/futures/Transfers/Transfers.tsx +++ b/sections/futures/Transfers/Transfers.tsx @@ -8,7 +8,7 @@ import { Body } from 'components/Text'; import { blockExplorer } from 'containers/Connector/Connector'; import useIsL2 from 'hooks/useIsL2'; import useNetworkSwitcher from 'hooks/useNetworkSwitcher'; -import { selectMarginTransfers, selectQueryStatuses } from 'state/futures/selectors'; +import { selectMarketMarginTransfers, selectQueryStatuses } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; import { FetchStatus } from 'state/types'; import { ExternalLink } from 'styles/common'; @@ -21,7 +21,7 @@ const Transfers: FC = () => { const { switchToL2 } = useNetworkSwitcher(); const isL2 = useIsL2(); - const marginTransfers = useAppSelector(selectMarginTransfers); + const marginTransfers = useAppSelector(selectMarketMarginTransfers); const { marginTransfers: { status: marginTransfersStatus }, } = useAppSelector(selectQueryStatuses); diff --git a/state/constants.ts b/state/constants.ts index 92d9da371b..6427f2db32 100644 --- a/state/constants.ts +++ b/state/constants.ts @@ -18,6 +18,15 @@ export const ZERO_CM_FEES = { total: '0', }; +export const ZERO_STATE_ISOLATED_ACCOUNT = { + position: undefined, + trades: [], + marginTransfers: [], + positions: [], + openOrders: [], + positionHistory: [], +}; + export const ZERO_STATE_CM_ACCOUNT = { position: undefined, balanceInfo: { diff --git a/state/futures/actions.ts b/state/futures/actions.ts index eeec9593be..96630cddca 100644 --- a/state/futures/actions.ts +++ b/state/futures/actions.ts @@ -800,7 +800,7 @@ export const fetchAllTradesForAccount = createAsyncThunk< const account = selectFuturesAccount(getState()); const futuresSupported = selectFuturesSupportedNetwork(getState()); if (!futuresSupported || !wallet || !account) return; - const trades = await sdk.futures.getAllTrades(wallet, accountType); + const trades = await sdk.futures.getAllTrades(wallet, accountType, 10000); return { trades: serializeTrades(trades), networkId, account, accountType, wallet }; } catch (err) { notifyError('Failed to fetch futures trades', err); diff --git a/state/futures/hooks.ts b/state/futures/hooks.ts index 56e0712cba..e97ef0257a 100644 --- a/state/futures/hooks.ts +++ b/state/futures/hooks.ts @@ -12,6 +12,7 @@ import { fetchSharedFuturesData, fetchIsolatedOpenOrders, fetchMarginTransfers, + fetchAllTradesForAccount, } from './actions'; import { selectCrossMarginAccount, @@ -83,6 +84,15 @@ export const usePollDashboardFuturesData = () => { const networkSupportsCrossMargin = useAppSelector(selectFuturesSupportedNetwork); const selectedAccountType = useAppSelector(selectFuturesType); + useFetchAction(fetchMarginTransfers, { + dependencies: [networkId, wallet, selectedAccountType], + disabled: !wallet, + }); + useFetchAction(fetchAllTradesForAccount, { + dependencies: [networkId, wallet], + disabled: !wallet, + }); + useFetchAction(fetchCrossMarginAccount, { dependencies: [networkId, wallet], disabled: !wallet || !networkSupportsCrossMargin || selectedAccountType === 'isolated_margin', diff --git a/state/futures/reducer.ts b/state/futures/reducer.ts index 06fdfefa74..7825bc5dca 100644 --- a/state/futures/reducer.ts +++ b/state/futures/reducer.ts @@ -2,8 +2,10 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { DEFAULT_FUTURES_MARGIN_TYPE, DEFAULT_PRICE_IMPACT_DELTA } from 'constants/defaults'; import { ORDER_PREVIEW_ERRORS } from 'queries/futures/constants'; +import { Period } from 'sdk/constants/period'; import { NetworkId } from 'sdk/types/common'; import { + FuturesAccountType, FuturesMarket, FuturesMarketAsset, FuturesMarketKey, @@ -18,6 +20,7 @@ import { ZERO_CM_FEES, ZERO_STATE_CM_ACCOUNT, ZERO_STATE_CM_TRADE_INPUTS, + ZERO_STATE_ISOLATED_ACCOUNT, ZERO_STATE_TRADE_INPUTS, } from 'state/constants'; import { accountType } from 'state/helpers'; @@ -46,11 +49,14 @@ import { getClosePositionOrderFee, } from './actions'; import { + CrossMarginAccountData, CrossMarginState, CrossMarginTradeFees, CrossMarginTradeInputs, + FuturesAccountData, FuturesState, InputCurrencyDenomination, + IsolatedAccountData, IsolatedMarginTradeInputs, TransactionEstimationPayload, TransactionEstimations, @@ -64,6 +70,9 @@ export const FUTURES_INITIAL_STATE: FuturesState = { errors: {}, fundingRates: [], selectedInputDenomination: 'usd', + dashboard: { + selectedPortfolioTimeframe: Period.ONE_WEEK, + }, leaderboard: { selectedTrader: undefined, selectedTraderPositionHistory: DEFAULT_MAP_BY_NETWORK, @@ -265,6 +274,9 @@ const futuresSlice = createSlice({ setSelectedTrader: (state, action: PayloadAction) => { state.leaderboard.selectedTrader = action.payload; }, + setSelectedPortfolioTimeframe: (state, action: PayloadAction) => { + state.dashboard.selectedPortfolioTimeframe = action.payload; + }, }, extraReducers: (builder) => { // TODO: Separate markets by network @@ -329,7 +341,15 @@ const futuresSlice = createSlice({ futuresState.queryStatuses.marginTransfers = SUCCESS_STATUS; if (payload) { const { wallet, network, type, marginTransfers } = payload; - futuresState[accountType(type)].accounts[network][wallet].marginTransfers = marginTransfers; + futuresState[accountType(type)].accounts[network][wallet] = updateFuturesAccount( + futuresState, + type, + network, + wallet, + { + marginTransfers, + } + ); } }); builder.addCase(fetchMarginTransfers.rejected, (futuresState) => { @@ -365,10 +385,12 @@ const futuresSlice = createSlice({ }); builder.addCase(fetchIsolatedMarginPositions.fulfilled, (futuresState, { payload }) => { futuresState.queryStatuses.isolatedPositions = SUCCESS_STATUS; - if (payload && futuresState.isolatedMargin.accounts[payload.network]) { - futuresState.isolatedMargin.accounts[payload.network][payload.wallet] = { - ...futuresState.isolatedMargin.accounts[payload.network][payload.wallet], - positions: payload.positions, + if (payload) { + const { positions, wallet, network } = payload; + const account = futuresState.isolatedMargin.accounts[network][wallet]; + futuresState.isolatedMargin.accounts[network][wallet] = { + ...account, + positions, }; } }); @@ -381,15 +403,15 @@ const futuresSlice = createSlice({ // Refetch selected position builder.addCase(refetchPosition.fulfilled, (futuresState, { payload }) => { - if (payload && futuresState.isolatedMargin.accounts[payload.networkId]) { - const existingPositions = - futuresState.isolatedMargin.accounts[payload.networkId][payload.wallet]?.positions || []; - const index = existingPositions.findIndex( - (p) => p.marketKey === payload!.position.marketKey - ); - existingPositions[index] = payload.position; - futuresState.isolatedMargin.accounts[payload.networkId][payload.wallet] = { - ...futuresState.isolatedMargin.accounts[payload.networkId][payload.wallet], + if (payload) { + const { position, wallet, networkId } = payload; + const account = futuresState.isolatedMargin.accounts[networkId][wallet]; + + const existingPositions = account.positions ?? []; + const index = existingPositions.findIndex((p) => p.marketKey === position.marketKey); + existingPositions[index] = position; + futuresState.isolatedMargin.accounts[networkId][wallet] = { + ...account, positions: existingPositions, }; } @@ -421,15 +443,13 @@ const futuresSlice = createSlice({ }); builder.addCase(fetchIsolatedOpenOrders.fulfilled, (futuresState, { payload }) => { futuresState.queryStatuses.openOrders = SUCCESS_STATUS; - if (!payload) return; - const { wallet, orders } = payload; - if (wallet) { - if (futuresState.isolatedMargin.accounts[payload.networkId]) { - futuresState.isolatedMargin.accounts[payload.networkId][wallet] = { - ...futuresState.isolatedMargin.accounts[payload.networkId][wallet], - openOrders: orders, - }; - } + if (payload) { + const { orders: openOrders, wallet, networkId } = payload; + const account = futuresState.isolatedMargin.accounts[networkId][wallet]; + futuresState.isolatedMargin.accounts[networkId][wallet] = { + ...account, + openOrders, + }; } }); builder.addCase(fetchIsolatedOpenOrders.rejected, (futuresState) => { @@ -528,25 +548,17 @@ const futuresSlice = createSlice({ }); builder.addCase(fetchFuturesPositionHistory.fulfilled, (futuresState, { payload }) => { futuresState.queryStatuses.positionHistory = SUCCESS_STATUS; - if (!payload) return; - if (payload.accountType === 'isolated_margin') { - if (futuresState.isolatedMargin.accounts[payload.networkId]) { - futuresState.isolatedMargin.accounts[payload.networkId][payload.account] = { - ...futuresState.isolatedMargin.accounts[payload.networkId][payload.account], - positionHistory: payload.history, - }; - } - } else { - const wallet = findWalletForAccount( - futuresState.crossMargin, - payload.account, - payload.networkId + if (payload) { + const { accountType: type, history: positionHistory, networkId, account: wallet } = payload; + futuresState[accountType(type)].accounts[networkId][wallet] = updateFuturesAccount( + futuresState, + type, + networkId, + wallet, + { + positionHistory, + } ); - if (wallet) { - futuresState.crossMargin.accounts[payload.networkId][ - wallet - ].positionHistory = payload.history.filter((p) => p.accountType === 'cross_margin'); - } } }); builder.addCase(fetchFuturesPositionHistory.rejected, (futuresState) => { @@ -581,17 +593,17 @@ const futuresSlice = createSlice({ }); builder.addCase(fetchTradesForSelectedMarket.fulfilled, (futuresState, { payload }) => { futuresState.queryStatuses.trades = SUCCESS_STATUS; - if (!payload) return; - if (payload.accountType === 'isolated_margin') { - if (futuresState.isolatedMargin.accounts[payload.networkId]) { - futuresState.isolatedMargin.accounts[payload.networkId][payload.account] = { - ...futuresState.isolatedMargin.accounts[payload.networkId][payload.account], - trades: payload.trades, - }; - } - } else { - futuresState.crossMargin.accounts[payload.networkId][payload.wallet].trades = - payload.trades; + if (payload) { + const { accountType: type, trades, networkId, account: wallet } = payload; + futuresState[accountType(type)].accounts[networkId][wallet] = updateFuturesAccount( + futuresState, + type, + networkId, + wallet, + { + trades, + } + ); } }); builder.addCase(fetchTradesForSelectedMarket.rejected, (futuresState) => { @@ -609,17 +621,17 @@ const futuresSlice = createSlice({ }); builder.addCase(fetchAllTradesForAccount.fulfilled, (futuresState, { payload }) => { futuresState.queryStatuses.trades = SUCCESS_STATUS; - if (!payload) return; - if (payload.accountType === 'isolated_margin') { - if (futuresState.isolatedMargin.accounts[payload.networkId]) { - futuresState.isolatedMargin.accounts[payload.networkId][payload.account] = { - ...futuresState.isolatedMargin.accounts[payload.networkId][payload.account], - trades: payload.trades, - }; - } - } else { - futuresState.crossMargin.accounts[payload.networkId][payload.wallet].trades = - payload.trades; + if (payload) { + const { accountType: type, trades, networkId, account: wallet } = payload; + futuresState[accountType(type)].accounts[networkId][wallet] = updateFuturesAccount( + futuresState, + type, + networkId, + wallet, + { + trades, + } + ); } }); builder.addCase(fetchAllTradesForAccount.rejected, (futuresState) => { @@ -671,6 +683,7 @@ export const { setShowCrossMarginOnboard, setSelectedTrader, setSelectedInputDenomination, + setSelectedPortfolioTimeframe, } = futuresSlice.actions; const findWalletForAccount = ( @@ -683,3 +696,27 @@ const findWalletForAccount = ( }); return entry ? entry[0] : undefined; }; + +const updateFuturesAccount = ( + futuresState: FuturesState, + type: FuturesAccountType, + network: NetworkId, + wallet: string, + newAccountData: Partial +): IsolatedAccountData | CrossMarginAccountData => { + if (type === 'isolated_margin') { + const account = futuresState.isolatedMargin.accounts[network][wallet]; + return { + ...ZERO_STATE_ISOLATED_ACCOUNT, + ...account, + ...newAccountData, + }; + } else { + const account = futuresState.crossMargin.accounts[network][wallet]; + return { + ...ZERO_STATE_CM_ACCOUNT, + ...account, + ...newAccountData, + }; + } +}; diff --git a/state/futures/selectors.ts b/state/futures/selectors.ts index 9711b29b19..62411d0292 100644 --- a/state/futures/selectors.ts +++ b/state/futures/selectors.ts @@ -1,9 +1,10 @@ import { createSelector } from '@reduxjs/toolkit'; import Wei, { wei } from '@synthetixio/wei'; -import { formatBytes32String } from 'ethers/lib/utils'; import { DEFAULT_LEVERAGE, DEFAULT_NP_LEVERAGE_ADJUSTMENT } from 'constants/defaults'; import { APP_MAX_LEVERAGE, DEFAULT_MAX_LEVERAGE } from 'constants/futures'; +import { ETH_UNIT } from 'constants/network'; +import { PERIOD_IN_SECONDS, Period } from 'sdk/constants/period'; import { TransactionStatus } from 'sdk/types/common'; import { FuturesPosition, PositionSide } from 'sdk/types/futures'; import { unserializePotentialTrade } from 'sdk/utils/futures'; @@ -12,6 +13,7 @@ import { selectOffchainPricesInfo, selectPrices } from 'state/prices/selectors'; import { RootState } from 'state/store'; import { selectNetwork, selectWallet } from 'state/wallet/selectors'; import { computeOrderFee, sameSide } from 'utils/costCalculations'; +import { truncateTimestamp } from 'utils/formatters/date'; import { getKnownError } from 'utils/formatters/error'; import { zeroBN } from 'utils/formatters/number'; import { @@ -30,7 +32,14 @@ import { unserializeFuturesOrders, } from 'utils/futures'; -import { MarkPrices, futuresPositionKeys, MarkPriceInfos } from './types'; +import { + FuturesAction, + FuturesPortfolio, + MarkPrices, + futuresPositionKeys, + MarkPriceInfos, + PortfolioValues, +} from './types'; export const selectFuturesType = (state: RootState) => state.futures.selectedType; @@ -317,6 +326,18 @@ export const selectActiveCrossPositionsCount = createSelector( } ); +export const selectTotalBuyingPower = createSelector(selectFuturesPositions, (positions) => { + return positions.reduce((acc, p) => { + return acc.add(p.accessibleMargin.mul(APP_MAX_LEVERAGE)); + }, zeroBN); +}); + +export const selectTotalUnrealizedPnl = createSelector(selectFuturesPositions, (positions) => { + return positions.reduce((acc, p) => { + return acc.add(p.position?.pnl ?? zeroBN); + }, zeroBN); +}); + export const selectSubmittingFuturesTx = createSelector( (state: RootState) => state.app, (app) => { @@ -659,7 +680,7 @@ export const selectFuturesPortfolio = createSelector( } ); -export const selectMarginTransfers = createSelector( +export const selectMarketMarginTransfers = createSelector( selectWallet, selectNetwork, selectFuturesType, @@ -675,6 +696,18 @@ export const selectMarginTransfers = createSelector( } ); +export const selectMarginTransfers = createSelector( + selectWallet, + selectNetwork, + selectFuturesType, + (state: RootState) => state.futures, + (wallet, network, type, futures) => { + if (!wallet) return []; + const account = futures[accountType(type)].accounts[network]?.[wallet]; + return account?.marginTransfers ?? []; + } +); + export const selectCrossMarginOpenOrders = createSelector( selectMarketAsset, selectCrossMarginAccountData, @@ -834,7 +867,7 @@ export const selectUsersTradesForMarket = createSelector( } else if (account) { trades = unserializeTrades(isolatedAccountData?.trades ?? []); } - return trades?.filter((t) => t.asset === formatBytes32String(asset)) ?? []; + return trades?.filter((t) => t.asset === asset) ?? []; } ); @@ -851,6 +884,129 @@ export const selectAllUsersTrades = createSelector( } ); +export const selectSelectedPortfolioTimeframe = (state: RootState) => + state.futures.dashboard.selectedPortfolioTimeframe; + +export const selectUserPortfolioValues = createSelector( + selectAllUsersTrades, + selectMarginTransfers, + selectFuturesPortfolio, + (trades, transfers, portfolioTotal) => { + const tradeActions = trades.map(({ account, timestamp, asset, margin }) => ({ + account, + timestamp, + asset, + margin: margin.div(ETH_UNIT).toNumber(), + size: 0, + })); + + const transferActions = transfers.map(({ account, timestamp, asset, size }) => ({ + account, + timestamp, + asset, + size, + margin: 0, + })); + + const actions = [...tradeActions, ...transferActions] + .filter((action): action is FuturesAction => !!action) + .sort((a, b) => a.timestamp - b.timestamp); + + const accountHistory = actions.reduce((acc, action) => { + if (acc.length === 0) { + const newTotal = action.size !== 0 ? action.size : action.margin; + const lastAction = { + account: action.account, + timestamp: action.timestamp, + assets: { + [action.asset]: newTotal, + }, + total: newTotal, + }; + return [lastAction]; + } else { + const lastAction = acc[acc.length - 1]; + const newAssets = { + ...lastAction.assets, + [action.asset]: + action.size !== 0 + ? (lastAction.assets[action.asset] ?? 0) + action.size + : action.margin, + }; + const newTotal = Object.entries(newAssets).reduce((acc, asset) => acc + asset[1], 0); + + const newAction = { + ...lastAction, + timestamp: action.timestamp, + assets: newAssets, + total: newTotal, + }; + const replacePrevious = newAction.timestamp === lastAction.timestamp; + + return [...acc.slice(0, acc.length - (replacePrevious ? 1 : 0)), newAction]; + } + }, [] as FuturesPortfolio[]); + return [ + ...accountHistory.map(({ timestamp, total }) => ({ timestamp: timestamp * 1000, total })), + { + timestamp: Date.now(), + total: portfolioTotal.isolatedMarginFutures.toNumber(), + }, + ]; + } +); + +export const selectPortfolioChartData = createSelector( + selectUserPortfolioValues, + selectSelectedPortfolioTimeframe, + (portfolioValues, timeframe) => { + // get the timeframe for interpolation + const interpolationGap = + timeframe === Period.ONE_YEAR + ? PERIOD_IN_SECONDS[Period.ONE_DAY] + : PERIOD_IN_SECONDS[Period.ONE_HOUR] * 6; + if (portfolioValues.length === 0) return []; + + const minTimestamp = Date.now() - PERIOD_IN_SECONDS[timeframe] * 1000; + const filteredPortfolioValues = portfolioValues.filter( + ({ timestamp }) => timestamp >= minTimestamp + ); + + const portfolioData: PortfolioValues[] = []; + for (let i = 0; i < filteredPortfolioValues.length; i++) { + if (i < filteredPortfolioValues.length - 1) { + const currentTimestamp = truncateTimestamp( + filteredPortfolioValues[i].timestamp, + interpolationGap * 1000 + ); + const nextTimestamp = truncateTimestamp( + filteredPortfolioValues[i + 1].timestamp, + interpolationGap * 1000 + ); + const timeDiff = nextTimestamp - currentTimestamp; + + if (nextTimestamp !== currentTimestamp) { + portfolioData.push({ + timestamp: currentTimestamp, + total: filteredPortfolioValues[i].total, + }); + } + if (timeDiff > interpolationGap * 1000) { + const gapCount = Math.floor(timeDiff / (interpolationGap * 1000)) - 1; + for (let j = 1; j <= gapCount; j++) { + portfolioData.push({ + timestamp: currentTimestamp + j * interpolationGap * 1000, + total: filteredPortfolioValues[i].total, + }); + } + } + } + } + portfolioData.push(portfolioValues[portfolioValues.length - 1]); + return portfolioData; + } +); + export const selectCancellingOrder = (state: RootState) => state.futures.crossMargin.cancellingOrder; diff --git a/state/futures/types.ts b/state/futures/types.ts index 1394480878..5d285f0135 100644 --- a/state/futures/types.ts +++ b/state/futures/types.ts @@ -1,5 +1,6 @@ import Wei from '@synthetixio/wei'; +import { Period } from 'sdk/constants/period'; import { TransactionStatus } from 'sdk/types/common'; import { CrossMarginOrderType, @@ -47,6 +48,29 @@ export type FundingRate = { fundingRate: T | null; }; +export type FuturesAction = { + account: string; + timestamp: number; + asset: FuturesMarketAsset; + margin: number; + size: number; + action: 'trade' | 'deposit' | 'withdraw'; +}; + +export type FuturesPortfolio = { + account: string; + timestamp: number; + assets: { + [asset: string]: number; + }; + total: number; +}; + +export type PortfolioValues = { + timestamp: number; + total: number; +}; + export type FuturesQueryStatuses = { markets: QueryStatus; crossMarginBalanceInfo: QueryStatus; @@ -166,6 +190,9 @@ export type FuturesState = { transactionEstimations: TransactionEstimations; errors: FuturesErrors; selectedInputDenomination: InputCurrencyDenomination; + dashboard: { + selectedPortfolioTimeframe: Period; + }; leaderboard: { selectedTrader: string | undefined; selectedTraderPositionHistory: Record< diff --git a/state/migrations.ts b/state/migrations.ts index 18d632897b..2bc7bc4727 100644 --- a/state/migrations.ts +++ b/state/migrations.ts @@ -58,6 +58,12 @@ export const migrations = { home: HOME_INITIAL_STATE, }; }, + 10: (state: any) => { + return { + ...state, + futures: FUTURES_INITIAL_STATE, + }; + }, }; export default migrations; diff --git a/state/store.ts b/state/store.ts index 42c5533ffe..55f7e6dd19 100644 --- a/state/store.ts +++ b/state/store.ts @@ -34,7 +34,7 @@ const LOG_REDUX = false; const persistConfig = { key: 'root1', storage, - version: 9, + version: 10, blacklist: ['app', 'wallet'], migrate: createMigrate(migrations, { debug: true }), }; diff --git a/translations/en.json b/translations/en.json index eb93064a7b..a6c6b7e283 100644 --- a/translations/en.json +++ b/translations/en.json @@ -503,6 +503,13 @@ "mobile": { "portfolio": "Portfolio", "open-positions": "Open Positions" + }, + "portfolio-chart": { + "welcome": "Welcome to Kwenta", + "hero": "Gain exposure to a variety of assets with up to 25x leverage and deep liquidity", + "portfolio-value": "Portfolio Value", + "buying-power": "Total Buying Power", + "upnl": "Unrealized PnL" } }, "earn": { @@ -514,7 +521,7 @@ "copy": "You can unstake your pool tokens." }, "withdraw-liquidity": { - "title": "Step 2. Withdraw Your Liuqidity", + "title": "Step 2. Withdraw Your Liquidity", "copy": "You can now withdraw your liquidity from the Arrakis ETH/KWENTA vault.", "pool-link": "Arrakis WETH/KWENTA Pool ↗" } diff --git a/utils/formatters/date.ts b/utils/formatters/date.ts index 971dbbdb30..905ea5140c 100644 --- a/utils/formatters/date.ts +++ b/utils/formatters/date.ts @@ -14,13 +14,17 @@ export const toJSTimestamp = (timestamp: number) => timestamp * 1000; export const formatShortDate = (date: Date | number) => formatDate(date, 'yyyy-MM-dd'); +export const formatChartTime = (date: Date | number) => formatDate(date, 'E, h a'); + +export const formatChartDate = (date: Date | number) => formatDate(date, 'M/d'); + export const formatShortDateUTC = (date: Date | number) => { const dateString = new Date(date).toISOString(); return dateString.substring(0, 10); }; export const formatShortDateWithTime = (date: Date | number) => - formatDate(date, 'MMM d, yyyy H:mma'); + formatDate(date, 'MMM d, yyyy h:mm a'); export const formatDateWithTime = (date: Date | number) => formatDate(date, 'd MMM yyyy H:mm'); export const secondsToTime = (seconds: number) => { @@ -83,6 +87,10 @@ export const formatTimer = (seconds: number) => { return `${numMinutes}:${String(numSeconds).padStart(2, '0')}`; }; +export const truncateTimestamp = (timestamp: number, delta: number): number => { + return Math.floor(timestamp / delta) * delta; +}; + export const formatTruncatedDuration = (delta: number): string => { const days = Math.floor(delta / 86400); delta -= days * 86400; diff --git a/utils/futures.ts b/utils/futures.ts index 6eb2302b08..571acf7e8d 100644 --- a/utils/futures.ts +++ b/utils/futures.ts @@ -602,9 +602,9 @@ export const unserializePositionHistory = ( export const serializeTrades = (trades: FuturesTrade[]): FuturesTrade[] => { return trades.map((t) => ({ ...t, + margin: t.margin.toString(), size: t.size.toString(), price: t.price.toString(), - timestamp: t.timestamp.toString(), positionSize: t.positionSize.toString(), pnl: t.pnl.toString(), feesPaid: t.feesPaid.toString(), @@ -615,9 +615,9 @@ export const serializeTrades = (trades: FuturesTrade[]): FuturesTrade[] export const unserializeTrades = (trades: FuturesTrade[]): FuturesTrade[] => { return trades.map((t) => ({ ...t, + margin: wei(t.margin), size: wei(t.size), price: wei(t.price), - timestamp: wei(t.timestamp), positionSize: wei(t.positionSize), pnl: wei(t.pnl), feesPaid: wei(t.feesPaid), diff --git a/utils/icons.ts b/utils/icons.ts index ff1e19bf54..0d536b3d92 100644 --- a/utils/icons.ts +++ b/utils/icons.ts @@ -81,6 +81,7 @@ export const SYNTH_ICONS: Record = sDOGE: DOGEIcon, sXMR: XMRIcon, sOP: OPIcon, + sARB: ARBIcon, sATOM: ATOMIcon, sFTM: FTMIcon, sNEAR: NEARIcon,