Skip to content

Commit

Permalink
feat: compliance checks
Browse files Browse the repository at this point in the history
  • Loading branch information
kyranjamie committed Mar 28, 2024
1 parent 6262267 commit 43dd138
Show file tree
Hide file tree
Showing 48 changed files with 331 additions and 99 deletions.
3 changes: 0 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion src/app/common/hooks/account/use-refresh-all-account-data.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useCallback } from 'react';

import { delay } from '@app/common/utils';
import { delay } from '@shared/utils';

import { useCurrentAccountMempool } from '@app/query/stacks/mempool/mempool.hooks';

// TODO: Can this be removed? It seems like we should be able
Expand Down
4 changes: 1 addition & 3 deletions src/app/common/hooks/use-submit-stx-transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { bytesToHex } from '@stacks/common';
import { StacksTransaction, broadcastTransaction } from '@stacks/transactions';

import { logger } from '@shared/logger';
import { isError } from '@shared/utils';
import { delay, isError } from '@shared/utils';

import { getErrorMessage } from '@app/common/get-error-message';
import { useRefreshAllAccountData } from '@app/common/hooks/account/use-refresh-all-account-data';
Expand All @@ -15,8 +15,6 @@ import { useToast } from '@app/features/toasts/use-toast';
import { useCurrentStacksNetworkState } from '@app/store/networks/networks.hooks';
import { useSubmittedTransactionsActions } from '@app/store/submitted-transactions/submitted-transactions.hooks';

import { delay } from '../utils';

const timeForApiToUpdate = 250;

interface UseSubmitTransactionArgs {
Expand Down
29 changes: 5 additions & 24 deletions src/app/common/utils.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { hexToBytes } from '@stacks/common';
import {
BytesReader,
ChainID,
PostCondition,
deserializePostCondition,
} from '@stacks/transactions';
import { BytesReader, PostCondition, deserializePostCondition } from '@stacks/transactions';
import { toUnicode } from 'punycode';

import { BitcoinChainConfig, BitcoinNetworkModes, KEBAB_REGEX } from '@shared/constants';
Expand Down Expand Up @@ -225,14 +220,6 @@ export function addPortSuffix(url: string) {
return port ? `:${port}` : '';
}

export async function delay(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}

export function createDelay(ms: number) {
return async () => delay(ms);
}

export function with0x(value: string): string {
return !value.startsWith('0x') ? `0x${value}` : value;
}
Expand All @@ -249,9 +236,11 @@ export function doesBrowserSupportWebUsbApi() {
return Boolean((navigator as any).usb);
}

const isFullPage = document.location.pathname.startsWith('/index.html');
function isFullPage() {
return document.location.pathname.startsWith('/index.html');
}

const pageMode = isFullPage ? 'full' : 'popup';
const pageMode = isFullPage() ? 'full' : 'popup';

type PageMode = 'popup' | 'full';

Expand All @@ -266,14 +255,6 @@ export function isPopupMode() {
return pageMode === 'popup';
}

interface WhenStacksChainIdMap<T> {
[ChainID.Mainnet]: T;
[ChainID.Testnet]: T;
}
export function whenStacksChainId(chainId: ChainID) {
return <T>(chainIdMap: WhenStacksChainIdMap<T>): T => chainIdMap[chainId];
}

export const parseIfValidPunycode = (s: string) => {
try {
return toUnicode(s);
Expand Down
29 changes: 29 additions & 0 deletions src/app/common/validation/forms/compliance-validators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { isString } from 'formik';
import * as yup from 'yup';

import type { NetworkModes } from '@shared/constants';

import { checkEntityAddressIsCompliant } from '@app/query/common/compliance-checker/compliance-checker.query';

export function complianceValidator(
shouldCheckCompliance: yup.StringSchema<string, yup.AnyObject>,
network: NetworkModes
) {
return yup.string().test({
message: 'Compliance check failed',
async test(value) {
if (!isString(value)) return false;

if (network !== 'mainnet') return true;

if (!shouldCheckCompliance.isValidSync(value)) return true;

try {
const resp = await checkEntityAddressIsCompliant(value);
return !resp.isOnSanctionsList;
} catch (e) {
return true;
}
},
});
}
10 changes: 9 additions & 1 deletion src/app/common/validation/forms/recipient-validators.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NetworkConfiguration } from '@shared/constants';
import { stacksChainIdToCoreNetworkMode } from '@shared/crypto/stacks/stacks.utils';

import { FormErrorMessages } from '@app/common/error-messages';

Expand All @@ -7,12 +8,19 @@ import {
stxAddressNetworkValidator,
stxAddressValidator,
} from './address-validators';
import { complianceValidator } from './compliance-validators';

export function stxRecipientValidator(
currentAddress: string,
currentNetwork: NetworkConfiguration
) {
return stxAddressValidator(FormErrorMessages.InvalidAddress)
.concat(stxAddressNetworkValidator(currentNetwork))
.concat(notCurrentAddressValidator(currentAddress || ''));
.concat(notCurrentAddressValidator(currentAddress || ''))
.concat(
complianceValidator(
stxAddressValidator(FormErrorMessages.InvalidAddress),
stacksChainIdToCoreNetworkMode(currentNetwork.chain.stacks.chainId)
)
);
}
19 changes: 11 additions & 8 deletions src/app/components/loaders/bitcoin-account-loader.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { BitcoinAccount } from '@shared/crypto/bitcoin/bitcoin.utils';
import type { P2Ret, P2TROut } from '@scure/btc-signer';

import { useCurrentNativeSegwitAccount } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import { useCurrentTaprootAccount } from '@app/store/accounts/blockchain/bitcoin/taproot-account.hooks';
import { ZERO_INDEX } from '@shared/constants';

interface CurrentBitcoinAccountLoaderProps {
children(data: { nativeSegwit: BitcoinAccount; taproot: BitcoinAccount }): React.ReactNode;
import type { Signer } from '@app/store/accounts/blockchain/bitcoin/bitcoin-signer';
import { useCurrentAccountNativeSegwitSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import { useCurrentAccountTaprootSigner } from '@app/store/accounts/blockchain/bitcoin/taproot-account.hooks';

interface CurrentBitcoinSignerLoaderProps {
children(data: { nativeSegwit: Signer<P2Ret>; taproot: Signer<P2TROut> }): React.ReactNode;
}
export function CurrentBitcoinAccountLoader({ children }: CurrentBitcoinAccountLoaderProps) {
const nativeSegwit = useCurrentNativeSegwitAccount();
const taproot = useCurrentTaprootAccount();
export function CurrentBitcoinSignerLoader({ children }: CurrentBitcoinSignerLoaderProps) {
const nativeSegwit = useCurrentAccountNativeSegwitSigner()?.(ZERO_INDEX);
const taproot = useCurrentAccountTaprootSigner()?.(ZERO_INDEX);
if (!taproot || !nativeSegwit) return null;
return children({ nativeSegwit, taproot });
}
9 changes: 4 additions & 5 deletions src/app/components/no-fees-warning-row.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { ChainID } from '@stacks/transactions';
import { HStack, styled } from 'leather-styles/jsx';

import { whenStacksChainId } from '@app/common/utils';
import { stacksChainIdToCoreNetworkMode } from '@shared/crypto/stacks/stacks.utils';

import { capitalize } from '@app/common/utils';

interface NoFeesWarningRowProps {
chainId: ChainID;
Expand All @@ -11,10 +13,7 @@ export function NoFeesWarningRow({ chainId }: NoFeesWarningRowProps) {
<HStack alignItems="center" justifyContent="space-between">
<styled.span textStyle="caption.01">No fees are incurred</styled.span>
<styled.span textStyle="caption.01">
{whenStacksChainId(chainId)({
[ChainID.Testnet]: 'Testnet',
[ChainID.Mainnet]: 'Mainnet',
})}
{capitalize(stacksChainIdToCoreNetworkMode(chainId))}
</styled.span>
</HStack>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { LedgerIcon } from '@app/ui/icons/ledger-icon';
interface ConnectLedgerAssetBtnProps {
chain: SupportedBlockchains;
}

export function ConnectLedgerAssetBtn({ chain }: ConnectLedgerAssetBtnProps) {
const navigate = useNavigate();

Expand Down
8 changes: 4 additions & 4 deletions src/app/features/collectibles/collectibles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useQueryClient } from '@tanstack/react-query';
import { RouteUrls } from '@shared/route-urls';

import { useWalletType } from '@app/common/use-wallet-type';
import { CurrentBitcoinAccountLoader } from '@app/components/loaders/bitcoin-account-loader';
import { CurrentBitcoinSignerLoader } from '@app/components/loaders/bitcoin-account-loader';
import { CurrentStacksAccountLoader } from '@app/components/loaders/stacks-account-loader';
import { useConfigNftMetadataEnabled } from '@app/query/common/remote-config/remote-config.query';

Expand Down Expand Up @@ -47,22 +47,22 @@ export function Collectibles() {
isLoadingMore={isLoadingMore}
onRefresh={() => void queryClient.refetchQueries({ type: 'active' })}
>
<CurrentBitcoinAccountLoader>{() => <AddCollectible />}</CurrentBitcoinAccountLoader>
<CurrentBitcoinSignerLoader>{() => <AddCollectible />}</CurrentBitcoinSignerLoader>

{isNftMetadataEnabled && (
<CurrentStacksAccountLoader>
{account => <StacksCryptoAssets account={account} />}
</CurrentStacksAccountLoader>
)}

<CurrentBitcoinAccountLoader>
<CurrentBitcoinSignerLoader>
{() => (
<>
<Stamps />
<Ordinals setIsLoadingMore={setIsLoadingMore} />
</>
)}
</CurrentBitcoinAccountLoader>
</CurrentBitcoinSignerLoader>
</CollectiblesLayout>
);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { createContext, useContext } from 'react';
import { Outlet, Route, useNavigate } from 'react-router-dom';

import { delay } from '@shared/utils';

import { useAnalytics } from '@app/common/hooks/analytics/use-analytics';
import { delay } from '@app/common/utils';
import { openInNewTab } from '@app/common/utils/open-in-new-tab';

import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import get from 'lodash.get';
import { BitcoinInputSigningConfig } from '@shared/crypto/bitcoin/signer-config';
import { logger } from '@shared/logger';
import { RouteUrls } from '@shared/route-urls';
import { delay } from '@shared/utils';

import { useLocationStateWithCache } from '@app/common/hooks/use-location-state';
import { useScrollLock } from '@app/common/hooks/use-scroll-lock';
import { appEvents } from '@app/common/publish-subscribe';
import { delay } from '@app/common/utils';
import { ApproveSignLedgerBitcoinTx } from '@app/features/ledger/flows/bitcoin-tx-signing/steps/approve-bitcoin-sign-ledger-tx';
import { ledgerSignTxRoutes } from '@app/features/ledger/generic-flows/tx-signing/ledger-sign-tx-route-generator';
import { LedgerTxSigningContext } from '@app/features/ledger/generic-flows/tx-signing/ledger-sign-tx.context';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import get from 'lodash.get';

import { finalizeAuthResponse } from '@shared/actions/finalize-auth-response';
import { logger } from '@shared/logger';
import { isError } from '@shared/utils';
import { delay, isError } from '@shared/utils';

import { useGetLegacyAuthBitcoinAddresses } from '@app/common/authentication/use-legacy-auth-bitcoin-addresses';
import { useOnboardingState } from '@app/common/hooks/auth/use-onboarding-state';
import { useDefaultRequestParams } from '@app/common/hooks/use-default-request-search-params';
import { useKeyActions } from '@app/common/hooks/use-key-actions';
import { useScrollLock } from '@app/common/hooks/use-scroll-lock';
import { makeLedgerCompatibleUnsignedAuthResponsePayload } from '@app/common/unsafe-auth-response';
import { delay } from '@app/common/utils';
import {
getStacksAppVersion,
prepareLedgerDeviceStacksAppConnection,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { BitcoinNetworkModes, NetworkModes } from '@shared/constants';
import { createWalletIdDecoratedPath } from '@shared/crypto/bitcoin/bitcoin.utils';
import { getTaprootAccountDerivationPath } from '@shared/crypto/bitcoin/p2tr-address-gen';
import { getNativeSegwitAccountDerivationPath } from '@shared/crypto/bitcoin/p2wpkh-address-gen';

import { delay } from '@app/common/utils';
import { delay } from '@shared/utils';

import {
WalletPolicyDetails,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import {
getIdentityDerivationPath,
getStxDerivationPath,
} from '@shared/crypto/stacks/stacks.utils';

import { delay } from '@app/common/utils';
import { delay } from '@shared/utils';

import {
StacksAppKeysResponseItem,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ import { LedgerError } from '@zondax/ledger-stacks';
import get from 'lodash.get';

import { UnsignedMessage, whenSignableMessageOfType } from '@shared/signature/signature-types';
import { isError } from '@shared/utils';
import { delay, isError } from '@shared/utils';

import { useScrollLock } from '@app/common/hooks/use-scroll-lock';
import { appEvents } from '@app/common/publish-subscribe';
import { delay } from '@app/common/utils';
import {
getStacksAppVersion,
prepareLedgerDeviceStacksAppConnection,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import {
encodeStructuredData,
} from '@stacks/transactions';

import { stacksChainIdToCoreNetworkMode } from '@shared/crypto/stacks/stacks.utils';
import { UnsignedMessageStructured } from '@shared/signature/signature-types';

import { whenStacksChainId } from '@app/common/utils';
import { capitalize } from '@app/common/utils';

export function cvToDisplay(cv: ClarityValue): string {
return cvToString(cv).replaceAll('"', '');
Expand All @@ -21,11 +22,7 @@ export function chainIdToDisplay(chainIdCv: ClarityValue): string {
const chainIdString = cvToString(chainIdCv);
const chainId = parseInt(chainIdString.replace('u', ''));
if (!Object.values(ChainID).includes(chainId)) return '';

return whenStacksChainId(chainId as ChainID)({
[ChainID.Testnet]: 'Testnet',
[ChainID.Mainnet]: 'Mainnet',
});
return capitalize(stacksChainIdToCoreNetworkMode(chainId));
}

export function deriveStructuredMessageHash({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import StacksApp, { LedgerError } from '@zondax/ledger-stacks';
import get from 'lodash.get';

import { RouteUrls } from '@shared/route-urls';
import { isError } from '@shared/utils';
import { delay, isError } from '@shared/utils';

import { useScrollLock } from '@app/common/hooks/use-scroll-lock';
import { appEvents } from '@app/common/publish-subscribe';
import { delay } from '@app/common/utils';
import { LedgerTxSigningContext } from '@app/features/ledger/generic-flows/tx-signing/ledger-sign-tx.context';
import {
connectLedgerStacksApp,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import GenericErrorImg from '@assets/images/generic-error.png';
import { Box, HStack, styled } from 'leather-styles/jsx';

import { delay } from '@shared/utils';

import { useLoading } from '@app/common/hooks/use-loading';
import { delay } from '@app/common/utils';
import { LedgerTitle } from '@app/features/ledger/components/ledger-title';
import { LedgerWrapper } from '@app/features/ledger/components/ledger-wrapper';
import { Button } from '@app/ui/components/button/button';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import StacksApp from '@zondax/ledger-stacks';
import BitcoinApp from 'ledger-bitcoin';

import { SupportedBlockchains } from '@shared/constants';
import { isError } from '@shared/utils';

import { delay } from '@app/common/utils';
import { delay, isError } from '@shared/utils';

import { useLedgerAnalytics } from '../../hooks/use-ledger-analytics.hook';
import { useLedgerNavigate } from '../../hooks/use-ledger-navigate';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import StacksApp from '@zondax/ledger-stacks';
import BitcoinApp from 'ledger-bitcoin';

import { SupportedBlockchains } from '@shared/constants';
import { isError } from '@shared/utils';

import { delay } from '@app/common/utils';
import { delay, isError } from '@shared/utils';

import { useLedgerNavigate } from '../../hooks/use-ledger-navigate';
import { BitcoinAppVersion } from '../../utils/bitcoin-ledger-utils';
Expand Down
3 changes: 2 additions & 1 deletion src/app/features/ledger/utils/generic-ledger-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { useState } from 'react';
import TransportWebUSB from '@ledgerhq/hw-transport-webusb';
import BitcoinApp from 'ledger-bitcoin';

import { delay } from '@app/common/utils';
import { delay } from '@shared/utils';

import { safeAwait } from '@app/common/utils/safe-await';

import { getStacksAppVersion } from './stacks-ledger-utils';
Expand Down
Loading

0 comments on commit 43dd138

Please sign in to comment.