From ab1cfe0c922e78c42a95ac27bc690c2e76d51fe3 Mon Sep 17 00:00:00 2001 From: Tyler Date: Thu, 16 Oct 2025 17:13:45 -0400 Subject: [PATCH] stop-updating-compliance --- src/bonsai/rest/compliance.ts | 152 +------------------- src/components/ComplianceBanner.tsx | 13 +- src/constants/dialogs.ts | 2 - src/layout/DialogManager.tsx | 2 - src/views/dialogs/GeoComplianceDialog.tsx | 165 ---------------------- 5 files changed, 5 insertions(+), 329 deletions(-) delete mode 100644 src/views/dialogs/GeoComplianceDialog.tsx diff --git a/src/bonsai/rest/compliance.ts b/src/bonsai/rest/compliance.ts index 2eae2ecb75..38d2d06776 100644 --- a/src/bonsai/rest/compliance.ts +++ b/src/bonsai/rest/compliance.ts @@ -1,29 +1,14 @@ -import { ComplianceV2Response } from '@dydxprotocol/v4-client-js'; - -import { DydxChainId, DydxNetwork, ENVIRONMENT_CONFIG_MAP } from '@/constants/networks'; import { timeUnits } from '@/constants/time'; -import { type AppDispatch, type RootState, type RootStore } from '@/state/_store'; +import { type RootStore } from '@/state/_store'; import { getUserSourceWalletAddress, getUserWalletAddress } from '@/state/accountInfoSelectors'; -import { appQueryClient } from '@/state/appQueryClient'; import { getSelectedDydxChainId, getSelectedNetwork } from '@/state/appSelectors'; import { createAppSelector } from '@/state/appTypes'; -import { - ComplianceErrors, - setLocalAddressScreenV2Raw, - setSourceAddressScreenV2Raw, -} from '@/state/raw'; +import { setLocalAddressScreenV2Raw, setSourceAddressScreenV2Raw } from '@/state/raw'; import { getHdKeyNonce } from '@/state/walletSelectors'; -import { signCompliancePayload } from '@/lib/compliance'; -import { mapIfPresent } from '@/lib/do'; -import { removeTrailingSlash } from '@/lib/stringifyHelpers'; - -import { loadableIdle, loadableLoaded } from '../lib/loadable'; -import { logBonsaiError } from '../logs'; -import { selectRawLocalAddressScreenV2 } from '../selectors/base'; +import { loadableIdle } from '../lib/loadable'; import { ComplianceResponse, ComplianceStatus } from '../types/summaryTypes'; -import { IndexerWebsocketManager } from '../websocket/lib/indexerWebsocketManager'; import { createIndexerQueryStoreEffect } from './lib/indexerQueryStoreEffect'; import { queryResultToLoadable } from './lib/queryResultToLoadable'; @@ -78,85 +63,6 @@ export enum ComplianceAction { INVALID_SURVEY = 'INVALID_SURVEY', } -const COMPLIANCE_PAYLOAD_MESSAGE = 'Verify account ownership'; - -async function updateCompliance({ - chainId, - address, - hdKeyNonce, - network, - status, - action, -}: { - chainId: DydxChainId; - address: string; - hdKeyNonce: number; - network: DydxNetwork; - status: ComplianceStatus; - action: ComplianceAction; -}) { - const networkConfig = ENVIRONMENT_CONFIG_MAP[network]; - const indexerUrl = mapIfPresent( - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - networkConfig?.endpoints.indexers[0]?.api, - removeTrailingSlash - ); - const payload = { - message: COMPLIANCE_PAYLOAD_MESSAGE, - action, - status, - chainId, - }; - - const signingResponse = await signCompliancePayload(address, hdKeyNonce, payload); - if (!signingResponse) { - return { status: ComplianceStatus.UNKNOWN }; - } - - const parsedSigningResponse = JSON.parse(signingResponse); - if (parsedSigningResponse.error != null) { - return { status: ComplianceStatus.UNKNOWN }; - } - - const { signedMessage, publicKey, timestamp, isKeplr } = parsedSigningResponse; - - const urlAddition = isKeplr ? '/v4/compliance/geoblock-keplr' : '/v4/compliance/geoblock'; - const hasMessageAndKey = signedMessage !== null && publicKey !== null; - const isKeplrOrHasTimestamp = timestamp !== null || isKeplr === true; - - if (!hasMessageAndKey || !isKeplrOrHasTimestamp || !indexerUrl) { - return { status: ComplianceStatus.UNKNOWN }; - } - - const body = isKeplr - ? { - address, - message: payload.message, - action: payload.action, - signedMessage, - pubkey: publicKey, - } - : { - address, - message: payload.message, - currentStatus: payload.status, - action: payload.action, - signedMessage, - pubkey: publicKey, - timestamp, - }; - - const options: RequestInit = { - method: 'POST', - headers: new globalThis.Headers([['Content-Type', 'application/json']]), - body: JSON.stringify(body), - }; - - const response = await fetch(`${indexerUrl}${urlAddition}`, options); - const data = await response.json(); - return data as ComplianceV2Response & ComplianceErrors; -} - export function setUpIndexerLocalAddressScreenV2Query(store: RootStore) { const cleanupEffect = createIndexerQueryStoreEffect(store, { name: 'localAddressScreenV2', @@ -167,7 +73,7 @@ export function setUpIndexerLocalAddressScreenV2Query(store: RootStore) { address, network, ], - getQueryFn: (indexerClient, { chainId, address, network, hdKeyNonce }) => { + getQueryFn: (indexerClient, { address, hdKeyNonce }) => { if (address == null || hdKeyNonce == null) { return null; } @@ -181,19 +87,8 @@ export function setUpIndexerLocalAddressScreenV2Query(store: RootStore) { return { status: ComplianceStatus.UNKNOWN }; } - const updateResult = updateCompliance({ - address, - hdKeyNonce, - chainId, - network, - status: firstScreenResult.status, - action: ComplianceAction.CONNECT, - }); - return { ...firstScreenResult, - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - ...(updateResult ?? {}), }; }; }, @@ -208,42 +103,3 @@ export function setUpIndexerLocalAddressScreenV2Query(store: RootStore) { store.dispatch(setLocalAddressScreenV2Raw(loadableIdle())); }; } - -export const triggerCompliance = (action: ComplianceAction) => { - return async (dispatch: AppDispatch, getState: () => RootState) => { - try { - const state = getState(); - const currentLocalScreenStatus = selectRawLocalAddressScreenV2(state).data?.status; - const chainId = getSelectedDydxChainId(state); - const address = getUserWalletAddress(state); - const hdKeyNonce = getHdKeyNonce(state); - const network = getSelectedNetwork(state); - - if (!address || !currentLocalScreenStatus || !hdKeyNonce) { - throw new Error('TriggerCompliance: No account connected or screen status not loaded'); - } - - const result = await updateCompliance({ - chainId, - address, - hdKeyNonce, - network, - status: currentLocalScreenStatus, - action, - }); - - dispatch(setLocalAddressScreenV2Raw(loadableLoaded(result))); - - // force refresh all account information from indexer - IndexerWebsocketManager.getActiveResources().forEach((r) => r.restart()); - appQueryClient.invalidateQueries({ - queryKey: ['indexer', 'account'], - }); - - return true; - } catch (e) { - logBonsaiError('TriggerCompliance', 'failed to update compliance', { error: e }); - return false; - } - }; -}; diff --git a/src/components/ComplianceBanner.tsx b/src/components/ComplianceBanner.tsx index c22359942e..11832f08c1 100644 --- a/src/components/ComplianceBanner.tsx +++ b/src/components/ComplianceBanner.tsx @@ -5,7 +5,6 @@ import styled from 'styled-components'; import { AlertType } from '@/constants/alerts'; import { ButtonSize, ButtonStyle, ButtonType } from '@/constants/buttons'; -import { DialogTypes } from '@/constants/dialogs'; import { STRING_KEYS } from '@/constants/localization'; import { AppRoute, BASE_ROUTE } from '@/constants/routes'; @@ -18,9 +17,6 @@ import { useURLConfigs } from '@/hooks/useURLConfigs'; import breakpoints from '@/styles/breakpoints'; -import { useAppDispatch } from '@/state/appTypes'; -import { openDialog } from '@/state/dialogs'; - import { AlertMessage } from './AlertMessage'; import { Button } from './Button'; import { IconName } from './Icon'; @@ -30,7 +26,6 @@ import { Link } from './Link'; export const ComplianceBanner = ({ className }: { className?: string }) => { const [showLess, setShowLess] = useState(false); const complianceBannerRef = useRef(null); - const dispatch = useAppDispatch(); const stringGetter = useStringGetter(); const { complianceMessage, complianceStatus, showComplianceBanner, showRestrictionWarning } = useComplianceState(); @@ -77,13 +72,7 @@ export const ComplianceBanner = ({ className }: { className?: string }) => { const action = complianceStatus === ComplianceStatus.FIRST_STRIKE_CLOSE_ONLY ? ( - ) : null; diff --git a/src/constants/dialogs.ts b/src/constants/dialogs.ts index 67d7f187c6..8527bb6003 100644 --- a/src/constants/dialogs.ts +++ b/src/constants/dialogs.ts @@ -46,7 +46,6 @@ export type ExternalLinkDialogProps = { }; export type ExternalNavStrideDialogProps = {}; export type FillDetailsDialogProps = { fillId: string }; -export type GeoComplianceDialogProps = {}; export type GlobalCommandDialogProps = {}; export type HelpDialogProps = {}; export type ExternalNavKeplrDialogProps = {}; @@ -143,7 +142,6 @@ export const DialogTypes = unionize( ExternalNavKeplr: ofType(), ExternalNavStride: ofType(), FillDetails: ofType(), - GeoCompliance: ofType(), GlobalCommand: ofType(), Help: ofType(), ManageAccount: ofType(), diff --git a/src/layout/DialogManager.tsx b/src/layout/DialogManager.tsx index 6f50685f00..adbc98fb84 100644 --- a/src/layout/DialogManager.tsx +++ b/src/layout/DialogManager.tsx @@ -25,7 +25,6 @@ import { ExchangeOfflineDialog } from '@/views/dialogs/ExchangeOfflineDialog'; import { ExternalLinkDialog } from '@/views/dialogs/ExternalLinkDialog'; import { ExternalNavKeplrDialog } from '@/views/dialogs/ExternalNavKeplrDialog'; import { ExternalNavStrideDialog } from '@/views/dialogs/ExternalNavStrideDialog'; -import { GeoComplianceDialog } from '@/views/dialogs/GeoComplianceDialog'; import { GlobalCommandDialog } from '@/views/dialogs/GlobalCommandDialog'; import { HelpDialog } from '@/views/dialogs/HelpDialog'; import { ManageAccountDialog } from '@/views/dialogs/ManageAccountDialog/ManageAccountDialog'; @@ -114,7 +113,6 @@ export const DialogManager = React.memo(() => { ExternalLink: (args) => , ExternalNavStride: (args) => , FillDetails: (args) => , - GeoCompliance: (args) => , GlobalCommand: (args) => , Help: (args) => , ExternalNavKeplr: (args) => , diff --git a/src/views/dialogs/GeoComplianceDialog.tsx b/src/views/dialogs/GeoComplianceDialog.tsx deleted file mode 100644 index c8d4a04e68..0000000000 --- a/src/views/dialogs/GeoComplianceDialog.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import { useState } from 'react'; - -import { logBonsaiError } from '@/bonsai/logs'; -// eslint-disable-next-line no-restricted-imports -import { ComplianceAction, triggerCompliance } from '@/bonsai/rest/compliance'; -import styled from 'styled-components'; - -import { ButtonAction } from '@/constants/buttons'; -import { DialogProps, GeoComplianceDialogProps } from '@/constants/dialogs'; -import { COUNTRIES_MAP, CountryCodes } from '@/constants/geo'; -import { STRING_KEYS } from '@/constants/localization'; -import { isMainnet } from '@/constants/networks'; - -import { useBreakpoints } from '@/hooks/useBreakpoints'; -import { useEndpointsConfig } from '@/hooks/useEndpointsConfig'; -import { useStringGetter } from '@/hooks/useStringGetter'; - -import { formMixins } from '@/styles/formMixins'; - -import { Button } from '@/components/Button'; -import { Checkbox } from '@/components/Checkbox'; -import { Dialog, DialogPlacement } from '@/components/Dialog'; -import { SearchSelectMenu } from '@/components/SearchSelectMenu'; -import { WithReceipt } from '@/components/WithReceipt'; - -import { useAppDispatch } from '@/state/appTypes'; - -import { runFn } from '@/lib/do'; -import { removeTrailingSlash } from '@/lib/stringifyHelpers'; - -const isBlockedGeo = (geo: string, restrictedGeos: string[]): boolean => { - return isMainnet ? restrictedGeos.includes(geo as CountryCodes) : false; -}; - -const CountrySelector = ({ - label, - selectedCountry, - onSelect, -}: { - label: string; - selectedCountry: string; - onSelect: (country: string) => void; -}) => { - const stringGetter = useStringGetter(); - - const countriesList = Object.keys(COUNTRIES_MAP).map((country) => ({ - value: country, - label: country, - onSelect: () => onSelect(country), - })); - - return ( - -
- {selectedCountry || stringGetter({ key: STRING_KEYS.SELECT_A_COUNTRY })} -
-
- ); -}; - -export const GeoComplianceDialog = ({ setIsOpen }: DialogProps) => { - const stringGetter = useStringGetter(); - const dispatch = useAppDispatch(); - - const [residence, setResidence] = useState(''); - const [hasAcknowledged, setHasAcknowledged] = useState(false); - - const [showForm, setShowForm] = useState(false); - const { isMobile } = useBreakpoints(); - const { geoV2 } = useEndpointsConfig(); - - const submit = async () => { - const restrictedGeos = await runFn(async (): Promise => { - try { - const result = (await (await fetch(`${removeTrailingSlash(geoV2)}/restricted`)).json()) - .restricted.countryCodes; - - if (!Array.isArray(result)) { - throw new Error('Expected array of country codes'); - } - - return result; - } catch (error) { - logBonsaiError('fetchRestrictedGeos', 'Failed to fetch restricted geos', { error }); - throw error; - } - }); - - const action = - residence && isBlockedGeo(COUNTRIES_MAP[residence]!, restrictedGeos) - ? ComplianceAction.INVALID_SURVEY - : ComplianceAction.VALID_SURVEY; - - const success = await dispatch(triggerCompliance(action)); - if (success) { - setIsOpen(false); - } - }; - - return ( - - {showForm ? ( - <$Form> - - - - - } - tw="[--withReceipt-backgroundColor:--color-layer-2]" - > - - - - ) : ( - <$Form> -

{stringGetter({ key: STRING_KEYS.COMPLIANCE_BODY_FIRST_OFFENSE_1 })}

-

{stringGetter({ key: STRING_KEYS.COMPLIANCE_BODY_FIRST_OFFENSE_2 })}

-

- {stringGetter({ key: STRING_KEYS.COMPLIANCE_BODY_FIRST_OFFENSE_3 })} -

- - - )} -
- ); -}; -const $Form = styled.form` - ${formMixins.transfersForm} -`;