From 8859ac9fdcefde77d6d8dd40298dd22b93a16e1a Mon Sep 17 00:00:00 2001 From: agustinhufferson Date: Sun, 1 Sep 2024 15:14:27 +0330 Subject: [PATCH 1/3] Checking trades that open with lower size than limit --- .../App/AccountData/AccountOverview.tsx | 2 +- .../App/TradePanel/MinPositionInfo.tsx | 64 ++----- .../OpenPosition/OpenPositionData.tsx | 36 +++- packages/core/src/hooks/useTradePage.ts | 48 ++++- yarn.lock | 164 ++---------------- 5 files changed, 108 insertions(+), 206 deletions(-) diff --git a/apps/Cloverfield/components/App/AccountData/AccountOverview.tsx b/apps/Cloverfield/components/App/AccountData/AccountOverview.tsx index 0e38f31..938e463 100644 --- a/apps/Cloverfield/components/App/AccountData/AccountOverview.tsx +++ b/apps/Cloverfield/components/App/AccountData/AccountOverview.tsx @@ -299,7 +299,7 @@ export const BypassPrecisionCheckModeTitle = ({ } #${tries}` ); } - }, [tries, setBypassPrecisionCheck]); + }, [tries, setBypassPrecisionCheck, bypassPrecisionCheck]); const handleAccountOverviewClick = () => { setTries(tries + 1); diff --git a/apps/Cloverfield/components/App/TradePanel/MinPositionInfo.tsx b/apps/Cloverfield/components/App/TradePanel/MinPositionInfo.tsx index 400d8f4..fa9169b 100644 --- a/apps/Cloverfield/components/App/TradePanel/MinPositionInfo.tsx +++ b/apps/Cloverfield/components/App/TradePanel/MinPositionInfo.tsx @@ -1,5 +1,5 @@ import { useMemo } from "react"; -import BigNumber from "bignumber.js"; +// import BigNumber from "bignumber.js"; import { DEFAULT_PRECISION } from "@symmio/frontend-sdk/constants/misc"; import { useCollateralToken } from "@symmio/frontend-sdk/constants/tokens"; @@ -14,10 +14,11 @@ import { InputField } from "@symmio/frontend-sdk/types/trade"; import useActiveWagmi from "@symmio/frontend-sdk/lib/hooks/useActiveWagmi"; import { useActiveMarket, - useActiveMarketPrice, + // useActiveMarketPrice, useSetTypedValue, } from "@symmio/frontend-sdk/state/trade/hooks"; -import { useLeverage } from "@symmio/frontend-sdk/state/user/hooks"; + +import useTradePage from "@symmio/frontend-sdk/hooks/useTradePage"; import InfoItem from "components/InfoItem"; @@ -30,64 +31,33 @@ export default function MinPositionInfo() { chainId ); - const leverage = useLeverage(); const market = useActiveMarket(); - const marketPrice = useActiveMarketPrice(); - const [ - outputTicker, - pricePrecision, - quantityPrecision, - minAcceptableQuoteValue, - ] = useMemo( + const tradePage = useTradePage(); + const [outputTicker, pricePrecision] = useMemo( () => - market - ? [ - market.symbol, - market.pricePrecision, - market.quantityPrecision, - market.minAcceptableQuoteValue, - market.maxLeverage, - ] - : ["", DEFAULT_PRECISION, DEFAULT_PRECISION, 10], + market ? [market.symbol, market.pricePrecision] : ["", DEFAULT_PRECISION], [market] ); - const [minPositionValue, minPositionQuantity] = useMemo(() => { - // find maximum quantity between min quote value & minimum value base on quantity precision - const quantity = BigNumber.max( - toBN(minAcceptableQuoteValue) - .div(marketPrice) - .times(leverage) - .toFixed(quantityPrecision, RoundMode.ROUND_UP), - toBN(10) - .pow(quantityPrecision * -1) - .toFixed(quantityPrecision, RoundMode.ROUND_UP) - ); - const value = toBN(quantity).times(marketPrice).div(leverage); - if (value.isNaN()) return ["-", "-"]; - return [ - value.toFixed(pricePrecision, RoundMode.ROUND_UP), - quantity.toFixed(quantityPrecision, RoundMode.ROUND_UP), - ]; - }, [ - leverage, - marketPrice, - minAcceptableQuoteValue, - pricePrecision, - quantityPrecision, - ]); + const [value, quantity] = useMemo( + () => + tradePage + ? [tradePage.minPositionValue, tradePage.minPositionQuantity] + : ["-", "-"], + [tradePage] + ); return ( setTypedValue(value, InputField.PRICE)} /> diff --git a/apps/Cloverfield/components/ReviewModal/OpenPosition/OpenPositionData.tsx b/apps/Cloverfield/components/ReviewModal/OpenPosition/OpenPositionData.tsx index 1998c6a..375dc80 100644 --- a/apps/Cloverfield/components/ReviewModal/OpenPosition/OpenPositionData.tsx +++ b/apps/Cloverfield/components/ReviewModal/OpenPosition/OpenPositionData.tsx @@ -29,6 +29,11 @@ const LabelsWrapper = styled(Column)` gap: 12px; `; +const ErrorMsgStyle = styled.div<{ color?: string; size?: string }>` + color: ${({ theme, color }) => color ?? theme.red2}; + font-size: ${({ size }) => size ?? "12px"}; +`; + export default function OpenPositionData() { const theme = useTheme(); const { chainId } = useActiveWagmi(); @@ -42,7 +47,7 @@ export default function OpenPositionData() { chainId ); - const { price, formattedAmounts } = useTradePage(); + const tradePage = useTradePage(); const [symbol, pricePrecision] = useMemo( () => @@ -50,11 +55,14 @@ export default function OpenPositionData() { [market] ); const quantityAsset = useMemo( - () => (toBN(formattedAmounts[1]).isNaN() ? "0" : formattedAmounts[1]), - [formattedAmounts] + () => + toBN(tradePage.formattedAmounts[1]).isNaN() + ? "0" + : tradePage.formattedAmounts[1], + [tradePage.formattedAmounts] ); const { tp, sl } = useTradeTpSl(); - const notionalValue = useNotionalValue(quantityAsset, price); + const notionalValue = useNotionalValue(quantityAsset, tradePage.price); const { total: lockedValue } = useLockedValues(notionalValue); @@ -79,7 +87,11 @@ export default function OpenPositionData() { { title: "Open Price:", value: `${ - price === "" ? "-" : orderType === OrderType.MARKET ? "Market" : price + tradePage.price === "" + ? "-" + : orderType === OrderType.MARKET + ? "Market" + : tradePage.price }`, valueColor: theme.primaryBlue, }, @@ -115,7 +127,7 @@ export default function OpenPositionData() { pricePrecision, collateralCurrency?.symbol, userLeverage, - price, + tradePage.price, orderType, theme.primaryBlue, tradingFee, @@ -123,6 +135,9 @@ export default function OpenPositionData() { sl, ]); + const errorMsg = + "Caution: The trade size might be smaller than the threshold while the order is being filled."; + return ( @@ -136,7 +151,7 @@ export default function OpenPositionData() { @@ -150,6 +165,13 @@ export default function OpenPositionData() { /> ); })} + +
+ {toBN(tradePage.formattedAmounts[1]).lt( + tradePage.minPositionQuantity + ) && errorMsg} +
+
); diff --git a/packages/core/src/hooks/useTradePage.ts b/packages/core/src/hooks/useTradePage.ts index 032c21c..c7e2d0c 100644 --- a/packages/core/src/hooks/useTradePage.ts +++ b/packages/core/src/hooks/useTradePage.ts @@ -42,6 +42,8 @@ export default function useTradePage(): { formattedAmounts: string[]; state: ErrorState; balance: string; + minPositionValue: string; + minPositionQuantity: string; } { const typedValue = useTypedValue(); const inputField = useInputField(); @@ -140,7 +142,6 @@ export default function useTradePage(): { }, [availableForOrder, leverage, market]); const outOfRangePrice = useMemo(() => { - // check limit price range) const { name, maxPrice, minPrice } = priceRange; if (orderType === OrderType.LIMIT && market && market.name === name) { @@ -153,6 +154,29 @@ export default function useTradePage(): { return false; }, [priceRange, orderType, market, positionType, limitPrice]); + const [minPositionValue, minPositionQuantity] = useMemo(() => { + // find maximum quantity between min quote value & minimum value base on quantity precision + if (market) { + const quantity = BigNumber.max( + toBN(market.minAcceptableQuoteValue) + .div(marketPrice) + .times(leverage) + .toFixed(quantityPrecision, RoundMode.ROUND_UP), + toBN(10) + .pow(quantityPrecision * -1) + .toFixed(quantityPrecision, RoundMode.ROUND_UP) + ); + const value = toBN(quantity).times(marketPrice).div(leverage); + + if (value.isNaN()) return ["-", "-"]; + return [ + value.toFixed(pricePrecision, RoundMode.ROUND_UP), + quantity.toFixed(quantityPrecision, RoundMode.ROUND_UP), + ]; + } + return ["-", "-"]; + }, [market, marketPrice, leverage, quantityPrecision, pricePrecision]); + const state = useMemo(() => { const notionalValue = toBN(formattedAmounts[1]).isNaN() ? toBN(0) @@ -161,7 +185,6 @@ export default function useTradePage(): { const freeOpenInterest = toBN(totalOpenInterest).minus(usedOpenInterest); const lockedValue = notionalValue.div(leverage); const minimumCap = BigNumber.min(freeNotionalCap, freeOpenInterest); - if ( formattedAmounts[0] && formattedAmounts[1] && @@ -174,7 +197,7 @@ export default function useTradePage(): { } if ( market && - toBN(lockedValue).lt(market.minAcceptableQuoteValue) && + toBN(lockedValue).lt(minPositionValue) && formattedAmounts[0] && formattedAmounts[1] ) { @@ -212,6 +235,7 @@ export default function useTradePage(): { totalOpenInterest, usedOpenInterest, leverage, + minPositionValue, balance, market, outOfRangePrice, @@ -220,8 +244,22 @@ export default function useTradePage(): { ]); return useMemo( - () => ({ price, formattedAmounts, state, balance }), - [price, formattedAmounts, state, balance] + () => ({ + price, + formattedAmounts, + state, + balance, + minPositionValue, + minPositionQuantity, + }), + [ + price, + formattedAmounts, + state, + balance, + minPositionValue, + minPositionQuantity, + ] ); } diff --git a/yarn.lock b/yarn.lock index bbe6ccc..e643a3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2202,23 +2202,6 @@ "@walletconnect/window-getters" "^1.0.1" tslib "1.14.1" -"@wojtekmaj/date-utils@^1.1.3", "@wojtekmaj/date-utils@^1.5.0": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@wojtekmaj/date-utils/-/date-utils-1.5.1.tgz#c3cd67177ac781cfa5736219d702a55a2aea5f2b" - integrity sha512-+i7+JmNiE/3c9FKxzWFi2IjRJ+KzZl1QPu6QNrsgaa2MuBgXvUy4gA1TVzf/JMdIIloB76xSKikTWuyYAIVLww== - -"@wojtekmaj/react-datetimerange-picker@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@wojtekmaj/react-datetimerange-picker/-/react-datetimerange-picker-6.0.0.tgz#dbbf59c17b4ba31c62c9886ec585d5a87898aed8" - integrity sha512-evzEzTL6yk6QsKplGRQpzfTxiKHCaK0caT5DQQnI5khRRBG7XKOgDcxFaJ3Ru2YDB3m3aEIdDKCynOHp2I5ubQ== - dependencies: - clsx "^2.0.0" - make-event-props "^1.6.0" - react-calendar "^5.0.0" - react-clock "^5.0.0" - react-datetime-picker "^6.0.1" - react-fit "^2.0.0" - "@wry/context@^0.7.0", "@wry/context@^0.7.3": version "0.7.3" resolved "https://registry.npmjs.org/@wry/context/-/context-0.7.3.tgz" @@ -2802,11 +2785,6 @@ clsx@^1.2.1: resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== -clsx@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" - integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== - color-convert@^1.9.0: version "1.9.3" resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" @@ -3164,11 +3142,6 @@ detect-browser@5.3.0, detect-browser@^5.2.0: resolved "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz" integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w== -detect-element-overflow@^1.4.0: - version "1.4.2" - resolved "https://registry.yarnpkg.com/detect-element-overflow/-/detect-element-overflow-1.4.2.tgz#2e48509e5aa07647f4335b5f4f52c146b92f99c5" - integrity sha512-4m6cVOtvm/GJLjo7WFkPfwXoEIIbM7GQwIh4WEa4g7IsNi1YzwUsGL5ApNLrrHL29bHeNeQ+/iZhw+YHqgE2Fw== - detect-libc@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" @@ -4206,13 +4179,6 @@ get-tsconfig@^4.5.0: dependencies: resolve-pkg-maps "^1.0.0" -get-user-locale@^2.2.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/get-user-locale/-/get-user-locale-2.3.2.tgz#d37ae6e670c2b57d23a96fb4d91e04b2059d52cf" - integrity sha512-O2GWvQkhnbDoWFUJfaBlDIKUEdND8ATpBXD6KXcbhxlfktyD/d8w6mkzM/IlQEqGZAMz/PW6j6Hv53BiigKLUQ== - dependencies: - mem "^8.0.0" - get-value@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/get-value/-/get-value-3.0.1.tgz#5efd2a157f1d6a516d7524e124ac52d0a39ef5a8" @@ -5174,18 +5140,6 @@ lru-cache@^6.0.0: resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz" integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g== -make-event-props@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/make-event-props/-/make-event-props-1.6.2.tgz#c8e0e48eb28b9b808730de38359f6341de7ec5a2" - integrity sha512-iDwf7mA03WPiR8QxvcVHmVWEPfMY1RZXerDVNCRYW7dUr2ppH3J58Rwb39/WG39yTZdRSxr3x+2v22tvI0VEvA== - -map-age-cleaner@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" - integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== - dependencies: - p-defer "^1.0.0" - markdown-table@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz" @@ -5294,14 +5248,6 @@ media-query-parser@^2.0.2: dependencies: "@babel/runtime" "^7.12.5" -mem@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/mem/-/mem-8.1.1.tgz#cf118b357c65ab7b7e0817bdf00c8062297c0122" - integrity sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA== - dependencies: - map-age-cleaner "^0.1.3" - mimic-fn "^3.1.0" - "memoize-one@>=3.1.1 <6": version "5.2.1" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" @@ -5424,11 +5370,6 @@ mimic-fn@^2.1.0: resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-fn@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" - integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== - mimic-fn@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz" @@ -5793,11 +5734,6 @@ outdent@^0.8.0: resolved "https://registry.npmjs.org/outdent/-/outdent-0.8.0.tgz" integrity sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A== -p-defer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" - integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw== - p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" @@ -6150,53 +6086,6 @@ rc-util@^5.27.0: "@babel/runtime" "^7.18.3" react-is "^16.12.0" -react-calendar@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/react-calendar/-/react-calendar-5.0.0.tgz#cf302db689ee1bba53d92644f7543e12164a7c0e" - integrity sha512-bHcE5e5f+VUKLd4R19BGkcSQLpuwjKBVG0fKz74cwPW5xDfNsReHdDbfd4z3mdjuUuZzVtw4Q920mkwK5/ZOEg== - dependencies: - "@wojtekmaj/date-utils" "^1.1.3" - clsx "^2.0.0" - get-user-locale "^2.2.1" - warning "^4.0.0" - -react-clock@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/react-clock/-/react-clock-5.0.0.tgz#369b1c258b304a538a4de7d8cae18c7be77e51d5" - integrity sha512-Cj3XqwLB1svtGWiw/A6vmLIPb9OhA/BsWUpS46lXTNTilK7zmP2zmtFgQEAfWUssc3nERXkMXzI0YrkzDpc0gQ== - dependencies: - "@wojtekmaj/date-utils" "^1.5.0" - clsx "^2.0.0" - get-user-locale "^2.2.1" - -react-date-picker@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/react-date-picker/-/react-date-picker-11.0.0.tgz#f7dc25e9a679f94ad44f11644ea0fdc541be1834" - integrity sha512-l+siu5HSZ/ciGL1293KCAHl4o9aD5rw16V4tB0C43h7QbMv2dWGgj7Dxgt8iztLaPVtEfOt/+sxNiTYw4WVq6A== - dependencies: - "@wojtekmaj/date-utils" "^1.1.3" - clsx "^2.0.0" - get-user-locale "^2.2.1" - make-event-props "^1.6.0" - react-calendar "^5.0.0" - react-fit "^2.0.0" - update-input-width "^1.4.0" - -react-datetime-picker@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/react-datetime-picker/-/react-datetime-picker-6.0.1.tgz#7a88ba84cdccd5096029965966723d74a0461535" - integrity sha512-G7W8bK0SLuO66RVWYGD2q1bD4Wk4pUOpJCq9r44A4P33uq0aAtd3dT1HNEu2fvlmMpYxC4J571ZPI9bUG46pDA== - dependencies: - "@wojtekmaj/date-utils" "^1.1.3" - clsx "^2.0.0" - get-user-locale "^2.2.1" - make-event-props "^1.6.0" - react-calendar "^5.0.0" - react-clock "^5.0.0" - react-date-picker "^11.0.0" - react-fit "^2.0.0" - react-time-picker "^7.0.0" - react-device-detect@^2.2.2: version "2.2.3" resolved "https://registry.npmjs.org/react-device-detect/-/react-device-detect-2.2.3.tgz" @@ -6219,14 +6108,6 @@ react-feather@^2.0.10: dependencies: prop-types "^15.7.2" -react-fit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/react-fit/-/react-fit-2.0.1.tgz#4bcb4de7aa94c9fdf452b0c63de0889496f50244" - integrity sha512-Eip6ALs/+6Jv82Si0I9UnfysdwVlAhkkZRycgmMdnj7jwUg69SVFp84ICxwB8zszkfvJJ2MGAAo9KAYM8ZUykQ== - dependencies: - detect-element-overflow "^1.4.0" - warning "^4.0.0" - react-hot-toast@^2.4.1: version "2.4.1" resolved "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz" @@ -6356,19 +6237,6 @@ react-style-singleton@^2.2.1: invariant "^2.2.4" tslib "^2.0.0" -react-time-picker@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/react-time-picker/-/react-time-picker-7.0.0.tgz#3f9d80d2de8a8ffc57c41dd71095477f6a7ffc03" - integrity sha512-k6mUjkI+OsY73mg0yjMxqkLXv/UXR1LN7AARNqfyGZOwqHqo1JrjL3lLHTHWQ86HmPTBL/dZACbIX/fV1NLmWg== - dependencies: - "@wojtekmaj/date-utils" "^1.1.3" - clsx "^2.0.0" - get-user-locale "^2.2.1" - make-event-props "^1.6.0" - react-clock "^5.0.0" - react-fit "^2.0.0" - update-input-width "^1.4.0" - react-tooltip@^4.2.21: version "4.5.1" resolved "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.5.1.tgz" @@ -6941,7 +6809,16 @@ strict-uri-encode@^2.0.0: resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz" integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -7015,7 +6892,14 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -7447,11 +7331,6 @@ untun@^0.1.3: consola "^3.2.3" pathe "^1.1.1" -update-input-width@^1.4.0: - version "1.4.2" - resolved "https://registry.yarnpkg.com/update-input-width/-/update-input-width-1.4.2.tgz#49d327a39395185b0fd440b9c3b1d6f81173655c" - integrity sha512-/p0XLhrQQQ4bMWD7bL9duYObwYCO1qGr8R19xcMmoMSmXuQ7/1//veUnCObQ7/iW6E2pGS6rFkS4TfH4ur7e/g== - update-section@^0.3.3: version "0.3.3" resolved "https://registry.npmjs.org/update-section/-/update-section-0.3.3.tgz" @@ -7615,13 +7494,6 @@ wagmi@^2.10.2: "@wagmi/core" "2.11.2" use-sync-external-store "1.2.0" -warning@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" - integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== - dependencies: - loose-envify "^1.0.0" - watchpack@2.4.0: version "2.4.0" resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz" From a36889d5d83e7bd3a33dd2c2ce7722a1e93bbe6c Mon Sep 17 00:00:00 2001 From: agustinhufferson Date: Sat, 7 Sep 2024 12:44:02 +0330 Subject: [PATCH 2/3] warning when trade size may be lower than the threshold --- .../App/AccountData/AccountOverview.tsx | 1 + .../App/TradePanel/MinPositionInfo.tsx | 52 +++---------------- .../OpenPosition/OpenPositionData.tsx | 16 +++++- packages/core/src/hooks/useTradePage.ts | 48 +++++++++++++++-- 4 files changed, 65 insertions(+), 52 deletions(-) diff --git a/apps/Cloverfield/components/App/AccountData/AccountOverview.tsx b/apps/Cloverfield/components/App/AccountData/AccountOverview.tsx index 0e38f31..b25f611 100644 --- a/apps/Cloverfield/components/App/AccountData/AccountOverview.tsx +++ b/apps/Cloverfield/components/App/AccountData/AccountOverview.tsx @@ -299,6 +299,7 @@ export const BypassPrecisionCheckModeTitle = ({ } #${tries}` ); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [tries, setBypassPrecisionCheck]); const handleAccountOverviewClick = () => { diff --git a/apps/Cloverfield/components/App/TradePanel/MinPositionInfo.tsx b/apps/Cloverfield/components/App/TradePanel/MinPositionInfo.tsx index 400d8f4..174ed11 100644 --- a/apps/Cloverfield/components/App/TradePanel/MinPositionInfo.tsx +++ b/apps/Cloverfield/components/App/TradePanel/MinPositionInfo.tsx @@ -1,5 +1,5 @@ import { useMemo } from "react"; -import BigNumber from "bignumber.js"; +// import BigNumber from "bignumber.js"; import { DEFAULT_PRECISION } from "@symmio/frontend-sdk/constants/misc"; import { useCollateralToken } from "@symmio/frontend-sdk/constants/tokens"; @@ -14,10 +14,11 @@ import { InputField } from "@symmio/frontend-sdk/types/trade"; import useActiveWagmi from "@symmio/frontend-sdk/lib/hooks/useActiveWagmi"; import { useActiveMarket, - useActiveMarketPrice, + // useActiveMarketPrice, useSetTypedValue, } from "@symmio/frontend-sdk/state/trade/hooks"; -import { useLeverage } from "@symmio/frontend-sdk/state/user/hooks"; + +import useTradePage from "@symmio/frontend-sdk/hooks/useTradePage"; import InfoItem from "components/InfoItem"; @@ -30,52 +31,13 @@ export default function MinPositionInfo() { chainId ); - const leverage = useLeverage(); const market = useActiveMarket(); - const marketPrice = useActiveMarketPrice(); - const [ - outputTicker, - pricePrecision, - quantityPrecision, - minAcceptableQuoteValue, - ] = useMemo( + const { minPositionValue, minPositionQuantity } = useTradePage(); + const [outputTicker, pricePrecision] = useMemo( () => - market - ? [ - market.symbol, - market.pricePrecision, - market.quantityPrecision, - market.minAcceptableQuoteValue, - market.maxLeverage, - ] - : ["", DEFAULT_PRECISION, DEFAULT_PRECISION, 10], + market ? [market.symbol, market.pricePrecision] : ["", DEFAULT_PRECISION], [market] ); - const [minPositionValue, minPositionQuantity] = useMemo(() => { - // find maximum quantity between min quote value & minimum value base on quantity precision - const quantity = BigNumber.max( - toBN(minAcceptableQuoteValue) - .div(marketPrice) - .times(leverage) - .toFixed(quantityPrecision, RoundMode.ROUND_UP), - toBN(10) - .pow(quantityPrecision * -1) - .toFixed(quantityPrecision, RoundMode.ROUND_UP) - ); - const value = toBN(quantity).times(marketPrice).div(leverage); - - if (value.isNaN()) return ["-", "-"]; - return [ - value.toFixed(pricePrecision, RoundMode.ROUND_UP), - quantity.toFixed(quantityPrecision, RoundMode.ROUND_UP), - ]; - }, [ - leverage, - marketPrice, - minAcceptableQuoteValue, - pricePrecision, - quantityPrecision, - ]); return ( ` + color: ${({ theme, color }) => color ?? theme.red2}; + font-size: ${({ size }) => size ?? "12px"}; +`; + export default function OpenPositionData() { const theme = useTheme(); const { chainId } = useActiveWagmi(); @@ -41,8 +46,7 @@ export default function OpenPositionData() { COLLATERAL_TOKEN, chainId ); - - const { price, formattedAmounts } = useTradePage(); + const { formattedAmounts, minPositionQuantity, price } = useTradePage(); const [symbol, pricePrecision] = useMemo( () => @@ -123,6 +127,9 @@ export default function OpenPositionData() { sl, ]); + const errorMsg = + "Caution: The trade size might be smaller than the threshold while the order is being filled."; + return ( @@ -150,6 +157,11 @@ export default function OpenPositionData() { /> ); })} + +
+ {toBN(formattedAmounts[1]).lt(minPositionQuantity) && errorMsg} +
+
); diff --git a/packages/core/src/hooks/useTradePage.ts b/packages/core/src/hooks/useTradePage.ts index 032c21c..c7e2d0c 100644 --- a/packages/core/src/hooks/useTradePage.ts +++ b/packages/core/src/hooks/useTradePage.ts @@ -42,6 +42,8 @@ export default function useTradePage(): { formattedAmounts: string[]; state: ErrorState; balance: string; + minPositionValue: string; + minPositionQuantity: string; } { const typedValue = useTypedValue(); const inputField = useInputField(); @@ -140,7 +142,6 @@ export default function useTradePage(): { }, [availableForOrder, leverage, market]); const outOfRangePrice = useMemo(() => { - // check limit price range) const { name, maxPrice, minPrice } = priceRange; if (orderType === OrderType.LIMIT && market && market.name === name) { @@ -153,6 +154,29 @@ export default function useTradePage(): { return false; }, [priceRange, orderType, market, positionType, limitPrice]); + const [minPositionValue, minPositionQuantity] = useMemo(() => { + // find maximum quantity between min quote value & minimum value base on quantity precision + if (market) { + const quantity = BigNumber.max( + toBN(market.minAcceptableQuoteValue) + .div(marketPrice) + .times(leverage) + .toFixed(quantityPrecision, RoundMode.ROUND_UP), + toBN(10) + .pow(quantityPrecision * -1) + .toFixed(quantityPrecision, RoundMode.ROUND_UP) + ); + const value = toBN(quantity).times(marketPrice).div(leverage); + + if (value.isNaN()) return ["-", "-"]; + return [ + value.toFixed(pricePrecision, RoundMode.ROUND_UP), + quantity.toFixed(quantityPrecision, RoundMode.ROUND_UP), + ]; + } + return ["-", "-"]; + }, [market, marketPrice, leverage, quantityPrecision, pricePrecision]); + const state = useMemo(() => { const notionalValue = toBN(formattedAmounts[1]).isNaN() ? toBN(0) @@ -161,7 +185,6 @@ export default function useTradePage(): { const freeOpenInterest = toBN(totalOpenInterest).minus(usedOpenInterest); const lockedValue = notionalValue.div(leverage); const minimumCap = BigNumber.min(freeNotionalCap, freeOpenInterest); - if ( formattedAmounts[0] && formattedAmounts[1] && @@ -174,7 +197,7 @@ export default function useTradePage(): { } if ( market && - toBN(lockedValue).lt(market.minAcceptableQuoteValue) && + toBN(lockedValue).lt(minPositionValue) && formattedAmounts[0] && formattedAmounts[1] ) { @@ -212,6 +235,7 @@ export default function useTradePage(): { totalOpenInterest, usedOpenInterest, leverage, + minPositionValue, balance, market, outOfRangePrice, @@ -220,8 +244,22 @@ export default function useTradePage(): { ]); return useMemo( - () => ({ price, formattedAmounts, state, balance }), - [price, formattedAmounts, state, balance] + () => ({ + price, + formattedAmounts, + state, + balance, + minPositionValue, + minPositionQuantity, + }), + [ + price, + formattedAmounts, + state, + balance, + minPositionValue, + minPositionQuantity, + ] ); } From fb54251b27a361b767ed266ddf9843198cf3e2f6 Mon Sep 17 00:00:00 2001 From: Agustin <40869652+agustinhufferson@users.noreply.github.com> Date: Sat, 16 Nov 2024 16:01:26 +0330 Subject: [PATCH 3/3] Subgraph address edited --- packages/core/src/apollo/queries.ts | 31 +++++++++++------------- packages/core/src/state/quotes/thunks.ts | 12 ++++----- packages/core/src/state/quotes/types.ts | 15 +++++------- 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/packages/core/src/apollo/queries.ts b/packages/core/src/apollo/queries.ts index 56ce4bd..b4a47c6 100644 --- a/packages/core/src/apollo/queries.ts +++ b/packages/core/src/apollo/queries.ts @@ -1,11 +1,11 @@ import gql from "graphql-tag"; export const ORDER_HISTORY_DATA = gql` - query OrderHistory($address: String!, $first: Int!, $skip: Int!) { - resultEntities( + query OrderHistory($address: Bytes!, $first: Int!, $skip: Int!) { + quotes( first: $first skip: $skip - orderBy: timeStamp + orderBy: timestamp orderDirection: desc where: { partyA: $address, quoteStatus_in: [3, 7, 8, 9] } ) { @@ -26,9 +26,9 @@ export const ORDER_HISTORY_DATA = gql` requestedOpenPrice closedPrice quantityToClose - timeStamp + timestamp closePrice - deadline + openDeadline partyBsWhiteList symbolId fillAmount @@ -37,19 +37,16 @@ export const ORDER_HISTORY_DATA = gql` liquidateAmount liquidatePrice closedAmount - initialData { - cva - lf - partyAmm - partyBmm - timeStamp - } + initialLf + initialCva + initialPartyAmm + initialPartyBmm } } `; export const BALANCE_CHANGES_DATA = gql` - query BalanceChanges($account: String!, $first: Int!, $skip: Int!) { + query BalanceChanges($account: Bytes!, $first: Int!, $skip: Int!) { balanceChanges( where: { account: $account, type_not: "ALLOCATE_PARTY_A" } first: $first @@ -67,7 +64,7 @@ export const BALANCE_CHANGES_DATA = gql` `; export const TOTAL_DEPOSITS_AND_WITHDRAWALS = gql` - query TotalDepositsAndWithdrawals($id: String!) { + query TotalDepositsAndWithdrawals($id: ID!) { accounts(where: { id: $id }) { id timestamp @@ -79,9 +76,9 @@ export const TOTAL_DEPOSITS_AND_WITHDRAWALS = gql` `; export const GET_PAID_AMOUNT = gql` - query GetPaidAmount($id: String!) { - resultEntities(where: { quoteId: $id }) { - fee + query GetPaidAmount($id: BigInt!) { + quotes(where: { quoteId: $id }) { + userPaidFunding } } `; diff --git a/packages/core/src/state/quotes/thunks.ts b/packages/core/src/state/quotes/thunks.ts index 4b3467f..602a328 100644 --- a/packages/core/src/state/quotes/thunks.ts +++ b/packages/core/src/state/quotes/thunks.ts @@ -34,9 +34,9 @@ function toQuoteFromGraph(entity: SubGraphData) { openedPrice: fromWei(entity.openedPrice), requestedOpenPrice: fromWei(entity.requestedOpenPrice), quantity: fromWei(entity.quantity), - initialCVA: fromWei(entity.initialData.cva ?? null), - initialPartyAMM: fromWei(entity.initialData.partyAmm ?? null), - initialLF: fromWei(entity.initialData.lf ?? null), + initialCVA: fromWei(entity.initialCva ?? null), + initialPartyAMM: fromWei(entity.initialPartyAmm ?? null), + initialLF: fromWei(entity.initialLf ?? null), CVA: fromWei(entity.cva), partyAMM: fromWei(entity.partyAmm), LF: fromWei(entity.lf), @@ -45,9 +45,9 @@ function toQuoteFromGraph(entity: SubGraphData) { quoteStatus: getQuoteStateByIndex(entity.quoteStatus), avgClosedPrice: fromWei(entity.averageClosedPrice), quantityToClose: fromWei(entity.quantityToClose), - statusModifyTimestamp: Number(entity.timeStamp), - createTimestamp: Number(entity.initialData.timeStamp ?? null), - deadline: Number(entity.deadline), + statusModifyTimestamp: Number(entity.timestamp), + // createTimestamp: Number(entity.initialData.timeStamp ?? null), + deadline: Number(entity.openDeadline), marketPrice: fromWei(entity.marketPrice), closedAmount: fromWei(entity.closedAmount), liquidateAmount: fromWei(entity.liquidateAmount), diff --git a/packages/core/src/state/quotes/types.ts b/packages/core/src/state/quotes/types.ts index c2b4315..e8155b1 100644 --- a/packages/core/src/state/quotes/types.ts +++ b/packages/core/src/state/quotes/types.ts @@ -35,23 +35,20 @@ export interface SubGraphData { closedPrice: string; quantityToClose: string; closePrice: string; - deadline: string; + openDeadline: string; partyBsWhiteList: string[]; symbolId: string; - timeStamp: string; + timestamp: string; marketPrice: string; fillAmount: string; closedAmount: string; averageClosedPrice: string; liquidateAmount: string; liquidatePrice: string; - initialData: { - cva: string; - lf: string; - partyAmm: string; - partyBmm: string; - timeStamp: string; - }; + initialLf: string; + initialCva: string; + initialPartyAmm: string; + initialPartyBmm: string; } export enum InstantCloseStatus {