Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import {
OptionKey,
} from '@biom3/react';
import {
fetchRiskAssessment,
fetchRiskAssessmentV2,
GetBalanceResult, WidgetTheme,
resultHasSanctionedWallets,
} from '@imtbl/checkout-sdk';
import { parseUnits } from 'ethers';
import {
useCallback, useContext, useEffect, useMemo, useRef, useState,
} from 'react';
import { useTranslation } from 'react-i18next';
import { Environment } from '@imtbl/config';
import { trackError } from '@imtbl/metrics';
import { UserJourney, useAnalytics } from '../../../context/analytics-provider/SegmentAnalyticsProvider';
import { amountInputValidation } from '../../../lib/validations/amountInputValidations';
import { BridgeActions, BridgeContext } from '../context/BridgeContext';
Expand Down Expand Up @@ -62,6 +65,7 @@ export function BridgeForm(props: BridgeFormProps) {
to,
amount,
token,
tokenBridge,
},
} = useContext(BridgeContext);

Expand Down Expand Up @@ -142,9 +146,7 @@ export function BridgeForm(props: BridgeFormProps) {
tokenBalances,
cryptoFiatState.conversions,
defaultTokenAddress,
hasSetDefaultState.current,
formatTokenOptionsId,
formatZeroAmount,
]);

useEffect(() => {
Expand All @@ -168,36 +170,15 @@ export function BridgeForm(props: BridgeFormProps) {
amount: '',
},
});
}, [amount, token, tokenBalances]);
}, [amount, token, tokenBalances, bridgeDispatch]);

const selectedOption = useMemo(
() => (formToken && formToken.token
? formatTokenOptionsId(formToken.token.symbol, formToken.token.address)
: undefined),
[formToken, tokenBalances, cryptoFiatState.conversions, formatTokenOptionsId],
[formToken, formatTokenOptionsId],
);

useEffect(() => {
if (!checkout || !from || !to) {
return;
}

(async () => {
const addresses = [from.walletAddress];
if (to.walletAddress.toLowerCase() !== from.walletAddress.toLowerCase()) {
addresses.push(to.walletAddress);
}

const assessment = await fetchRiskAssessment(addresses, checkout.config);
bridgeDispatch({
payload: {
type: BridgeActions.SET_RISK_ASSESSMENT,
riskAssessment: assessment,
},
});
})();
}, [checkout, from, to]);

const canFetchEstimates = (silently: boolean): boolean => {
if (Number.isNaN(parseFloat(formAmount))) return false;
if (parseFloat(formAmount) <= 0) return false;
Expand Down Expand Up @@ -255,7 +236,7 @@ export function BridgeForm(props: BridgeFormProps) {
formToken.token.symbol,
cryptoFiatState.conversions,
));
}, [formAmount, formToken]);
}, [formAmount, formToken, cryptoFiatState.conversions]);

const bridgeFormValidator = useCallback((): boolean => {
const validateTokenError = validateToken(formToken);
Expand All @@ -266,10 +247,73 @@ export function BridgeForm(props: BridgeFormProps) {
return true;
}, [formToken, formAmount, setTokenError, setAmountError]);

const getRiskAssessment = useCallback(async () => {
if (!from || !to || !formToken || !formAmount || !tokenBridge || !formToken.token.address) return false;

const addresses = [from.walletAddress];
if (to.walletAddress.toLowerCase() !== from.walletAddress.toLowerCase()) {
addresses.push(to.walletAddress);
}

// Determine if we're bridging from L1 to L2 (deposit)
const isDeposit = checkout.config.l2ChainId === to.network && from.network === checkout.config.l1ChainId;

let tokenAddress = formToken.token.address;

// If we are bridging IN from L1 to L2, we need to find the token address on our chain
if (isDeposit) {
try {
const tokenMapping = await tokenBridge.getTokenMapping({
rootToken: formToken.token.address,
rootChainId: from.network.toString(),
childChainId: to.network.toString(),
});

if (!tokenMapping.childToken) {
throw new Error(`Token mapping not found for deposit token ${formToken.token.address}`);
}

// Use child token address if mapping exists, otherwise use original token address
tokenAddress = tokenMapping.childToken;
} catch (error) {
trackError('commerce', 'bridgeForm', error instanceof Error ? error : new Error(String(error)));
}
}

// Create risk assessment data array
const riskAssessmentData = [{
address: from.walletAddress,
tokenAddr: tokenAddress,
amount: parseUnits(formAmount, formToken.token.decimals),
}];

// Add second wallet if different
if (to.walletAddress.toLowerCase() !== from.walletAddress.toLowerCase()) {
riskAssessmentData.push({
address: to.walletAddress,
tokenAddr: tokenAddress,
amount: parseUnits(formAmount, formToken.token.decimals),
});
}

return fetchRiskAssessmentV2(riskAssessmentData, checkout.config);
}, [from, to, formToken, formAmount, tokenBridge, checkout]);

const submitBridgeValues = useCallback(async () => {
if (!bridgeFormValidator()) return;
if (!checkout || !from?.browserProvider || !formToken) return;

// perform sanctions check
const riskAssessment = await getRiskAssessment();
if (riskAssessment && resultHasSanctionedWallets(riskAssessment)) {
bridgeDispatch({
payload: {
type: BridgeActions.SET_RISK_ASSESSMENT,
riskAssessment,
},
});
}

track({
userJourney: UserJourney.BRIDGE,
screen: 'TokenAmount',
Expand Down Expand Up @@ -298,10 +342,15 @@ export function BridgeForm(props: BridgeFormProps) {
},
});
}, [
checkout,
from?.browserProvider,
bridgeDispatch,
bridgeFormValidator,
checkout,
formAmount,
formToken,
from,
getRiskAssessment,
track,
viewDispatch,
]);

const retrySubmitBridgeValues = async () => {
Expand Down