Compare commits

..
Author SHA1 Message Date
Rui be57b2facf Change iOS app scheme to dydx-t-v4 2024-01-25 05:37:02 -08:00
22 changed files with 106 additions and 422 deletions
+3 -3
View File
@@ -39,9 +39,9 @@
"@cosmjs/proto-signing": "^0.32.1", "@cosmjs/proto-signing": "^0.32.1",
"@cosmjs/stargate": "^0.32.1", "@cosmjs/stargate": "^0.32.1",
"@cosmjs/tendermint-rpc": "^0.32.1", "@cosmjs/tendermint-rpc": "^0.32.1",
"@dydxprotocol/v4-abacus": "^1.3.2", "@dydxprotocol/v4-abacus": "^1.2.5",
"@dydxprotocol/v4-client-js": "^1.0.17", "@dydxprotocol/v4-client-js": "^1.0.14",
"@dydxprotocol/v4-localization": "^1.1.17", "@dydxprotocol/v4-localization": "^1.1.11",
"@ethersproject/providers": "^5.7.2", "@ethersproject/providers": "^5.7.2",
"@js-joda/core": "^5.5.3", "@js-joda/core": "^5.5.3",
"@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-accordion": "^1.1.2",
+12 -12
View File
@@ -27,14 +27,14 @@ dependencies:
specifier: ^0.32.1 specifier: ^0.32.1
version: 0.32.2 version: 0.32.2
'@dydxprotocol/v4-abacus': '@dydxprotocol/v4-abacus':
specifier: ^1.3.2 specifier: ^1.2.5
version: 1.3.2 version: 1.2.5
'@dydxprotocol/v4-client-js': '@dydxprotocol/v4-client-js':
specifier: ^1.0.17 specifier: ^1.0.14
version: 1.0.17 version: 1.0.14
'@dydxprotocol/v4-localization': '@dydxprotocol/v4-localization':
specifier: ^1.1.17 specifier: ^1.1.11
version: 1.1.17 version: 1.1.11
'@ethersproject/providers': '@ethersproject/providers':
specifier: ^5.7.2 specifier: ^5.7.2
version: 5.7.2 version: 5.7.2
@@ -1086,12 +1086,12 @@ packages:
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==} resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
dev: true dev: true
/@dydxprotocol/v4-abacus@1.3.2: /@dydxprotocol/v4-abacus@1.2.5:
resolution: {integrity: sha512-zo0IHjGMlJRKOYDgNqNFQ9GtBJKJP4+Y9YY7V0X3Wt61ppKAYzodaYQhc9V/RYchcZTtS/xkicLug444YrvehQ==} resolution: {integrity: sha512-pB3Fv1bzJRUDp29kAN61daZ34gTSGrSTNh+/AP3TUB63/Q/gaXQVBf91xVcso4Hw23xM3FwIcrRK0cvOSWgXKg==}
dev: false dev: false
/@dydxprotocol/v4-client-js@1.0.17: /@dydxprotocol/v4-client-js@1.0.14:
resolution: {integrity: sha512-PbTKbzcS7VapuFRofkirUxkF9ThNS2tWYyr0asFOMUfebsQWMvTC1sYC/s1NZIiBeq3cFz9vKdZFbfsKi7Z1bw==} resolution: {integrity: sha512-nIjj9OKuXb3n3rrihDPkBE6OIBxXNB7gf0NMsrG1Pc9O7M0yjpitTUgnfIzplf0XMrtmozWRYZhlLgBfJcIbBg==}
dependencies: dependencies:
'@cosmjs/amino': 0.32.2 '@cosmjs/amino': 0.32.2
'@cosmjs/encoding': 0.32.2 '@cosmjs/encoding': 0.32.2
@@ -1119,8 +1119,8 @@ packages:
- utf-8-validate - utf-8-validate
dev: false dev: false
/@dydxprotocol/v4-localization@1.1.17: /@dydxprotocol/v4-localization@1.1.11:
resolution: {integrity: sha512-kal1LrcihLMEv5YxaA/hd6Zl10Mp3x6jicoXDcXvtyNdrczAl3YapyI2nmeifRAPvfueOaY3W/sKkm2BiSKSsA==} resolution: {integrity: sha512-ZHnyrWD1bEpvY1tctkcmSV6A5+hQSYBFwyjbiyOqepqDqrv24J5a3hlZU94lDyYf+7Sdk3alOvy9Z7Lpk59nvw==}
dev: false dev: false
/@dydxprotocol/v4-proto@3.0.0-dev.0: /@dydxprotocol/v4-proto@3.0.0-dev.0:
-8
View File
@@ -1,8 +0,0 @@
[
{
"name": "coinbase",
"label": "Coinbase",
"icon": "/exchanges/coinbase.png",
"depositType": "noble"
}
]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

+2 -10
View File
@@ -5,7 +5,7 @@ import { Checkbox, CheckboxProps } from '@/components/Checkbox';
import { StoryWrapper } from '.ladle/components'; import { StoryWrapper } from '.ladle/components';
export const CheckboxStory: Story<CheckboxProps> = (args) => { export const Checkboxes: Story<CheckboxProps> = (args) => {
const [isChecked, setIsChecked] = useState(false); const [isChecked, setIsChecked] = useState(false);
return ( return (
@@ -21,12 +21,4 @@ export const CheckboxStory: Story<CheckboxProps> = (args) => {
); );
}; };
CheckboxStory.args = {}; Checkboxes.args = {};
CheckboxStory.argTypes = {
disabled: {
options: [true, false],
control: { type: 'select' },
defaultValue: false,
}
}
+4 -20
View File
@@ -1,4 +1,4 @@
import styled, { css, type AnyStyledComponent } from 'styled-components'; import styled, { type AnyStyledComponent } from 'styled-components';
import { Root, Indicator } from '@radix-ui/react-checkbox'; import { Root, Indicator } from '@radix-ui/react-checkbox';
import { CheckIcon } from '@radix-ui/react-icons'; import { CheckIcon } from '@radix-ui/react-icons';
@@ -9,7 +9,6 @@ type ElementProps = {
onCheckedChange: (checked: boolean) => void; onCheckedChange: (checked: boolean) => void;
id?: string; id?: string;
label?: React.ReactNode; label?: React.ReactNode;
disabled?: boolean;
}; };
type StyleProps = { type StyleProps = {
@@ -24,15 +23,14 @@ export const Checkbox: React.FC<CheckboxProps> = ({
onCheckedChange, onCheckedChange,
id, id,
label, label,
disabled
}) => ( }) => (
<Styled.Container> <Styled.Container>
<Styled.Root className={className} checked={checked} disabled={disabled} onCheckedChange={onCheckedChange} id={id}> <Styled.Root className={className} checked={checked} onCheckedChange={onCheckedChange} id={id}>
<Styled.Indicator> <Styled.Indicator>
<CheckIcon /> <CheckIcon />
</Styled.Indicator> </Styled.Indicator>
</Styled.Root> </Styled.Root>
{label && <Styled.label disabled={disabled} htmlFor={id}>{label}</Styled.label>} {label && <label htmlFor={id}>{label}</label>}
</Styled.Container> </Styled.Container>
); );
@@ -50,23 +48,17 @@ Styled.Container = styled.div`
Styled.Root = styled(Root)` Styled.Root = styled(Root)`
--checkbox-backgroundColor: var(--color-layer-0); --checkbox-backgroundColor: var(--color-layer-0);
--checkbox-borderColor: var(--color-border);
min-width: 1.25rem; min-width: 1.25rem;
height: 1.25rem; height: 1.25rem;
border-radius: 0.375rem; border-radius: 0.375rem;
border: var(--border-width) solid var(--checkbox-borderColor); border: var(--border-width) solid var(--color-border);
background-color: var(--checkbox-backgroundColor); background-color: var(--checkbox-backgroundColor);
&[data-state='checked'] { &[data-state='checked'] {
--checkbox-backgroundColor: var(--color-accent); --checkbox-backgroundColor: var(--color-accent);
} }
&[data-disabled] {
cursor: not-allowed;
--checkbox-backgroundColor: var(--color-layer-1);
}
`; `;
Styled.Indicator = styled(Indicator)` Styled.Indicator = styled(Indicator)`
@@ -76,11 +68,3 @@ Styled.Indicator = styled(Indicator)`
color: var(--color-text-2); color: var(--color-text-2);
`; `;
Styled.label = styled.div<{ disabled: boolean; }>`
color: var(--color-text-2);
${({disabled}) => disabled && css`
color: var(--color-text-0);
`}
`;
+2 -3
View File
@@ -11,7 +11,6 @@ type ElementProps = {
}; };
type StyleProps = { type StyleProps = {
className?: string;
hasLogo?: boolean; hasLogo?: boolean;
size?: number; size?: number;
}; };
@@ -19,7 +18,7 @@ type StyleProps = {
const DARK_LOGO_MARK_URL = '/logos/logo-mark-dark.svg'; const DARK_LOGO_MARK_URL = '/logos/logo-mark-dark.svg';
const LIGHT_LOGO_MARK_URL = '/logos/logo-mark-light.svg'; const LIGHT_LOGO_MARK_URL = '/logos/logo-mark-light.svg';
export const QrCode = ({ className, value, hasLogo, size = 300 }: ElementProps & StyleProps) => { export const QrCode = ({ value, hasLogo, size = 300 }: ElementProps & StyleProps) => {
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
const appTheme: AppTheme = useSelector(getAppTheme); const appTheme: AppTheme = useSelector(getAppTheme);
@@ -75,7 +74,7 @@ export const QrCode = ({ className, value, hasLogo, size = 300 }: ElementProps &
} }
}, [appTheme, hasLogo]); }, [appTheme, hasLogo]);
return <Styled.QrCode className={className} ref={ref} />; return <Styled.QrCode ref={ref} />;
}; };
const Styled: Record<string, AnyStyledComponent> = {}; const Styled: Record<string, AnyStyledComponent> = {};
+4 -5
View File
@@ -125,7 +125,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
selectionMode = 'single', selectionMode = 'single',
selectionBehavior = 'toggle', selectionBehavior = 'toggle',
slotEmpty, slotEmpty,
initialNumRowsToShow, initialNumRowsToShow = data.length,
// shouldRowRender, // shouldRowRender,
// collection, // collection,
@@ -142,7 +142,6 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
}: ElementProps<TableRowData, TableRowKey> & StyleProps) => { }: ElementProps<TableRowData, TableRowKey> & StyleProps) => {
const [selectedKeys, setSelectedKeys] = useState(new Set<TableRowKey>()); const [selectedKeys, setSelectedKeys] = useState(new Set<TableRowKey>());
const [numRowsToShow, setNumRowsToShow] = useState(initialNumRowsToShow); const [numRowsToShow, setNumRowsToShow] = useState(initialNumRowsToShow);
const enableViewMore = numRowsToShow !== undefined;
const currentBreakpoints = useBreakpoints(); const currentBreakpoints = useBreakpoints();
const shownColumns = columns.filter( const shownColumns = columns.filter(
@@ -218,7 +217,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
} }
numColumns={shownColumns.length} numColumns={shownColumns.length}
onViewMoreClick={ onViewMoreClick={
enableViewMore && numRowsToShow < data.length numRowsToShow !== undefined && numRowsToShow < data.length
? () => setNumRowsToShow(data.length) ? () => setNumRowsToShow(data.length)
: undefined : undefined
} }
@@ -246,7 +245,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
)} )}
</TableHeader> </TableHeader>
<TableBody items={enableViewMore ? list.items.slice(0, numRowsToShow) : list.items}> <TableBody items={list.items.slice(0, numRowsToShow)}>
{(item) => ( {(item) => (
<Row key={getRowKey(item)}> <Row key={getRowKey(item)}>
{(columnKey) => ( {(columnKey) => (
@@ -983,4 +982,4 @@ Styled.ViewMoreButton = styled(Button)`
width: 0.675rem; width: 0.675rem;
margin-left: 0.5ch; margin-left: 0.5ch;
} }
`; `;
-4
View File
@@ -8,7 +8,6 @@ import { Button, type ButtonStateConfig, type ButtonProps } from '@/components/B
type ElementProps = { type ElementProps = {
timeoutInSeconds: number; timeoutInSeconds: number;
slotFinal?: ReactNode;
} & ButtonProps; } & ButtonProps;
export type TimeoutButtonProps = ElementProps; export type TimeoutButtonProps = ElementProps;
@@ -16,7 +15,6 @@ export type TimeoutButtonProps = ElementProps;
export const TimeoutButton = ({ export const TimeoutButton = ({
children, children,
timeoutInSeconds, timeoutInSeconds,
slotFinal,
...otherProps ...otherProps
}: TimeoutButtonProps) => { }: TimeoutButtonProps) => {
const [timeoutDeadline] = useState(Date.now() + timeoutInSeconds * 1000); const [timeoutDeadline] = useState(Date.now() + timeoutInSeconds * 1000);
@@ -25,8 +23,6 @@ export const TimeoutButton = ({
const secondsLeft = Math.max(0, (timeoutDeadline - now) / 1000); const secondsLeft = Math.max(0, (timeoutDeadline - now) / 1000);
if (slotFinal && secondsLeft <= 0) return slotFinal;
return ( return (
<Button <Button
{...otherProps} {...otherProps}
-12
View File
@@ -138,10 +138,6 @@ export const tradeTooltips: TooltipStrings = {
title: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TITLE }), title: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_BODY }), body: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_BODY }),
}), }),
'post-only-timeinforce-gtt': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TIMEINFORCE_GTT_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TIMEINFORCE_GTT_BODY }),
}),
'price-impact': ({ stringGetter }) => ({ 'price-impact': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.PRICE_IMPACT_TITLE }), title: stringGetter({ key: TOOLTIP_STRING_KEYS.PRICE_IMPACT_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.PRICE_IMPACT_BODY }), body: stringGetter({ key: TOOLTIP_STRING_KEYS.PRICE_IMPACT_BODY }),
@@ -155,14 +151,6 @@ export const tradeTooltips: TooltipStrings = {
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_BODY }), body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_BODY }),
learnMoreLink: urlConfigs?.reduceOnlyLearnMore, learnMoreLink: urlConfigs?.reduceOnlyLearnMore,
}), }),
'reduce-only-execution-ioc-fok': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_EXECUTION_IOC_FOK_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_EXECUTION_IOC_FOK_BODY }),
}),
'reduce-only-timeinforce-ioc-fok': ({ stringGetter }) => ({
title: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_TIMEINFORCE_IOC_FOK_TITLE }),
body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_TIMEINFORCE_IOC_FOK_BODY }),
}),
spread: () => ({ spread: () => ({
title: 'Spread', title: 'Spread',
body: 'The difference in price between the highest bid (the price a buyer is willing to buy for) and lowest ask (the price a seller is willing to sell for) an asset.', body: 'The difference in price between the highest bid (the price a buyer is willing to buy for) and lowest ask (the price a seller is willing to sell for) an asset.',
+1 -13
View File
@@ -33,7 +33,6 @@ export enum WalletConnectionType {
CosmosSigner = 'CosmosSigner', CosmosSigner = 'CosmosSigner',
InjectedEip1193 = 'injectedEip1193', InjectedEip1193 = 'injectedEip1193',
WalletConnect2 = 'walletConnect2', WalletConnect2 = 'walletConnect2',
TestWallet = 'TestWallet',
} }
export enum WalletErrorType { export enum WalletErrorType {
@@ -69,9 +68,6 @@ export const walletConnectionTypes: Record<WalletConnectionType, WalletConnectio
[WalletConnectionType.CosmosSigner]: { [WalletConnectionType.CosmosSigner]: {
name: 'CosmosSigner', name: 'CosmosSigner',
}, },
[WalletConnectionType.TestWallet]: {
name: 'TestWallet',
},
}; };
// Wallets // Wallets
@@ -92,7 +88,7 @@ export enum WalletType {
TokenPocket = 'TOKEN_POCKET', TokenPocket = 'TOKEN_POCKET',
TrustWallet = 'TRUST_WALLET', TrustWallet = 'TRUST_WALLET',
WalletConnect2 = 'WALLETCONNECT_2', WalletConnect2 = 'WALLETCONNECT_2',
TestWallet = 'TEST_WALLET', // TestWallet = 'TEST_WALLET',
OtherWallet = 'OTHER_WALLET', OtherWallet = 'OTHER_WALLET',
} }
@@ -247,12 +243,6 @@ export const wallets: Record<WalletType, WalletConfig> = {
icon: KeplrIcon, icon: KeplrIcon,
connectionTypes: [WalletConnectionType.CosmosSigner], connectionTypes: [WalletConnectionType.CosmosSigner],
}, },
[WalletType.TestWallet]: {
type: WalletType.TestWallet,
stringKey: STRING_KEYS.TEST_WALLET,
icon: GenericWalletIcon,
connectionTypes: [WalletConnectionType.TestWallet],
},
}; };
// Injected EIP-1193 Providers // Injected EIP-1193 Providers
@@ -364,5 +354,3 @@ export enum DydxChainAsset {
USDC = 'usdc', USDC = 'usdc',
CHAINTOKEN = 'chain', CHAINTOKEN = 'chain',
} }
export const TEST_WALLET_EVM_ADDRESS: EvmAddress = '0x0000000000000000000000000000000000000000';
+2 -37
View File
@@ -6,22 +6,14 @@ import { NOBLE_BECH32_PREFIX, LocalWallet, type Subaccount } from '@dydxprotocol
import { OnboardingGuard, OnboardingState, type EvmDerivedAddresses } from '@/constants/account'; import { OnboardingGuard, OnboardingState, type EvmDerivedAddresses } from '@/constants/account';
import { DialogTypes } from '@/constants/dialogs'; import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization';
import { LocalStorageKey, LOCAL_STORAGE_VERSIONS } from '@/constants/localStorage'; import { LocalStorageKey, LOCAL_STORAGE_VERSIONS } from '@/constants/localStorage';
import { import { DydxAddress, EvmAddress, PrivateInformation } from '@/constants/wallets';
DydxAddress,
EvmAddress,
PrivateInformation,
TEST_WALLET_EVM_ADDRESS,
WalletType,
} from '@/constants/wallets';
import { setOnboardingState, setOnboardingGuard } from '@/state/account'; import { setOnboardingState, setOnboardingGuard } from '@/state/account';
import { forceOpenDialog } from '@/state/dialogs'; import { forceOpenDialog } from '@/state/dialogs';
import abacusStateManager from '@/lib/abacus'; import abacusStateManager from '@/lib/abacus';
import { log } from '@/lib/telemetry'; import { log } from '@/lib/telemetry';
import { testFlags } from '@/lib/testFlags';
import { useDydxClient } from './useDydxClient'; import { useDydxClient } from './useDydxClient';
import { useLocalStorage } from './useLocalStorage'; import { useLocalStorage } from './useLocalStorage';
@@ -161,7 +153,6 @@ const useAccountsContext = () => {
// dYdX wallet / onboarding state // dYdX wallet / onboarding state
const [localDydxWallet, setLocalDydxWallet] = useState<LocalWallet>(); const [localDydxWallet, setLocalDydxWallet] = useState<LocalWallet>();
const [localNobleWallet, setLocalNobleWallet] = useState<LocalWallet>();
const [hdKey, setHdKey] = useState<PrivateInformation>(); const [hdKey, setHdKey] = useState<PrivateInformation>();
const dydxAccounts = useMemo(() => localDydxWallet?.accounts, [localDydxWallet]); const dydxAccounts = useMemo(() => localDydxWallet?.accounts, [localDydxWallet]);
@@ -171,11 +162,6 @@ const useAccountsContext = () => {
[localDydxWallet] [localDydxWallet]
); );
const nobleAddress = useMemo(
() => localNobleWallet?.address,
[localNobleWallet]
);
const setWalletFromEvmSignature = async (signature: string) => { const setWalletFromEvmSignature = async (signature: string) => {
const { wallet, mnemonic, privateKey, publicKey } = await getWalletFromEvmSignature({ const { wallet, mnemonic, privateKey, publicKey } = await getWalletFromEvmSignature({
signature, signature,
@@ -192,26 +178,7 @@ const useAccountsContext = () => {
useEffect(() => { useEffect(() => {
(async () => { (async () => {
if (walletType === WalletType.TestWallet) { if (connectedDydxAddress && signerGraz) {
// Get override values. Use the testFlags value if it exists, otherwise use the previously
// saved value where possible. If neither exist, use a default garbage value.
const addressOverride: DydxAddress = testFlags.addressOverride as DydxAddress ||
evmDerivedAddresses?.[TEST_WALLET_EVM_ADDRESS]?.dydxAddress as DydxAddress ||
'dydx1';
dispatch(setOnboardingState(OnboardingState.WalletConnected));
// Set variables.
saveEvmDerivedAccount({
evmAddress: TEST_WALLET_EVM_ADDRESS,
dydxAddress: addressOverride,
});
const wallet = new LocalWallet();
wallet.address = addressOverride;
setLocalDydxWallet(wallet);
dispatch(setOnboardingState(OnboardingState.AccountConnected));
} else if (connectedDydxAddress && signerGraz) {
dispatch(setOnboardingState(OnboardingState.WalletConnected)); dispatch(setOnboardingState(OnboardingState.WalletConnected));
try { try {
setLocalDydxWallet(await LocalWallet.fromOfflineSigner(signerGraz)); setLocalDydxWallet(await LocalWallet.fromOfflineSigner(signerGraz));
@@ -257,7 +224,6 @@ const useAccountsContext = () => {
if (hdKey?.mnemonic) { if (hdKey?.mnemonic) {
const nobleWallet = await LocalWallet.fromMnemonic(hdKey.mnemonic, NOBLE_BECH32_PREFIX); const nobleWallet = await LocalWallet.fromMnemonic(hdKey.mnemonic, NOBLE_BECH32_PREFIX);
abacusStateManager.setNobleWallet(nobleWallet); abacusStateManager.setNobleWallet(nobleWallet);
setLocalNobleWallet(nobleWallet);
} }
}; };
setNobleWallet(); setNobleWallet();
@@ -356,7 +322,6 @@ const useAccountsContext = () => {
localDydxWallet, localDydxWallet,
dydxAccounts, dydxAccounts,
dydxAddress, dydxAddress,
nobleAddress,
// Onboarding state // Onboarding state
saveHasAcknowledgedTerms, saveHasAcknowledgedTerms,
-13
View File
@@ -2,7 +2,6 @@ import { useCallback, useEffect, useState, useMemo } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { EvmDerivedAddresses } from '@/constants/account'; import { EvmDerivedAddresses } from '@/constants/account';
import { STRING_KEYS } from '@/constants/localization';
import { LocalStorageKey } from '@/constants/localStorage'; import { LocalStorageKey } from '@/constants/localStorage';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks'; import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
@@ -39,7 +38,6 @@ import { getWalletConnection, parseWalletError } from '@/lib/wallet';
import { log } from '@/lib/telemetry'; import { log } from '@/lib/telemetry';
import { useStringGetter } from './useStringGetter'; import { useStringGetter } from './useStringGetter';
import { testFlags } from '@/lib/testFlags';
export const useWalletConnection = () => { export const useWalletConnection = () => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
@@ -140,8 +138,6 @@ export const useWalletConnection = () => {
walletType: cosmosWalletType, walletType: cosmosWalletType,
}); });
} }
} else if (walletConnection.type === WalletConnectionType.TestWallet) {
saveEvmAddress(STRING_KEYS.TEST_WALLET as EvmAddress);
} else { } else {
const isAccountConnected = Boolean( const isAccountConnected = Boolean(
evmAddress && evmDerivedAddresses[evmAddress]?.encryptedSignature evmAddress && evmDerivedAddresses[evmAddress]?.encryptedSignature
@@ -228,15 +224,6 @@ export const useWalletConnection = () => {
setSelectedWalletType(walletType); setSelectedWalletType(walletType);
}; };
// On page load, if testFlag.address is set, connect to the test wallet.
useEffect(() => {
(async () => {
if (testFlags.addressOverride) {
setSelectedWalletType(WalletType.TestWallet);
}
})();
}, []);
return { return {
// Wallet connection // Wallet connection
walletType, walletType,
-8
View File
@@ -22,14 +22,6 @@ class TestFlags {
get showMobileSignInOption() { get showMobileSignInOption() {
return !!this.queryParams.mobilesignin; return !!this.queryParams.mobilesignin;
} }
get addressOverride():string {
return this.queryParams.address;
}
get showCEXDepositOption() {
return !!this.queryParams.cexdeposit;
}
} }
export const testFlags = new TestFlags(); export const testFlags = new TestFlags();
-6
View File
@@ -62,12 +62,6 @@ export const getWalletConnection = ({
type: WalletConnectionType.CosmosSigner, type: WalletConnectionType.CosmosSigner,
}; };
} }
case WalletConnectionType.TestWallet: {
return {
type: WalletConnectionType.TestWallet,
};
}
} }
} }
}; };
-4
View File
@@ -96,8 +96,6 @@ export const useTradeFormData = () => {
needsGoodUntil, needsGoodUntil,
needsPostOnly, needsPostOnly,
needsReduceOnly, needsReduceOnly,
postOnlyTooltip,
reduceOnlyTooltip,
timeInForceOptions, timeInForceOptions,
} = tradeOptions || {}; } = tradeOptions || {};
@@ -113,8 +111,6 @@ export const useTradeFormData = () => {
needsGoodUntil, needsGoodUntil,
needsPostOnly, needsPostOnly,
needsReduceOnly, needsReduceOnly,
postOnlyTooltip,
reduceOnlyTooltip,
timeInForceOptions, timeInForceOptions,
tradeErrors, tradeErrors,
@@ -3,7 +3,6 @@ import { shallowEqual, useSelector } from 'react-redux';
import { TransferType } from '@/constants/abacus'; import { TransferType } from '@/constants/abacus';
import { STRING_KEYS } from '@/constants/localization'; import { STRING_KEYS } from '@/constants/localization';
import { useStringGetter } from '@/hooks'; import { useStringGetter } from '@/hooks';
import { SearchSelectMenu } from '@/components/SearchSelectMenu'; import { SearchSelectMenu } from '@/components/SearchSelectMenu';
@@ -13,78 +12,45 @@ import { popoverMixins } from '@/styles/popoverMixins';
import { getTransferInputs } from '@/state/inputsSelectors'; import { getTransferInputs } from '@/state/inputsSelectors';
import { isTruthy } from '@/lib/isTruthy';
import { testFlags } from '@/lib/testFlags';
type ElementProps = { type ElementProps = {
label?: string; label?: string;
selectedExchange?: string;
selectedChain?: string; selectedChain?: string;
onSelect: (name: string, type: 'chain' | 'exchange') => void; onSelectChain: (chain: string) => void;
}; };
export const SourceSelectMenu = ({ export const ChainSelectMenu = ({ label, selectedChain, onSelectChain }: ElementProps) => {
label,
selectedExchange,
selectedChain,
onSelect,
}: ElementProps) => {
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const { type, depositOptions, withdrawalOptions, resources } = const { type, depositOptions, withdrawalOptions, resources } =
useSelector(getTransferInputs, shallowEqual) || {}; useSelector(getTransferInputs, shallowEqual) || {};
const chains = const chains =
(type === TransferType.deposit ? depositOptions : withdrawalOptions)?.chains?.toArray() || []; (type === TransferType.deposit ? depositOptions : withdrawalOptions)?.chains?.toArray() || [];
const exchanges =
(type === TransferType.deposit ? depositOptions : withdrawalOptions)?.exchanges?.toArray() ||
[];
const chainItems = Object.values(chains).map((chain) => ({ const chainItems = Object.values(chains).map((chain) => ({
value: chain.type, value: chain.type,
label: chain.stringKey, label: chain.stringKey,
onSelect: () => { onSelect: () => {
onSelect(chain.type, 'chain'); onSelectChain(chain.type);
}, },
slotBefore: <Styled.Img src={chain.iconUrl} alt="" />, slotBefore: <Styled.Img src={chain.iconUrl} alt="" />,
})); }));
const exchangeItems = Object.values(exchanges).map((exchange) => ({ const selectedOption = chains.find((item) => item.type === selectedChain);
value: exchange.type,
label: exchange.string,
onSelect: () => {
onSelect(exchange.type, 'exchange');
},
slotBefore: <Styled.Img src={exchange.iconUrl} alt="" />,
}));
const selectedChainOption = chains.find((item) => item.type === selectedChain);
const selectedExchangeOption = exchanges.find((item) => item.type === selectedExchange);
return ( return (
<SearchSelectMenu <SearchSelectMenu
items={[ items={[
exchangeItems.length > 0 && testFlags.showCEXDepositOption && { {
group: 'exchanges',
groupLabel: stringGetter({ key: STRING_KEYS.EXCHANGES }),
items: exchangeItems,
},
chainItems.length > 0 && {
group: 'chains', group: 'chains',
groupLabel: stringGetter({ key: STRING_KEYS.CHAINS }), groupLabel: stringGetter({ key: STRING_KEYS.CHAINS }),
items: chainItems, items: chainItems,
}, },
].filter(isTruthy)} ]}
label={label || (type === TransferType.deposit ? 'Source' : 'Destination')} label={label || (type === TransferType.deposit ? 'Source' : 'Destination')}
> >
<Styled.ChainRow> <Styled.ChainRow>
{selectedChainOption ? ( {selectedChain ? (
<> <>
<Styled.Img src={selectedChainOption.iconUrl} alt="" /> {selectedChainOption.stringKey} <Styled.Img src={selectedOption?.iconUrl} alt="" /> {selectedOption?.stringKey}
</>
) : selectedExchangeOption ? (
<>
<Styled.Img src={selectedExchangeOption.iconUrl} alt="" />{' '}
{selectedExchangeOption.string}
</> </>
) : ( ) : (
stringGetter({ key: STRING_KEYS.SELECT_CHAIN }) stringGetter({ key: STRING_KEYS.SELECT_CHAIN })
@@ -17,6 +17,7 @@ import type { EvmAddress } from '@/constants/wallets';
import { useAccounts, useDebounce, useStringGetter, useSelectedNetwork } from '@/hooks'; import { useAccounts, useDebounce, useStringGetter, useSelectedNetwork } from '@/hooks';
import { useAccountBalance, CHAIN_DEFAULT_TOKEN_ADDRESS } from '@/hooks/useAccountBalance'; import { useAccountBalance, CHAIN_DEFAULT_TOKEN_ADDRESS } from '@/hooks/useAccountBalance';
import { useLocalNotifications } from '@/hooks/useLocalNotifications'; import { useLocalNotifications } from '@/hooks/useLocalNotifications';
import { useWalletConnection } from '@/hooks/useWalletConnection';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
import { formMixins } from '@/styles/formMixins'; import { formMixins } from '@/styles/formMixins';
@@ -40,11 +41,10 @@ import { getNobleChainId, NATIVE_TOKEN_ADDRESS } from '@/lib/squid';
import { log } from '@/lib/telemetry'; import { log } from '@/lib/telemetry';
import { parseWalletError } from '@/lib/wallet'; import { parseWalletError } from '@/lib/wallet';
import { SourceSelectMenu } from './SourceSelectMenu'; import { ChainSelectMenu } from './ChainSelectMenu';
import { TokenSelectMenu } from './TokenSelectMenu'; import { TokenSelectMenu } from './TokenSelectMenu';
import { DepositButtonAndReceipt } from './DepositForm/DepositButtonAndReceipt'; import { DepositButtonAndReceipt } from './DepositForm/DepositButtonAndReceipt';
import { NobleDeposit } from '../NobleDeposit';
type DepositFormProps = { type DepositFormProps = {
onDeposit?: () => void; onDeposit?: () => void;
@@ -57,14 +57,13 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const { selectedNetwork } = useSelectedNetwork(); const { selectedNetwork } = useSelectedNetwork();
const { evmAddress, signerWagmi, publicClientWagmi, nobleAddress } = useAccounts(); const { evmAddress, signerWagmi, publicClientWagmi } = useAccounts();
const { addTransferNotification } = useLocalNotifications(); const { addTransferNotification } = useLocalNotifications();
const { const {
requestPayload, requestPayload,
token, token,
exchange,
chain: chainIdStr, chain: chainIdStr,
resources, resources,
summary, summary,
@@ -130,21 +129,14 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
if (error) onError?.(); if (error) onError?.();
}, [error]); }, [error]);
const onSelectChain = useCallback((name: string, type: 'chain' | 'exchange') => { const onSelectChain = useCallback((chain: string) => {
if (name) { if (chain) {
abacusStateManager.clearTransferInputValues(); abacusStateManager.clearTransferInputValues();
abacusStateManager.setTransferValue({
field: TransferInputField.chain,
value: chain,
});
setFromAmount(''); setFromAmount('');
if (type === 'chain') {
abacusStateManager.setTransferValue({
field: TransferInputField.chain,
value: name,
});
} else {
abacusStateManager.setTransferValue({
field: TransferInputField.exchange,
value: name,
});
}
} }
}, []); }, []);
@@ -377,49 +369,39 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
return ( return (
<Styled.Form onSubmit={onSubmit}> <Styled.Form onSubmit={onSubmit}>
<SourceSelectMenu <ChainSelectMenu selectedChain={chainIdStr || undefined} onSelectChain={onSelectChain} />
selectedChain={chainIdStr || undefined} <TokenSelectMenu selectedToken={sourceToken || undefined} onSelectToken={onSelectToken} />
selectedExchange={exchange || undefined} <Styled.WithDetailsReceipt side="bottom" detailItems={amountInputReceipt}>
onSelect={onSelectChain} <FormInput
/> type={InputType.Number}
{exchange && nobleAddress ? ( onChange={onChangeAmount}
<NobleDeposit /> label={stringGetter({ key: STRING_KEYS.AMOUNT })}
) : ( value={fromAmount}
<> slotRight={
<TokenSelectMenu selectedToken={sourceToken || undefined} onSelectToken={onSelectToken} /> <Styled.FormInputButton size={ButtonSize.XSmall} onClick={onClickMax}>
<Styled.WithDetailsReceipt side="bottom" detailItems={amountInputReceipt}> {stringGetter({ key: STRING_KEYS.MAX })}
<FormInput </Styled.FormInputButton>
type={InputType.Number} }
onChange={onChangeAmount} />
label={stringGetter({ key: STRING_KEYS.AMOUNT })} </Styled.WithDetailsReceipt>
value={fromAmount} {errorMessage && <AlertMessage type={AlertType.Error}>{errorMessage}</AlertMessage>}
slotRight={ {requireUserActionInWallet && (
<Styled.FormInputButton size={ButtonSize.XSmall} onClick={onClickMax}> <AlertMessage type={AlertType.Warning}>
{stringGetter({ key: STRING_KEYS.MAX })} {stringGetter({ key: STRING_KEYS.CHECK_WALLET_FOR_REQUEST })}
</Styled.FormInputButton> </AlertMessage>
}
/>
</Styled.WithDetailsReceipt>
{errorMessage && <AlertMessage type={AlertType.Error}>{errorMessage}</AlertMessage>}
{requireUserActionInWallet && (
<AlertMessage type={AlertType.Warning}>
{stringGetter({ key: STRING_KEYS.CHECK_WALLET_FOR_REQUEST })}
</AlertMessage>
)}
<Styled.Footer>
<DepositButtonAndReceipt
isDisabled={isDisabled}
isLoading={isLoading}
chainId={chainId || undefined}
setSlippage={onSetSlippage}
slippage={slippage}
sourceToken={sourceToken || undefined}
setRequireUserActionInWallet={setRequireUserActionInWallet}
setError={setError}
/>
</Styled.Footer>
</>
)} )}
<Styled.Footer>
<DepositButtonAndReceipt
isDisabled={isDisabled}
isLoading={isLoading}
chainId={chainId || undefined}
setSlippage={onSetSlippage}
slippage={slippage}
sourceToken={sourceToken || undefined}
setRequireUserActionInWallet={setRequireUserActionInWallet}
setError={setError}
/>
</Styled.Footer>
</Styled.Form> </Styled.Form>
); );
}; };
@@ -38,7 +38,7 @@ import { Tag } from '@/components/Tag';
import { WithDetailsReceipt } from '@/components/WithDetailsReceipt'; import { WithDetailsReceipt } from '@/components/WithDetailsReceipt';
import { Icon, IconName } from '@/components/Icon'; import { Icon, IconName } from '@/components/Icon';
import { SourceSelectMenu } from '@/views/forms/AccountManagementForms/SourceSelectMenu'; import { ChainSelectMenu } from '@/views/forms/AccountManagementForms/ChainSelectMenu';
import { getSubaccount } from '@/state/accountSelectors'; import { getSubaccount } from '@/state/accountSelectors';
import { getTransferInputs } from '@/state/inputsSelectors'; import { getTransferInputs } from '@/state/inputsSelectors';
@@ -374,10 +374,10 @@ export const WithdrawForm = () => {
</span> </span>
} }
/> />
<SourceSelectMenu <ChainSelectMenu
label={stringGetter({ key: STRING_KEYS.NETWORK })} label={stringGetter({ key: STRING_KEYS.NETWORK })}
selectedChain={chainIdStr || undefined} selectedChain={chainIdStr || undefined}
onSelect={onSelectChain} onSelectChain={onSelectChain}
/> />
</Styled.DestinationRow> </Styled.DestinationRow>
<TokenSelectMenu selectedToken={toToken || undefined} onSelectToken={onSelectToken} /> <TokenSelectMenu selectedToken={toToken || undefined} onSelectToken={onSelectToken} />
-131
View File
@@ -1,131 +0,0 @@
import { useState } from 'react';
import styled, { type AnyStyledComponent } from 'styled-components';
import { OpacityToken } from '@/constants/styles/base';
import { STRING_KEYS } from '@/constants/localization';
import { layoutMixins } from '@/styles/layoutMixins';
import { useAccounts, useStringGetter } from '@/hooks';
import { CopyButton } from '@/components/CopyButton';
import { QrCode } from '@/components/QrCode';
import { Checkbox } from '@/components/Checkbox';
import { Icon, IconName } from '@/components/Icon';
import { TimeoutButton } from '@/components/TimeoutButton';
import { WithDetailsReceipt } from '@/components/WithDetailsReceipt';
import { WithReceipt } from '@/components/WithReceipt';
import { generateFadedColorVariant } from '@/lib/styles';
export const NobleDeposit = () => {
const [hasAcknowledged, setHasAcknowledged] = useState(false);
const stringGetter = useStringGetter();
const { nobleAddress } = useAccounts();
return (
<>
<WithDetailsReceipt
side="bottom"
detailItems={[
{
key: 'nobleAddress',
label: stringGetter({ key: STRING_KEYS.NOBLE_ADDRESS }),
value: nobleAddress,
},
]}
>
<Styled.QrCodeContainer>
<Styled.QrCode size={432} value={nobleAddress || ''} />
</Styled.QrCodeContainer>
</WithDetailsReceipt>
<Styled.WaitingSpan>
<Styled.CautionIconContainer>
<Icon iconName={IconName.CautionCircleStroked} />
</Styled.CautionIconContainer>
<p>{stringGetter({ key: STRING_KEYS.NOBLE_WARNING })}</p>
</Styled.WaitingSpan>
<Styled.WithReceipt
slotReceipt={
<Styled.CheckboxContainer>
<Checkbox
checked={hasAcknowledged}
onCheckedChange={setHasAcknowledged}
id="acknowledge-secret-phase-risk"
label={stringGetter({
key: STRING_KEYS.NOBLE_ACKNOWLEDGEMENT,
})}
/>
</Styled.CheckboxContainer>
}
>
<TimeoutButton
timeoutInSeconds={8}
slotFinal={<CopyButton state={{ isDisabled: !hasAcknowledged }} value={nobleAddress} />}
/>
</Styled.WithReceipt>
</>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.WaitingSpan = styled.span`
${layoutMixins.row}
gap: 1rem;
color: var(--color-text-1);
`;
Styled.WithReceipt = styled(WithReceipt)`
--withReceipt-backgroundColor: var(--color-layer-2);
`;
Styled.QrCodeContainer = styled.div`
display: flex;
justify-content: center;
padding: 0.5rem;
background-color: var(--color-layer-2);
border-radius: 0.5rem;
`;
Styled.QrCode = styled(QrCode)`
max-height: 20rem;
width: fit-content;
svg {
max-height: 20rem;
}
`;
Styled.CheckboxContainer = styled.div`
padding: 1rem;
color: var(--color-text-0);
`;
Styled.CautionIconContainer = styled.div`
${layoutMixins.stack}
min-width: 2.5rem;
height: 2.5rem;
align-items: center;
border-radius: 50%;
overflow: hidden;
color: var(--color-warning);
svg {
width: 1.125em;
height: 1.125em;
justify-self: center;
}
&:before {
content: '';
width: 2.5rem;
height: 2.5rem;
background-color: ${({ theme }) =>
generateFadedColorVariant(theme.warning, OpacityToken.Opacity16)};
}
`;
+2 -3
View File
@@ -10,6 +10,7 @@ import {
type HumanReadablePlaceOrderPayload, type HumanReadablePlaceOrderPayload,
type Nullable, type Nullable,
TradeInputErrorAction, TradeInputErrorAction,
TradeInputField,
ValidationError, ValidationError,
} from '@/constants/abacus'; } from '@/constants/abacus';
@@ -95,8 +96,6 @@ export const TradeForm = ({
needsGoodUntil, needsGoodUntil,
needsPostOnly, needsPostOnly,
needsReduceOnly, needsReduceOnly,
postOnlyTooltip,
reduceOnlyTooltip,
timeInForceOptions, timeInForceOptions,
tradeErrors, tradeErrors,
} = useTradeFormData(); } = useTradeFormData();
@@ -109,7 +108,7 @@ export const TradeForm = ({
const { limitPriceInput, triggerPriceInput, trailingPercentInput } = tradeFormInputValues; const { limitPriceInput, triggerPriceInput, trailingPercentInput } = tradeFormInputValues;
const needsAdvancedOptions = const needsAdvancedOptions =
needsGoodUntil || timeInForceOptions || executionOptions || (needsPostOnly || postOnlyTooltip) || (needsReduceOnly || reduceOnlyTooltip); needsGoodUntil || timeInForceOptions || executionOptions || needsPostOnly || needsReduceOnly;
const tradeFormInputs: TradeBoxInputConfig[] = []; const tradeFormInputs: TradeBoxInputConfig[] = [];
@@ -31,15 +31,12 @@ export const AdvancedTradeOptions = () => {
const { execution, goodTil, postOnly, reduceOnly, timeInForce, type } = inputTradeData || {}; const { execution, goodTil, postOnly, reduceOnly, timeInForce, type } = inputTradeData || {};
const { executionOptions, needsGoodUntil, needsPostOnly, needsReduceOnly, postOnlyTooltip, reduceOnlyTooltip, timeInForceOptions } = const { executionOptions, needsGoodUntil, needsPostOnly, needsReduceOnly, timeInForceOptions } =
currentTradeFormConfig || {}; currentTradeFormConfig || {};
const { duration, unit } = goodTil || {}; const { duration, unit } = goodTil || {};
const showPostOnly = (needsPostOnly || postOnlyTooltip); const needsExecution = executionOptions || needsPostOnly || needsReduceOnly;
const showReduceOnly = (needsReduceOnly || reduceOnlyTooltip);
const needsExecution = executionOptions || showPostOnly || showReduceOnly;
const hasTimeInForce = timeInForceOptions?.toArray()?.length; const hasTimeInForce = timeInForceOptions?.toArray()?.length;
return ( return (
@@ -132,27 +129,9 @@ export const AdvancedTradeOptions = () => {
))} ))}
</Styled.SelectMenu> </Styled.SelectMenu>
)} )}
{showReduceOnly && <Checkbox {needsPostOnly && (
checked={(reduceOnly && !reduceOnlyTooltip) || false}
disabled={!!reduceOnlyTooltip}
onCheckedChange={(checked) =>
abacusStateManager.setTradeValue({
value: checked,
field: TradeInputField.reduceOnly,
})
}
id="reduce-only"
label={
<WithTooltip tooltip={needsReduceOnly ? "reduce-only" : reduceOnlyTooltip?.titleStringKey.includes("REDUCE_ONLY_EXECUTION_IOC_FOK") ? "reduce-only-execution-ioc-fok" : "reduce-only-timeinforce-ioc-fok"} side="right">
{stringGetter({ key: STRING_KEYS.REDUCE_ONLY })}
</WithTooltip>
}
/>
}
{showPostOnly && (
<Checkbox <Checkbox
checked={(postOnly && !postOnlyTooltip) || false} checked={postOnly || false}
disabled={!!postOnlyTooltip}
onCheckedChange={(checked) => onCheckedChange={(checked) =>
abacusStateManager.setTradeValue({ abacusStateManager.setTradeValue({
value: checked, value: checked,
@@ -161,12 +140,29 @@ export const AdvancedTradeOptions = () => {
} }
id="post-only" id="post-only"
label={ label={
<WithTooltip tooltip={needsPostOnly ? "post-only" : "post-only-timeinforce-gtt"} side="right"> <WithTooltip tooltip="post-only" side="right">
{stringGetter({ key: STRING_KEYS.POST_ONLY })} {stringGetter({ key: STRING_KEYS.POST_ONLY })}
</WithTooltip> </WithTooltip>
} }
/> />
)} )}
{needsReduceOnly && (
<Checkbox
checked={reduceOnly || false}
onCheckedChange={(checked) =>
abacusStateManager.setTradeValue({
value: checked,
field: TradeInputField.reduceOnly,
})
}
id="reduce-only"
label={
<WithTooltip tooltip="reduce-only" side="right">
{stringGetter({ key: STRING_KEYS.REDUCE_ONLY })}
</WithTooltip>
}
/>
)}
</> </>
)} )}
</Styled.AdvancedInputsContainer> </Styled.AdvancedInputsContainer>