Compare commits

..
Author SHA1 Message Date
mulan xia 7d6dd402a2 remove order lines on wallet disconnect 2024-02-21 16:28:45 -05:00
mulan xia 24e7cdac14 wip 2024-02-21 13:43:10 -05:00
mulan xia cc1811da16 turn orderlines on 2024-02-21 07:42:18 -05:00
aleka fc5d8538fe bump abacus for new env config path usage (#314)
* bump abacus for new env config path usage

* bump abacus + localization for good til date
2024-02-20 22:42:18 -05:00
9 changed files with 41 additions and 190 deletions
+1 -1
View File
@@ -40,7 +40,7 @@
"@cosmjs/proto-signing": "^0.32.1",
"@cosmjs/stargate": "^0.32.1",
"@cosmjs/tendermint-rpc": "^0.32.1",
"@dydxprotocol/v4-abacus": "^1.4.6",
"@dydxprotocol/v4-abacus": "^1.4.9",
"@dydxprotocol/v4-client-js": "^1.0.20",
"@dydxprotocol/v4-localization": "^1.1.34",
"@ethersproject/providers": "^5.7.2",
+4 -4
View File
@@ -30,8 +30,8 @@ dependencies:
specifier: ^0.32.1
version: 0.32.2
'@dydxprotocol/v4-abacus':
specifier: ^1.4.6
version: 1.4.6
specifier: ^1.4.9
version: 1.4.9
'@dydxprotocol/v4-client-js':
specifier: ^1.0.20
version: 1.0.20
@@ -1290,8 +1290,8 @@ packages:
resolution: {integrity: sha512-Gg5t+eR7vPJMAmhkFt6CZrzPd0EKpAslWwk5rFVYZpJsM8JG5KT9XQ99hgNM3Ov6ScNoIWbXkpX27F6A9cXR4Q==}
dev: false
/@dydxprotocol/v4-abacus@1.4.6:
resolution: {integrity: sha512-qYq+4TizcMMxYVXckn0LCucWBe5N9ZNtD1XnowCAuBUUifHSgMGvao5OeZIKMgNM/udSKOXLss4zLy6dH/G2SA==}
/@dydxprotocol/v4-abacus@1.4.9:
resolution: {integrity: sha512-OnrD5Db7AGSxyQE+gWRmkBuXbkZMfSEDB+v2s+ft0zgd4D5j/WTZkk1RG0fn8ISV4AffoN5T24jBWxLfqVlmZw==}
dev: false
/@dydxprotocol/v4-client-js@1.0.20:
-1
View File
@@ -11,7 +11,6 @@ export enum DialogTypes {
ExternalNavKeplr = 'ExternalNavKeplr',
MnemonicExport = 'MnemonicExport',
MobileSignIn = 'MobileSignIn',
MobileDownload = 'MobileDownload',
Onboarding = 'Onboarding',
OrderDetails = 'OrderDetails',
Preferences = 'Preferences',
+30 -26
View File
@@ -9,14 +9,16 @@ import type { ChartLine, TvWidget } from '@/constants/tvchart';
import { useStringGetter } from '@/hooks';
import { getCurrentMarketOrders, getCurrentMarketPositionData } from '@/state/accountSelectors';
import {
getCurrentMarketOrders,
getCurrentMarketPositionData,
getIsAccountConnected,
} from '@/state/accountSelectors';
import { getAppTheme, getAppColorMode } from '@/state/configsSelectors';
import { MustBigNumber } from '@/lib/numbers';
import { getChartLineColors } from '@/lib/tradingView/utils';
let chartLines: Record<string, ChartLine> = {};
/**
* @description Hook to handle drawing chart lines
*/
@@ -25,43 +27,47 @@ export const useChartLines = ({
tvWidget,
displayButton,
isChartReady,
chartLinesRef,
}: {
tvWidget: TvWidget | null;
displayButton: HTMLElement | null;
isChartReady?: boolean;
isChartReady: boolean;
chartLinesRef: React.MutableRefObject<Record<string, ChartLine>>;
}) => {
const [showOrderLines, setShowOrderLines] = useState(false);
const [showOrderLines, setShowOrderLines] = useState(true);
const stringGetter = useStringGetter();
const appTheme = useSelector(getAppTheme);
const appColorMode = useSelector(getAppColorMode);
const isAccountConnected = useSelector(getIsAccountConnected);
const currentMarketPositionData = useSelector(getCurrentMarketPositionData, shallowEqual);
const currentMarketOrders: SubaccountOrder[] = useSelector(getCurrentMarketOrders, shallowEqual);
useEffect(() => {
if (isChartReady && displayButton) {
displayButton.onclick = () => {
const newShowOrderLinesState = !showOrderLines;
if (newShowOrderLinesState) {
displayButton?.classList?.add('order-lines-active');
} else {
displayButton?.classList?.remove('order-lines-active');
}
setShowOrderLines(newShowOrderLinesState);
};
displayButton.onclick = () => setShowOrderLines(!showOrderLines);
}
}, [isChartReady, showOrderLines]);
useEffect(() => {
if (tvWidget && isChartReady) {
if (!isAccountConnected) {
deleteChartLines();
}
}, [isAccountConnected]);
useEffect(() => {
if (isChartReady && tvWidget) {
tvWidget.onChartReady(() => {
tvWidget.chart().dataReady(() => {
if (showOrderLines) {
displayButton?.classList?.add('order-lines-active');
drawOrderLines();
drawPositionLine();
} else {
displayButton?.classList?.remove('order-lines-active');
deleteChartLines();
}
});
@@ -78,13 +84,13 @@ export const useChartLines = ({
const key = currentMarketPositionData.id;
const price = MustBigNumber(entryPrice).toNumber();
const maybePositionLine = chartLines[key]?.line;
const maybePositionLine = chartLinesRef.current[key]?.line;
const shouldShow = size && size !== 0;
if (!shouldShow) {
if (maybePositionLine) {
maybePositionLine.remove();
delete chartLines[key];
delete chartLinesRef.current[key];
return;
}
} else {
@@ -106,9 +112,9 @@ export const useChartLines = ({
.setQuantity(quantity);
if (positionLine) {
const chartLine = { line: positionLine, chartLineType: 'position' };
const chartLine: ChartLine = { line: positionLine, chartLineType: 'position' };
setLineColors({ chartLine: chartLine });
chartLines[key] = chartLine;
chartLinesRef.current[key] = chartLine;
}
}
}
@@ -143,12 +149,12 @@ export const useChartLines = ({
!cancelReason &&
(status === AbacusOrderStatus.open || status === AbacusOrderStatus.untriggered);
const maybeOrderLine = chartLines[key]?.line;
const maybeOrderLine = chartLinesRef.current[key]?.line;
if (!shouldShow) {
if (maybeOrderLine) {
maybeOrderLine.remove();
delete chartLines[key];
delete chartLinesRef.current[key];
return;
}
} else {
@@ -170,7 +176,7 @@ export const useChartLines = ({
chartLineType: ORDER_SIDES[side.name],
};
setLineColors({ chartLine: chartLine });
chartLines[key] = chartLine;
chartLinesRef.current[key] = chartLine;
}
}
}
@@ -179,10 +185,10 @@ export const useChartLines = ({
};
const deleteChartLines = () => {
Object.values(chartLines).forEach(({ line }) => {
Object.values(chartLinesRef.current).forEach(({ line }) => {
line.remove();
});
chartLines = {};
chartLinesRef.current = {};
};
const setLineColors = ({ chartLine }: { chartLine: ChartLine }) => {
@@ -204,6 +210,4 @@ export const useChartLines = ({
maybeQuantityColor &&
line.setLineColor(maybeQuantityColor).setQuantityBackgroundColor(maybeQuantityColor);
};
return { chartLines };
};
@@ -38,7 +38,7 @@ export const useChartMarketAndResolution = ({
* @description Hook to handle changing markets - intentionally should avoid triggering on change of resolutions.
*/
useEffect(() => {
if (currentMarketId && isWidgetReady) {
if (isWidgetReady && currentMarketId !== tvWidget?.activeChart().symbol()) {
const resolution = savedResolution || selectedResolution;
tvWidget?.setSymbol(currentMarketId, resolution as ResolutionString, () => {});
}
-2
View File
@@ -31,7 +31,6 @@ import { FillDetailsDialog } from '@/views/dialogs/DetailsDialog/FillDetailsDial
import { NewMarketMessageDetailsDialog } from '@/views/dialogs/NewMarketMessageDetailsDialog';
import { NewMarketAgreementDialog } from '@/views/dialogs/NewMarketAgreementDialog';
import { ExternalNavStrideDialog } from '@/views/dialogs/ExternalNavStrideDialog';
import { MobileDownloadDialog } from '@/views/dialogs/MobileDownloadDialog';
export const DialogManager = () => {
const dispatch = useDispatch();
@@ -64,7 +63,6 @@ export const DialogManager = () => {
[DialogTypes.ExternalNavStride]: <ExternalNavStrideDialog {...modalProps} />,
[DialogTypes.MnemonicExport]: <MnemonicExportDialog {...modalProps} />,
[DialogTypes.MobileSignIn]: <MobileSignInDialog {...modalProps} />,
[DialogTypes.MobileDownload]: <MobileDownloadDialog {...modalProps} />,
[DialogTypes.Onboarding]: <OnboardingDialog {...modalProps} />,
[DialogTypes.OrderDetails]: <OrderDetailsDialog {...modalProps} />,
[DialogTypes.Preferences]: <PreferencesDialog {...modalProps} />,
+5 -2
View File
@@ -4,7 +4,7 @@ import styled, { type AnyStyledComponent, css } from 'styled-components';
import type { ResolutionString } from 'public/tradingview/charting_library';
import type { TvWidget } from '@/constants/tvchart';
import type { ChartLine, TvWidget } from '@/constants/tvchart';
import {
useChartLines,
@@ -27,13 +27,16 @@ export const TvChart = () => {
const displayButtonRef = useRef<HTMLElement | null>(null);
const displayButton = displayButtonRef.current;
const chartLinesRef = useRef<Record<string, ChartLine>>({});
const chartLines = chartLinesRef.current;
const { savedResolution } = useTradingView({ tvWidgetRef, displayButtonRef, setIsChartReady });
useChartMarketAndResolution({
tvWidget,
isWidgetReady,
savedResolution: savedResolution as ResolutionString | undefined,
});
const { chartLines } = useChartLines({ tvWidget, displayButton, isChartReady });
useChartLines({ tvWidget, displayButton, isChartReady, chartLinesRef });
useTradingViewTheme({ tvWidget, isWidgetReady, chartLines });
return (
-140
View File
@@ -1,140 +0,0 @@
import styled, { AnyStyledComponent, css } from 'styled-components';
import { layoutMixins } from '@/styles/layoutMixins';
import { Dialog } from '@/components/Dialog';
import { QrCode } from '@/components/QrCode';
import { useStringGetter } from '@/hooks';
import { STRING_KEYS } from '@/constants/localization';
type ElementProps = {
setIsOpen: (open: boolean) => void;
};
/*
When/if deployer deploys the web app with smartbanner, "smartbanner:button-url-apple" and/or
"smartbanner:button-url-google" <meta> are set.
This implementation assumes "smartbanner:button-url-apple" and "smartbanner:button-url-google"
are set to the same value with onelink or other redirect URL.
Since there is no way for the desktop web app to know what mobile device the user is using,
we should give a onelink URL which redirects to either iOS or Android app store depending on
the mobile device used to scan the link.
*/
// for testing only
// export const mobileAppUrl = "http://example.com";
let mobileAppUrl: string | undefined | null = undefined;
export const getMobileAppUrl = () => {
if (!mobileAppUrl) {
mobileAppUrl =
// for testing to verify <meta> is retrieved by name, QR code should show "@dYdX" as value
// document.querySelector('meta[name="twitter:creator"]')?.getAttribute('content') ??
document.querySelector('meta[name="smartbanner:button-url-apple"]')?.getAttribute('content') ??
document.querySelector('meta[name="smartbanner:button-url-google"]')?.getAttribute('content');
}
return mobileAppUrl;
}
const MobileQrCode = ({
url,
}: {
url: string;
}) => {
return (
<Styled.QrCodeContainer isShowing={true}>
<QrCode hasLogo size={432} value={url} />
</Styled.QrCodeContainer>
);
};
/*
MobileDownloadDialog should only been shown on desktop when mobileAppUrl has value. That's controlled by AccountMenu.tsx.
*/
export const MobileDownloadDialog = ({ setIsOpen }: ElementProps) => {
const stringGetter = useStringGetter();
const content = (
<MobileQrCode url={mobileAppUrl!} />
);
return (
<Dialog isOpen setIsOpen={setIsOpen} title={
stringGetter({ key: STRING_KEYS.DOWNLOAD_MOBILE_APP })
}>
<Styled.Content>{content}</Styled.Content>
</Dialog>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Content = styled.div`
${layoutMixins.column}
gap: 1rem;
strong {
font-weight: 900;
color: var(--color-text-2);
}
footer {
${layoutMixins.row}
justify-content: space-between;
svg {
width: auto;
}
}
`;
Styled.WaitingSpan = styled.span`
strong {
color: var(--color-warning);
}
`;
Styled.QrCodeContainer = styled.figure<{ isShowing: boolean }>`
${layoutMixins.stack}
overflow: hidden;
border-radius: 0.75em;
cursor: pointer;
transition: 0.2s;
&:hover {
filter: brightness(var(--hover-filter-base));
}
> * {
position: relative;
transition: 0.16s;
}
> :first-child {
pointer-events: none;
${({ isShowing }) =>
!isShowing &&
css`
filter: blur(1rem) brightness(1.4);
will-change: filter;
`}
}
> span {
place-self: center;
font-size: 1.4em;
color: var(--color-text-2);
${({ isShowing }) =>
isShowing &&
css`
opacity: 0;
`}
}
`;
-13
View File
@@ -40,7 +40,6 @@ import { getAppTheme } from '@/state/configsSelectors';
import { isTruthy } from '@/lib/isTruthy';
import { truncateAddress } from '@/lib/wallet';
import { MustBigNumber } from '@/lib/numbers';
import { getMobileAppUrl } from '../dialogs/MobileDownloadDialog';
export const AccountMenu = () => {
const stringGetter = useStringGetter();
@@ -190,18 +189,6 @@ export const AccountMenu = () => {
label: stringGetter({ key: STRING_KEYS.DISPLAY_SETTINGS }),
onSelect: () => dispatch(openDialog({ type: DialogTypes.DisplaySettings })),
},
...(getMobileAppUrl()
? [
{
value: 'MobileDownload',
icon: <Icon iconName={IconName.Qr} />,
label: stringGetter({ key: STRING_KEYS.DOWNLOAD_MOBILE_APP }),
onSelect: () => {
dispatch(openDialog({ type: DialogTypes.MobileDownload }));
},
},
]
: []),
...(onboardingState === OnboardingState.AccountConnected && hdKey
? [
{