Skip to content

Commit

Permalink
feat: Adding sanctions validation to Swap widget (#2383)
Browse files Browse the repository at this point in the history
  • Loading branch information
alejoloaiza authored Nov 13, 2024
1 parent 318c3dd commit 7af66ef
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export enum SwapWidgetViews {
FAIL = 'FAIL',
PRICE_SURGE = 'PRICE_SURGE',
APPROVE_ERC20 = 'APPROVE_ERC20_SWAP',
SERVICE_UNAVAILABLE = 'SERVICE_UNAVAILABLE',
}

export type SwapWidgetView =
Expand All @@ -17,7 +18,8 @@ export type SwapWidgetView =
| SwapSuccessView
| PriceSurgeView
| SwapFailView
| ApproveERC20View;
| ApproveERC20View
| ServiceUnavailableView;

export interface SwapSuccessView extends ViewType {
type: SwapWidgetViews.SUCCESS;
Expand Down Expand Up @@ -50,6 +52,10 @@ interface ApproveERC20View extends ViewType {
data: ApproveERC20SwapData
}

interface ServiceUnavailableView extends ViewType {
type: SwapWidgetViews.SERVICE_UNAVAILABLE;
}

interface SwapInProgressView extends ViewType {
type: SwapWidgetViews.IN_PROGRESS;
data: {
Expand Down
34 changes: 34 additions & 0 deletions packages/checkout/widgets-lib/src/widgets/swap/SwapWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import {
TokenFilterTypes, IMTBLWidgetEvents, SwapWidgetParams,
SwapDirection,
fetchRiskAssessment,
} from '@imtbl/checkout-sdk';
import { useTranslation } from 'react-i18next';
import { SwapCoins } from './views/SwapCoins';
Expand Down Expand Up @@ -50,6 +51,7 @@ import { ConnectLoaderContext } from '../../context/connect-loader-context/Conne
import { EventTargetContext } from '../../context/event-target-context/EventTargetContext';
import { getAllowedBalances } from '../../lib/balance';
import { UserJourney, useAnalytics } from '../../context/analytics-provider/SegmentAnalyticsProvider';
import { ServiceUnavailableErrorView } from '../../views/error/ServiceUnavailableErrorView';

export type SwapWidgetInputs = SwapWidgetParams & {
config: StrongCheckoutWidgetsConfig;
Expand Down Expand Up @@ -186,6 +188,28 @@ export default function SwapWidget({
})();
}, [checkout, provider]);

useEffect(() => {
if (!checkout || swapState.riskAssessment) {
return;
}

(async () => {
const address = await provider?.getSigner()?.getAddress();

if (!address) {
return;
}

const assessment = await fetchRiskAssessment([address], checkout.config);
swapDispatch({
payload: {
type: SwapActions.SET_RISK_ASSESSMENT,
riskAssessment: assessment,
},
});
})();
}, [checkout, provider]);

useEffect(() => {
swapDispatch({
payload: {
Expand Down Expand Up @@ -341,6 +365,16 @@ export default function SwapWidget({
errorEventActionLoading={errorViewLoading}
/>
)}
{viewState.view.type === SwapWidgetViews.SERVICE_UNAVAILABLE && (
<ServiceUnavailableErrorView
onCloseClick={() => sendSwapWidgetCloseEvent(eventTarget)}
onBackButtonClick={() => {
viewDispatch({
payload: { type: ViewActions.UPDATE_VIEW, view: { type: SwapWidgetViews.SWAP } },
});
}}
/>
)}
{viewState.view.type === SharedViews.TOP_UP_VIEW && (
<TopUpView
analytics={{ userJourney: UserJourney.SWAP }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
Box, Heading, Icon, OptionKey, Tooltip,
} from '@biom3/react';
import { BigNumber, utils } from 'ethers';
import { TokenInfo, WidgetTheme } from '@imtbl/checkout-sdk';
import { isAddressSanctioned, TokenInfo, WidgetTheme } from '@imtbl/checkout-sdk';

import { TransactionResponse } from '@imtbl/dex-sdk';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -83,6 +83,7 @@ export function SwapForm({ data, theme, cancelAutoProceed }: SwapFromProps) {
tokenBalances,
network,
autoProceed,
riskAssessment,
},
} = useContext(SwapContext);

Expand Down Expand Up @@ -695,6 +696,18 @@ export function SwapForm({ data, theme, cancelAutoProceed }: SwapFromProps) {

const sendTransaction = async () => {
if (!quote) return;
if (riskAssessment && isAddressSanctioned(riskAssessment)) {
viewDispatch({
payload: {
type: ViewActions.UPDATE_VIEW,
view: {
type: SwapWidgetViews.SERVICE_UNAVAILABLE,
},
},
});

return;
}
const transaction = quote;
const isValid = SwapFormValidator();
// Tracking swap from data here and is valid or not to understand behaviour
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
NetworkInfo,
TokenInfo,
SwapDirection,
AssessmentResult,
} from '@imtbl/checkout-sdk';
import { Exchange } from '@imtbl/dex-sdk';
import { createContext } from 'react';
Expand All @@ -16,6 +17,7 @@ export interface SwapState {
supportedTopUps: TopUpFeature | null;
allowedTokens: TokenInfo[];
autoProceed: boolean;
riskAssessment: AssessmentResult | undefined;
}

export interface TopUpFeature {
Expand All @@ -32,6 +34,7 @@ export const initialSwapState: SwapState = {
supportedTopUps: null,
allowedTokens: [],
autoProceed: false,
riskAssessment: undefined,
};

export interface SwapContextState {
Expand All @@ -50,7 +53,8 @@ type ActionPayload =
| SetSupportedTopUpPayload
| SetTokenBalancesPayload
| SetAllowedTokensPayload
| SetAutoProceedPayload;
| SetAutoProceedPayload
| SetRiskAssessmentPayload;

export enum SwapActions {
SET_EXCHANGE = 'SET_EXCHANGE',
Expand All @@ -60,6 +64,7 @@ export enum SwapActions {
SET_TOKEN_BALANCES = 'SET_TOKEN_BALANCES',
SET_ALLOWED_TOKENS = 'SET_ALLOWED_TOKENS',
SET_AUTO_PROCEED = 'SET_AUTO_PROCEED',
SET_RISK_ASSESSMENT = 'SET_RISK_ASSESSMENT',
}

export interface SetExchangePayload {
Expand Down Expand Up @@ -98,6 +103,11 @@ export interface SetAutoProceedPayload {
direction: SwapDirection;
}

export interface SetRiskAssessmentPayload {
type: SwapActions.SET_RISK_ASSESSMENT;
riskAssessment: AssessmentResult;
}

// eslint-disable-next-line @typescript-eslint/naming-convention
export const SwapContext = createContext<SwapContextState>({
swapState: initialSwapState,
Expand Down Expand Up @@ -155,6 +165,11 @@ export const swapReducer: Reducer<SwapState, SwapAction> = (
autoProceed: action.payload.autoProceed,
direction: action.payload.direction,
};
case SwapActions.SET_RISK_ASSESSMENT:
return {
...state,
riskAssessment: action.payload.riskAssessment,
};
default:
return state;
}
Expand Down

0 comments on commit 7af66ef

Please sign in to comment.