import { r as ro, A as Ao, o as oo, m as mo, n as no, f as fo, g as go, a as ao, E as Eo, i as io, R as Ro, l as lo, u as uo, s as so, C as Co, T as To, p as po, b as reactExports, V as ViewActions, c as parseUnits, d as formatZeroAmount, e as calculateCryptoToFiat, h as Contract, j as ie, k as useTranslation, q as dist, t as getRemoteRive, v as tt, w as jsx, x as jsxs, B as Box, H as Heading, L as Link, y as Button, S as Stack, z as SimpleLayout, D as Body, F as useAnalytics, G as EventTargetContext, I as CryptoFiatContext, J as tokenValueFormat, K as getDefaultTokenImage, U as UserJourney, M as HeaderNavigation, N as sendCloseWidgetEvent, O as orchestrationEvents$1, P as amountInputValidation, Q as useTheme, W as CloudImage, X as getRemoteImage, Y as CryptoFiatProvider, Z as ConnectLoaderContext, _ as isAddress, $ as isError, a0 as LoadingView, a1 as CryptoFiatActions, a2 as useViewState, a3 as useEventTargetState, a4 as commerceFlows, a5 as SharedViews, a6 as ErrorView, a7 as ConnectWidget, a8 as ProvidersContextProvider, a9 as PurchaseWidget, aa as ConnectLoader, ab as ViewContextProvider } from './index-Cy6GwrlT.js';
import { S as SelectInput, a as SwapWidget } from './SwapWidget-DZX2e6Mw.js';
import { B as BridgeWidget } from './BridgeWidget-BMoOgSRy.js';
import OnRampWidget from './OnRampWidget-OqTWgFMn.js';
import WalletWidget from './WalletWidget-CJ7WYkGs.js';
import SaleWidget from './SaleWidget-CB1VUdA1.js';
import AddTokensWidget from './AddTokensWidget-CtgTMQaF.js';
import { g as getAllowedBalances, T as TextInputForm } from './WalletApproveHero-CLOuWFdK.js';
import './useInterval-BLsKyqA9.js';
import './TopUpView-Cn30wgNE.js';
import './FeesBreakdown-CwI-so3y.js';
import './SpendingCapHero-O4mxTGj9.js';
import './TokenImage-DJVztWVN.js';

const sendCheckoutEvent = (eventTarget, detail) => {
    const event = new CustomEvent(ro.IMTBL_COMMERCE_WIDGET_EVENT, { detail });
    // eslint-disable-next-line no-console
    console.log('checkout app event ', eventTarget, event);
    if (eventTarget !== undefined)
        eventTarget.dispatchEvent(event);
};

/**
 * List of views that require a connect loader wrapper
 */
const connectLoaderFlows = [
    Ao.SALE,
    Ao.SWAP,
    Ao.WALLET,
    Ao.ONRAMP,
    Ao.TRANSFER,
];
/**
 * List of views that require a providers context wrapper
 */
const providersContextFlows = [
    Ao.ADD_TOKENS,
    Ao.PURCHASE,
];
/**
 * Check if the given view requires a connected wallet
 */
function isConnectLoaderFlow(view) {
    return connectLoaderFlows.includes(view);
}
/**
 * Check if the given view requires a providers context wrapper
 */
function isProvidersContextFlow(view) {
    return providersContextFlows.includes(view);
}

/**
 * Map Connect Widget Events
 */
function mapConnectWidgetEvent(event) {
    const { type, data } = event.detail;
    switch (type) {
        case no.SUCCESS:
            return {
                type: mo.SUCCESS,
                data: {
                    type: go.CONNECT_SUCCESS,
                    data,
                },
            };
        case no.FAILURE:
            return {
                type: mo.FAILURE,
                data: {
                    type: fo.CONNECT_FAILED,
                    data,
                },
            };
        case no.CLOSE_WIDGET:
            return {
                type: mo.CLOSE,
                data: {},
            };
        default:
            throw new Error(`Unknown connect event type "${event.detail.type}"`);
    }
}
/**
 * Map Wallet Widget Events
 */
function mapWalletWidgetEvent(event) {
    const { type, data } = event.detail;
    switch (type) {
        case ao.NETWORK_SWITCH:
            return {
                type: mo.USER_ACTION,
                data: {
                    type: Eo.NETWORK_SWITCH,
                    data,
                },
            };
        case ao.DISCONNECT_WALLET:
            return {
                type: mo.DISCONNECTED,
                data: {},
            };
        case ao.CLOSE_WIDGET:
            return {
                type: mo.CLOSE,
                data: {},
            };
        default:
            throw new Error(`Unknown wallet event type "${event.detail.type}"`);
    }
}
/**
 * Map Swap Widget Events
 */
function mapSwapWidgetEvent(event) {
    const { type, data } = event.detail;
    switch (type) {
        case io.SUCCESS:
            return {
                type: mo.SUCCESS,
                data: {
                    type: go.SWAP_SUCCESS,
                    data,
                },
            };
        case io.FAILURE:
            return {
                type: mo.FAILURE,
                data: {
                    type: fo.SWAP_FAILED,
                    data,
                },
            };
        case io.REJECTED:
            return {
                type: mo.FAILURE,
                data: {
                    type: fo.SWAP_REJECTED,
                    data,
                },
            };
        case io.CLOSE_WIDGET:
            return {
                type: mo.CLOSE,
                data: {},
            };
        default:
            throw new Error(`Unknown swap event type "${event.detail.type}"`);
    }
}
/**
 * Map Add Tokens Widget Events
 */
function mapAddTokensWidgetEvent(event) {
    const { type } = event.detail;
    switch (type) {
        case Ro.SUCCESS:
            return {
                type: mo.SUCCESS,
                data: {
                    type: go.ADD_TOKENS_SUCCESS,
                    data: event.detail.data,
                },
            };
        case Ro.CONNECT_SUCCESS:
            return {
                type: mo.SUCCESS,
                data: {
                    type: go.ADD_TOKENS_CONNECT_SUCCESS,
                    data: event.detail.data,
                },
            };
        case Ro.FAILURE:
            return {
                type: mo.FAILURE,
                data: {
                    type: fo.ADD_TOKENS_FAILED,
                    data: event.detail.data,
                },
            };
        case Ro.CLOSE_WIDGET:
            return {
                type: mo.CLOSE,
                data: {},
            };
        default:
            throw new Error(`Unknown add tokens event type "${event.detail.type}"`);
    }
}
/**
 * Map Bridge Widget Events
 */
function mapBridgeWidgetEvent(event) {
    const { type, data } = event.detail;
    switch (type) {
        case lo.TRANSACTION_SENT:
            return {
                type: mo.SUCCESS,
                data: {
                    type: go.BRIDGE_SUCCESS,
                    data,
                },
            };
        case lo.CLAIM_WITHDRAWAL_SUCCESS:
            return {
                type: mo.SUCCESS,
                data: {
                    type: go.BRIDGE_CLAIM_WITHDRAWAL_SUCCESS,
                    data,
                },
            };
        case lo.CLAIM_WITHDRAWAL_FAILURE:
            return {
                type: mo.FAILURE,
                data: {
                    type: fo.BRIDGE_CLAIM_WITHDRAWAL_FAILED,
                    data,
                },
            };
        case lo.FAILURE:
            return {
                type: mo.FAILURE,
                data: {
                    type: fo.BRIDGE_FAILED,
                    data,
                },
            };
        case lo.CLOSE_WIDGET:
            return {
                type: mo.CLOSE,
                data: {},
            };
        default:
            throw new Error(`Unknown bridge event type "${event.detail.type}"`);
    }
}
/**
 * Map Bridge Widget Events
 */
function mapOnrampWidgetEvent(event) {
    const { type, data } = event.detail;
    switch (type) {
        case uo.SUCCESS:
            return {
                type: mo.SUCCESS,
                data: {
                    type: go.ONRAMP_SUCCESS,
                    data,
                },
            };
        case uo.FAILURE:
            return {
                type: mo.FAILURE,
                data: {
                    type: fo.ONRAMP_FAILED,
                    data,
                },
            };
        case uo.CLOSE_WIDGET:
            return {
                type: mo.CLOSE,
                data: {},
            };
        default:
            throw new Error(`Unknown onRamp event type "${event.detail.type}"`);
    }
}
function mapSaleWidgetEvent(event) {
    const { type, data } = event.detail;
    switch (type) {
        case so.SUCCESS:
            return {
                type: mo.SUCCESS,
                data: {
                    type: go.SALE_SUCCESS,
                    data,
                },
            };
        case so.FAILURE:
            return {
                type: mo.FAILURE,
                data: {
                    type: fo.SALE_FAILED,
                    data,
                },
            };
        case so.CLOSE_WIDGET:
            return {
                type: mo.CLOSE,
                data: {},
            };
        case so.TRANSACTION_SUCCESS:
            return {
                type: mo.SUCCESS,
                data: {
                    type: go.SALE_TRANSACTION_SUCCESS,
                    data,
                },
            };
        case so.PAYMENT_METHOD:
            return {
                type: mo.USER_ACTION,
                data: {
                    type: Eo.PAYMENT_METHOD_SELECTED,
                    data,
                },
            };
        case so.PAYMENT_TOKEN:
            return {
                type: mo.USER_ACTION,
                data: {
                    type: Eo.PAYMENT_TOKEN_SELECTED,
                    data,
                },
            };
        default:
            throw new Error(`Unknown sale event type "${event.detail.type}"`);
    }
}
function mapPurchaseWidgetEvent(event) {
    const { type, data } = event.detail;
    switch (type) {
        case Co.SUCCESS:
            return {
                type: mo.SUCCESS,
                data: {
                    type: go.SALE_SUCCESS,
                    data,
                },
            };
        case Co.FAILURE:
            return {
                type: mo.FAILURE,
                data: {
                    type: fo.SALE_FAILED,
                    data,
                },
            };
        case Co.CLOSE_WIDGET:
            return {
                type: mo.CLOSE,
                data: {},
            };
        default:
            throw new Error(`Unknown purchase event type "${event.detail.type}"`);
    }
}
/**
 * Map Transfer Widget Events
 */
function mapTransferWidgetEvent(event) {
    const { type, data } = event.detail;
    switch (type) {
        case To.SUCCESS:
            return {
                type: mo.SUCCESS,
                data: {
                    type: go.TRANSFER_SUCCESS,
                    data,
                },
            };
        case To.FAILURE:
            return {
                type: mo.FAILURE,
                data: {
                    type: fo.TRANSFER_FAILED,
                    data,
                },
            };
        case To.CLOSE_WIDGET:
            return {
                type: mo.CLOSE,
                data: {},
            };
        default:
            throw new Error(`Unknown transfer event type "${event.detail.type}"`);
    }
}
/**
 * Map widget events to commerce widget event detail
 */
function getCommerceWidgetEvent(event) {
    if (event.detail.type === oo.PROVIDER_UPDATED) {
        return {
            type: mo.PROVIDER_UPDATED,
            data: event.detail.data,
        };
    }
    switch (event.type) {
        case ro.IMTBL_CONNECT_WIDGET_EVENT:
            return mapConnectWidgetEvent(event);
        case ro.IMTBL_WALLET_WIDGET_EVENT:
            return mapWalletWidgetEvent(event);
        case ro.IMTBL_SWAP_WIDGET_EVENT:
            return mapSwapWidgetEvent(event);
        case ro.IMTBL_ADD_TOKENS_WIDGET_EVENT:
            return mapAddTokensWidgetEvent(event);
        case ro.IMTBL_BRIDGE_WIDGET_EVENT:
            return mapBridgeWidgetEvent(event);
        case ro.IMTBL_ONRAMP_WIDGET_EVENT:
            return mapOnrampWidgetEvent(event);
        case ro.IMTBL_SALE_WIDGET_EVENT:
            return mapSaleWidgetEvent(event);
        case ro.IMTBL_PURCHASE_WIDGET_EVENT:
            return mapPurchaseWidgetEvent(event);
        case ro.IMTBL_TRANSFER_WIDGET_EVENT:
            return mapTransferWidgetEvent(event);
        default:
            throw new Error(`Unknown widget event type "${event.type}"`);
    }
}

/**
 * Get view from orchestration event type
 */
function getViewFromOrchestrationEventType(type) {
    switch (type) {
        case po.REQUEST_SWAP:
            return Ao.SWAP;
        case po.REQUEST_CONNECT:
            return Ao.CONNECT;
        case po.REQUEST_WALLET:
            return Ao.WALLET;
        case po.REQUEST_BRIDGE:
            return Ao.BRIDGE;
        case po.REQUEST_ONRAMP:
            return Ao.ONRAMP;
        case po.REQUEST_ADD_TOKENS:
            return Ao.ADD_TOKENS;
        case po.REQUEST_PURCHASE:
            return Ao.PURCHASE;
        default:
            return null;
    }
}

/** Orchestration Events List */
const orchestrationEvents = [
    po.REQUEST_CONNECT,
    po.REQUEST_WALLET,
    po.REQUEST_SWAP,
    po.REQUEST_BRIDGE,
    po.REQUEST_ONRAMP,
    po.REQUEST_ADD_TOKENS,
    po.REQUEST_PURCHASE,
    po.REQUEST_GO_BACK,
];
/**
 * Check if event is orchestration event
 */
function isOrchestrationEvent(event) {
    return orchestrationEvents.includes(event.detail.type);
}

/** Widget Events List */
const widgetEvents = [
    ro.IMTBL_CONNECT_WIDGET_EVENT,
    ro.IMTBL_WALLET_WIDGET_EVENT,
    ro.IMTBL_SWAP_WIDGET_EVENT,
    ro.IMTBL_BRIDGE_WIDGET_EVENT,
    ro.IMTBL_ONRAMP_WIDGET_EVENT,
    ro.IMTBL_SALE_WIDGET_EVENT,
    ro.IMTBL_ADD_TOKENS_WIDGET_EVENT,
    ro.IMTBL_PURCHASE_WIDGET_EVENT,
    ro.IMTBL_TRANSFER_WIDGET_EVENT,
];
/**
 * Subscribe and Handle widget events
 */
function useWidgetEvents(eventTarget, viewState, handleProviderUpdated) {
    const [{ history }, viewDispatch] = viewState;
    /**
     * Change view as per orchestration event requests
     */
    const handleOrchestrationEvent = (event) => {
        const { type, data } = event.detail;
        if (type === po.REQUEST_GO_BACK) {
            viewDispatch({
                payload: {
                    type: ViewActions.UPDATE_VIEW,
                    view: history?.[0],
                },
            });
            return;
        }
        if (type === po.REQUEST_ONRAMP) {
            const onRampEvent = data;
            if (onRampEvent.provider) {
                handleProviderUpdated(onRampEvent.provider);
            }
        }
        const flow = getViewFromOrchestrationEventType(type);
        if (!flow)
            return;
        viewDispatch({
            payload: {
                type: ViewActions.UPDATE_VIEW,
                view: {
                    type: flow,
                    data: { params: data, config: {}, showBackButton: true },
                },
            },
        });
    };
    /**
     * Proxy widget events to Commerce Widget events
     */
    const handleWidgetEvent = reactExports.useMemo(() => {
        if (!eventTarget)
            return null;
        return (event) => {
            const customEvent = event;
            if (isOrchestrationEvent(customEvent)) {
                handleOrchestrationEvent(customEvent);
                return;
            }
            // ignore walletconnect provider updated event on CONNECT
            // as that is not really consumed and the provider is available to the consumer on success event
            // GFI-596
            const isConnectProviderUpdatedEvent = customEvent.detail.type === no.WALLETCONNECT_PROVIDER_UPDATED;
            if (isConnectProviderUpdatedEvent) {
                return;
            }
            const eventDetail = getCommerceWidgetEvent(customEvent);
            sendCheckoutEvent(eventTarget, eventDetail);
        };
    }, [eventTarget]);
    reactExports.useEffect(() => {
        if (!handleWidgetEvent)
            return () => { };
        widgetEvents.map((event) => window.addEventListener(event, handleWidgetEvent));
        return () => {
            widgetEvents.map((event) => window.removeEventListener(event, handleWidgetEvent));
        };
    }, [handleWidgetEvent]);
}

/**
 * Get the connect loader params for the widget
 */
function getConnectLoaderParams(view, flowConfig, checkout, browserProvider) {
    const { type } = view;
    switch (type) {
        case Ao.WALLET:
            return {
                checkout,
                browserProvider,
                targetChainId: checkout.config.l2ChainId,
                allowedChains: [
                    checkout.config.l1ChainId,
                    checkout.config.l2ChainId,
                ],
                allowlistWalletRdns: flowConfig.CONNECT?.allowlistWalletRdns,
                walletProviderName: undefined,
            };
        case Ao.ONRAMP:
        case Ao.ADD_TOKENS:
            return {
                checkout,
                browserProvider,
                targetChainId: checkout.config.l2ChainId,
                allowedChains: [
                    checkout.config.l1ChainId,
                    checkout.config.l2ChainId,
                ],
                allowlistWalletRdns: flowConfig.CONNECT?.allowlistWalletRdns,
                walletProviderName: undefined,
            };
        case Ao.SALE:
        case Ao.SWAP:
        case Ao.TRANSFER:
            return {
                checkout,
                browserProvider,
                targetChainId: checkout.config.l2ChainId,
                allowedChains: [checkout.config.l2ChainId],
                allowlistWalletRdns: flowConfig.CONNECT?.allowlistWalletRdns,
                walletProviderName: undefined,
            };
        default:
            return {};
    }
}

const initialCommerceState = {
    checkout: undefined,
    provider: undefined,
    passport: undefined,
};
var CommerceActions;
(function (CommerceActions) {
    CommerceActions["SET_CHECKOUT"] = "SET_CHECKOUT";
    CommerceActions["SET_PROVIDER"] = "SET_PROVIDER";
    CommerceActions["SET_PASSPORT"] = "SET_PASSPORT";
})(CommerceActions || (CommerceActions = {}));
// eslint-disable-next-line @typescript-eslint/naming-convention
const CommerceContext = reactExports.createContext({
    commerceState: initialCommerceState,
    commerceDispatch: () => { },
});
CommerceContext.displayName = 'CommerceContext'; // help with debugging Context in browser
const commerceReducer = (state, action) => {
    switch (action.payload.type) {
        case CommerceActions.SET_CHECKOUT:
            return {
                ...state,
                checkout: action.payload.checkout,
            };
        case CommerceActions.SET_PROVIDER:
            return {
                ...state,
                provider: action.payload.provider,
            };
        case CommerceActions.SET_PASSPORT:
            return {
                ...state,
                passport: action.payload.passport,
            };
        default:
            return state;
    }
};

const erc20Abi = ['function transfer(address to, uint amount)'];
const validatePartialAddress = (value) => {
    const regex = /^(0(x[0-9a-fA-F]{0,40})?)?$/;
    return regex.test(value);
};
const getOptionKey = (token) => token.address ?? 'native';
const getFiatAmount = (cryptoFiatState, tokenBalance) => {
    if (cryptoFiatState.conversions.size === 0)
        return formatZeroAmount('');
    return calculateCryptoToFiat(tokenBalance.formattedBalance, tokenBalance.token.symbol || '', cryptoFiatState.conversions);
};
const sendErc20Tokens = async (signer, tokenAddress, recipientAddress, amount) => new Contract(tokenAddress, erc20Abi, signer).transfer(recipientAddress, amount);
const sendNativeTokens = async (signer, recipientAddress, amount) => signer.sendTransaction({
    to: recipientAddress,
    value: amount,
});
const sendTokens = async (provider, gbr, recipientAddress, amount) => {
    const amountBigInt = parseUnits(amount, gbr.token.decimals);
    const signer = await provider.getSigner();
    if (!gbr.token.address)
        throw new Error('Token address not found'); // the types say it can be undefined, but for native it's "native" so not sure when this would be the case.
    if (gbr.token.address === 'native')
        return sendNativeTokens(signer, recipientAddress, amountBigInt);
    return sendErc20Tokens(signer, gbr.token.address, recipientAddress, amountBigInt);
};
const loadBalances = async (checkout, provider) => {
    const result = await getAllowedBalances({
        checkout,
        provider,
        allowTokenListType: ie.ALL,
    });
    if (!result)
        throw new Error('Failed to load balances');
    return result;
};

function TransferComplete({ config, viewState, onContinue, }) {
    const { t } = useTranslation();
    const { RiveComponent, rive } = dist.useRive({
        src: getRemoteRive(config.environment, '/purchasing_items.riv'),
        stateMachines: 'State',
        autoplay: true,
    });
    const input = dist.useStateMachineInput(rive, 'State', 'mode');
    reactExports.useEffect(() => {
        if (!input)
            return;
        input.value = 3;
    }, [input]);
    const explorerLink = reactExports.useMemo(() => tt.getTransactionLink(viewState.chainId, viewState.receipt.hash), [viewState.chainId, viewState.receipt.hash]);
    return (jsx(SimpleLayout, { containerSx: { bg: 'transparent' }, children: jsxs(Stack, { justifyContent: "space-between", sx: {
                height: '100%',
                mb: 'base.spacing.x10',
                textAlign: 'center',
            }, children: [jsxs(Box, { children: [jsx(Box, { sx: { height: '240px' }, rc: jsx(RiveComponent, {}) }), jsx(Heading, { sx: { my: 'base.spacing.x4', mx: 'base.spacing.x4' }, children: t('views.TRANSFER.content.tokensSentSuccessfully') }), jsx(Link, { rc: jsx("a", { target: "_blank", href: explorerLink, rel: "noreferrer" }), children: t('views.TRANSFER.content.seeTransactionOnImmutableZkEVM') })] }), jsx(Box, { sx: { mx: 'base.spacing.x4' }, children: jsx(Button, { sx: { width: '100%' }, onClick: onContinue, size: "large", children: t('views.TRANSFER.form.continueButtonText') }) })] }) }));
}

function SendingTokens({ config }) {
    const { t } = useTranslation();
    const { RiveComponent, rive } = dist.useRive({
        src: getRemoteRive(config.environment, '/purchasing_items.riv'),
        stateMachines: 'State',
        autoplay: true,
    });
    const input = dist.useStateMachineInput(rive, 'State', 'mode');
    reactExports.useEffect(() => {
        if (!input)
            return;
        input.value = 2;
    }, [input]);
    return (jsx(SimpleLayout, { containerSx: { bg: 'transparent' }, children: jsx(Stack, { justifyContent: "space-between", sx: {
                height: '100%',
                mb: 'base.spacing.x10',
                textAlign: 'center',
            }, children: jsxs(Box, { children: [jsx(Box, { sx: { height: '240px' }, rc: jsx(RiveComponent, {}) }), jsx(Heading, { sx: { my: 'base.spacing.x4', mx: 'base.spacing.x4' }, children: t('views.TRANSFER.content.sendingTokens') })] }) }) }));
}

function AwaitingApproval({ config }) {
    const { t } = useTranslation();
    const { RiveComponent, rive } = dist.useRive({
        src: getRemoteRive(config.environment, '/purchasing_items.riv'),
        stateMachines: 'State',
        autoplay: true,
    });
    const input = dist.useStateMachineInput(rive, 'State', 'mode');
    reactExports.useEffect(() => {
        if (!input)
            return;
        input.value = 2;
    }, [input]);
    return (jsx(SimpleLayout, { containerSx: { bg: 'transparent' }, children: jsx(Stack, { justifyContent: "space-between", sx: {
                height: '100%',
                mb: 'base.spacing.x10',
                textAlign: 'center',
            }, children: jsxs(Box, { children: [jsx(Box, { sx: { height: '240px' }, rc: jsx(RiveComponent, {}) }), jsx(Heading, { sx: { my: 'base.spacing.x4', mx: 'base.spacing.x4' }, children: t('views.TRANSFER.content.waitingForYouToApproveTxn') }), jsx(Body, { rc: jsx("div", {}), children: t('views.TRANSFER.content.waitingForYouToApproveTxnDescription') })] }) }) }));
}

function TransferForm({ config, viewState, setViewState, onSend, showBackButton, showHeader, title, coinAmountTitle, }) {
    const { t } = useTranslation();
    const { track } = useAnalytics();
    const { eventTargetState: { eventTarget } } = reactExports.useContext(EventTargetContext);
    const { cryptoFiatState } = reactExports.useContext(CryptoFiatContext);
    const tokenOptions = reactExports.useMemo(() => viewState.allowedBalances.map((tokenBalance) => ({
        id: getOptionKey(tokenBalance.token),
        name: tokenBalance.token.name,
        symbol: tokenBalance.token.symbol,
        defaultTokenImage: tokenBalance.token.icon || 'TODO',
        balance: {
            fullBalance: tokenBalance.formattedBalance,
            formattedAmount: tokenValueFormat(tokenBalance.formattedBalance),
            formattedFiatAmount: getFiatAmount(cryptoFiatState, tokenBalance),
        },
    })), [viewState.allowedBalances, cryptoFiatState]);
    const token = reactExports.useMemo(() => tokenOptions.find((option) => option.id === viewState.tokenAddress), [tokenOptions, viewState.tokenAddress]);
    const defaultTokenImage = reactExports.useMemo(() => getDefaultTokenImage(viewState.checkout.config.environment, config.theme), [viewState.checkout.config.environment, config.theme]);
    const fromFiatValue = reactExports.useMemo(() => calculateCryptoToFiat(viewState.amount, token?.symbol || '', cryptoFiatState.conversions), [viewState.amount, token, cryptoFiatState.conversions]);
    const handleTokenChange = reactExports.useCallback((optionKey) => {
        track({
            screen: 'TransferToken',
            userJourney: UserJourney.TRANSFER,
            control: 'SelectToken',
            controlType: 'Select',
            extras: { token: optionKey },
        });
        if (typeof optionKey !== 'string')
            throw new Error('Invalid token address');
        setViewState((s) => ({ ...s, tokenAddress: optionKey, amountError: '' }));
    }, [setViewState, track]);
    const handleMaxButtonClick = reactExports.useCallback(() => {
        if (!token)
            throw new Error('Token not found');
        if (!token.balance)
            throw new Error('Token balance not found');
        track({
            screen: 'TransferToken',
            userJourney: UserJourney.TRANSFER,
            control: 'Max',
            controlType: 'Button',
            extras: { token: token.id, amount: token.balance.fullBalance },
        });
        setViewState((s) => {
            if (!token.balance)
                throw new Error('Token balance not found');
            return { ...s, amount: token.balance.fullBalance };
        });
    }, [token, setViewState, track]);
    const handleRecipientAddressChange = reactExports.useCallback((value) => {
        setViewState((s) => ({ ...s, toAddress: value, toAddressError: '' }));
    }, [setViewState]);
    const handleAmountChange = reactExports.useCallback((value) => {
        setViewState((s) => ({ ...s, amount: value, amountError: '' }));
    }, [setViewState]);
    const selectSubtext = reactExports.useMemo(() => {
        if (!token)
            return '';
        return `${t('views.TRANSFER.content.availableBalancePrefix')} ${token.balance?.formattedAmount}`;
    }, [token, t]);
    const isButtonDisabled = reactExports.useMemo(() => !viewState.amount || !viewState.toAddress || !token, [viewState.amount, viewState.toAddress, token]);
    return (jsx(SimpleLayout, { header: showHeader ? (jsx(HeaderNavigation, { title: title, onCloseButtonClick: () => sendCloseWidgetEvent(eventTarget), showBack: showBackButton, onBackButtonClick: () => {
                orchestrationEvents$1.sendRequestGoBackEvent(eventTarget, ro.IMTBL_TRANSFER_WIDGET_EVENT, {});
            } })) : undefined, children: jsxs(Stack, { justifyContent: "space-between", sx: {
                height: '100%',
                mt: 'base.spacing.x6',
                mx: 'base.spacing.x4',
                mb: 'base.spacing.x10',
            }, children: [jsxs(Stack, { gap: "base.spacing.x9", children: [jsxs(Stack, { gap: "base.spacing.x1", children: [jsx(Heading, { size: "xSmall", children: coinAmountTitle }), jsx(SelectInput, { testId: "transfer-token-select", options: tokenOptions, textInputValue: viewState.amount, textInputPlaceholder: "0", textInputTextAlign: "right", coinSelectorHeading: t('views.TRANSFER.form.coinSelectorHeading'), textInputMaxButtonClick: token ? handleMaxButtonClick : undefined, textInputValidator: amountInputValidation, textInputErrorMessage: viewState.amountError, selectSubtext: selectSubtext, textInputSubtext: `${t('views.TRANSFER.content.fiatPricePrefix')} $${formatZeroAmount(fromFiatValue, true)}`, onTextInputChange: handleAmountChange, onSelectChange: handleTokenChange, selectedOption: token?.id, defaultTokenImage: defaultTokenImage, userJourney: UserJourney.TRANSFER, screen: "TransferToken", control: "Token", theme: config.theme, themeOverrides: config.themeOverrides })] }), jsxs(Stack, { gap: "base.spacing.x1", children: [jsx(Heading, { size: "xSmall", children: t('views.TRANSFER.form.toAddressHeading') }), jsx(TextInputForm, { testId: "transfer-to-address-input", value: viewState.toAddress, placeholder: "0x", validator: validatePartialAddress, onTextInputChange: handleRecipientAddressChange, errorMessage: viewState.toAddressError })] })] }), jsxs(Box, { children: [jsx(Body, { rc: jsx("div", {}), size: "xSmall", weight: "bold", sx: { color: 'base.color.text.status.fatal.primary' }, children: t('views.TRANSFER.content.notAllExchangesSupportImmutableZkEVM') }), jsx(Body, { rc: jsx("div", {}), size: "xxSmall", weight: "regular", sx: { mb: 'base.spacing.x4' }, children: t('views.TRANSFER.content.notAllExchangesSupportImmutableZkEVMDescription') }), jsx(Button, { sx: { width: '100%' }, variant: "primary", size: "large", disabled: isButtonDisabled, onClick: onSend, children: t('views.TRANSFER.form.buttonText') })] })] }) }));
}

const sendSuccessEvent = (eventTarget, transactionHash) => {
    const successEvent = new CustomEvent(ro.IMTBL_TRANSFER_WIDGET_EVENT, {
        detail: {
            type: To.SUCCESS,
            data: {
                transactionHash,
            },
        },
    });
    // eslint-disable-next-line no-console
    console.log('transfer success event:', eventTarget, successEvent);
    if (eventTarget !== undefined)
        eventTarget.dispatchEvent(successEvent);
};
const sendFailedEvent = (eventTarget, reason) => {
    const failedEvent = new CustomEvent(ro.IMTBL_TRANSFER_WIDGET_EVENT, {
        detail: {
            type: To.FAILURE,
            data: {
                reason,
                timestamp: new Date().getTime(),
            },
        },
    });
    // eslint-disable-next-line no-console
    console.log('transfer failed event:', eventTarget, failedEvent);
    if (eventTarget !== undefined)
        eventTarget.dispatchEvent(failedEvent);
};
const sendRejectedEvent = (eventTarget, reason) => {
    const rejectedEvent = new CustomEvent(ro.IMTBL_TRANSFER_WIDGET_EVENT, {
        detail: {
            type: To.REJECTED,
            data: {
                reason,
                timestamp: new Date().getTime(),
            },
        },
    });
    // eslint-disable-next-line no-console
    console.log('transfer rejected event:', eventTarget, rejectedEvent);
    if (eventTarget !== undefined)
        eventTarget.dispatchEvent(rejectedEvent);
};

const TRANSACTION_CANCELLED_ERROR_CODE = -32003;
function TransferWidgetInner(props) {
    const { t } = useTranslation();
    const { cryptoFiatDispatch } = reactExports.useContext(CryptoFiatContext);
    const { eventTargetState: { eventTarget } } = reactExports.useContext(EventTargetContext);
    const { track } = useAnalytics();
    const { connectLoaderState: { checkout, provider }, } = reactExports.useContext(ConnectLoaderContext);
    const [viewState, setViewState] = reactExports.useState({
        type: 'INITIALISING',
    });
    reactExports.useEffect(() => {
        const x = async () => {
            if (viewState.type !== 'INITIALISING')
                return;
            if (!checkout || !provider)
                return;
            const tokensAndBalances = await loadBalances(checkout, provider);
            cryptoFiatDispatch({
                payload: {
                    type: CryptoFiatActions.SET_TOKEN_SYMBOLS,
                    tokenSymbols: tokensAndBalances.allowedBalances.map((tb) => tb.token.symbol),
                },
            });
            setViewState({
                type: 'FORM',
                allowedBalances: tokensAndBalances.allowedBalances,
                checkout,
                provider,
                amount: props.amount || '',
                amountError: '',
                tokenAddress: props.tokenAddress || '',
                toAddress: props.toAddress || '',
                toAddressError: '',
            });
        };
        x();
    }, [checkout, provider, cryptoFiatDispatch, props.amount, props.tokenAddress, props.toAddress, viewState.type]);
    const resetForm = reactExports.useCallback(() => {
        setViewState({ type: 'INITIALISING' });
    }, []);
    const onSend = reactExports.useCallback(async () => {
        if (viewState.type !== 'FORM')
            throw new Error('Unexpected state');
        track({
            screen: 'TransferToken',
            userJourney: UserJourney.TRANSFER,
            control: 'Send',
            controlType: 'Button',
            extras: { token: viewState.tokenAddress, amount: viewState.amount },
        });
        if (!isAddress(viewState.toAddress)) {
            setViewState((s) => ({ ...s, toAddressError: 'Invalid wallet address' }));
            return;
        }
        const tokenInfo = viewState.allowedBalances.find((tb) => tb.token.address === viewState.tokenAddress);
        if (!tokenInfo)
            throw new Error('Token not found');
        if (tokenInfo.balance < parseUnits(viewState.amount, tokenInfo.token.decimals)) {
            setViewState((s) => ({ ...s, amountError: 'Insufficient balance' }));
            return;
        }
        if (Number(viewState.amount) <= 0) {
            setViewState((s) => ({ ...s, amountError: 'Amount must be positive' }));
            return;
        }
        setViewState({
            type: 'AWAITING_APPROVAL',
            checkout: viewState.checkout,
            provider: viewState.provider,
            allowedBalances: viewState.allowedBalances,
        });
        try {
            const txResponse = await sendTokens(viewState.provider, tokenInfo, viewState.toAddress, viewState.amount);
            setViewState({
                type: 'TRANSFERRING',
                checkout: viewState.checkout,
                provider: viewState.provider,
                allowedBalances: viewState.allowedBalances,
            });
            const receipt = await txResponse.wait();
            if (!receipt) {
                sendFailedEvent(eventTarget, 'Transaction failed');
                setViewState({ ...viewState, type: 'FORM' }); // TODO: We should be showing a failed view here
                return;
            }
            sendSuccessEvent(eventTarget, receipt.hash);
            setViewState({
                type: 'COMPLETE',
                receipt,
                chainId: viewState.checkout.config.l2ChainId,
                checkout: viewState.checkout,
                provider: viewState.provider,
                allowedBalances: viewState.allowedBalances,
            });
        }
        catch (e) {
            setViewState({
                type: 'FORM',
                allowedBalances: viewState.allowedBalances,
                checkout: viewState.checkout,
                provider: viewState.provider,
                amount: viewState.amount,
                amountError: viewState.amountError,
                tokenAddress: viewState.tokenAddress,
                toAddress: viewState.toAddress,
                toAddressError: viewState.toAddressError,
            });
            if (isError(e, 'UNKNOWN_ERROR')
                && e.error
                && 'code' in e.error
                && e.error.code === TRANSACTION_CANCELLED_ERROR_CODE) {
                track({
                    screen: 'TransferToken',
                    userJourney: UserJourney.TRANSFER,
                    control: 'TranactionCancel',
                    controlType: 'Event',
                    extras: { token: viewState.tokenAddress, amount: viewState.amount },
                });
                sendRejectedEvent(eventTarget, 'Transaction cancelled');
            }
            else {
                // eslint-disable-next-line no-console
                console.error(e); // TODO: where can we send these?
                sendFailedEvent(eventTarget, 'Transaction failed');
                setViewState({ ...viewState, type: 'FORM' }); // TODO: We should be showing a failed view here
            }
        }
    }, [viewState, eventTarget, track]);
    switch (viewState.type) {
        case 'INITIALISING':
            return jsx(LoadingView, { loadingText: t('views.LOADING_VIEW.text') });
        case 'FORM':
            return (jsx(TransferForm, { config: props.config, viewState: viewState, setViewState: setViewState, onSend: onSend, showBackButton: props.showBackButton, showHeader: props.transferConfig.showHeader ?? true, title: props.transferConfig.customTitle ?? t('views.TRANSFER.header.title'), coinAmountTitle: props.transferConfig.customCoinAmountTitle ?? t('views.TRANSFER.form.coinAmountHeading') }));
        case 'AWAITING_APPROVAL':
            return jsx(AwaitingApproval, { config: props.config });
        case 'TRANSFERRING':
            return jsx(SendingTokens, { config: props.config });
        case 'COMPLETE':
            return (jsx(TransferComplete, { config: props.config, viewState: viewState, onContinue: resetForm }));
        default:
            throw new Error('Invalid view state');
    }
}
function TransferWidget(props) {
    const { base: { colorMode }, } = useTheme();
    return (jsx(CryptoFiatProvider, { environment: props.config.environment, children: jsxs(Stack, { sx: { pos: 'relative' }, children: [jsx(CloudImage, { use: (jsx("img", { src: getRemoteImage(props.config.environment, `/add-tokens-bg-texture-${colorMode}.webp`), alt: "blurry bg texture" })), sx: {
                        pos: 'absolute',
                        h: '100%',
                        w: '100%',
                        objectFit: 'cover',
                        objectPosition: 'center',
                    } }), jsx(TransferWidgetInner, { ...props })] }) }));
}

function CommerceWidget(props) {
    const { flowParams, flowConfig, widgetsConfig, checkout, browserProvider, } = props;
    const { t } = useTranslation();
    const viewState = useViewState();
    const [{ view, history }, viewDispatch] = viewState;
    const [{ eventTarget }] = useEventTargetState();
    const [commerceState, commerceDispatch] = reactExports.useReducer(commerceReducer, initialCommerceState);
    const commerceReducerValues = reactExports.useMemo(() => ({ commerceState, commerceDispatch }), [commerceState, commerceDispatch]);
    const { provider } = commerceState;
    const connectLoaderParams = reactExports.useMemo(() => getConnectLoaderParams(view, flowConfig, checkout, provider || browserProvider), [view, flowConfig, checkout, provider, browserProvider]);
    const connectLoaderSuccessEvent = (flowParams.flow === Ao.ADD_TOKENS
        || flowParams.flow === Ao.PURCHASE) ? () => { } : undefined;
    const goToPreviousView = reactExports.useCallback(() => {
        const sharedViews = [
            SharedViews.LOADING_VIEW,
            SharedViews.ERROR_VIEW,
            SharedViews.SUCCESS_VIEW,
            SharedViews.TOP_UP_VIEW,
            SharedViews.SERVICE_UNAVAILABLE_ERROR_VIEW,
        ];
        const views = history
            .slice(0, -1)
            .filter(({ type }) => !sharedViews.includes(type));
        const lastView = views[views.length - 1];
        if (lastView) {
            viewDispatch({
                payload: {
                    type: ViewActions.UPDATE_VIEW,
                    view: lastView,
                },
            });
        }
    }, [history]);
    const handleProviderUpdated = reactExports.useMemo(() => (updatedProvider) => {
        commerceDispatch({
            payload: {
                type: CommerceActions.SET_PROVIDER,
                provider: updatedProvider,
            },
        });
    }, [commerceDispatch]);
    /**
     * Subscribe and Handle widget events
     */
    useWidgetEvents(eventTarget, viewState, handleProviderUpdated);
    reactExports.useEffect(() => {
        if (!browserProvider) {
            return;
        }
        commerceDispatch({
            payload: {
                type: CommerceActions.SET_PROVIDER,
                provider: browserProvider,
            },
        });
    }, [commerceDispatch, browserProvider]);
    /**
     * Mount the view according to set flow in params
     */
    reactExports.useEffect(() => {
        if (!flowParams.flow)
            return;
        const { flow, ...mountedWidgetParams } = flowParams;
        viewDispatch({
            payload: {
                type: ViewActions.UPDATE_VIEW,
                view: {
                    type: flow,
                    data: {
                        params: mountedWidgetParams,
                        config: { ...(flowConfig?.[flow] || {}) },
                    },
                },
            },
        });
    }, [flowParams]);
    /**
     * If invalid flow set error view
     */
    reactExports.useEffect(() => {
        if (commerceFlows.includes(flowParams.flow))
            return;
        viewDispatch({
            payload: {
                type: ViewActions.UPDATE_VIEW,
                view: {
                    type: SharedViews.ERROR_VIEW,
                    error: {
                        name: 'InvalidViewType',
                        message: `Invalid view type "${flowParams.flow}"`,
                    },
                },
            },
        });
    }, [flowParams.flow]);
    /**
     * Validate if the view requires connect loader
     */
    const shouldWrapWithConnectLoader = reactExports.useMemo(() => isConnectLoaderFlow(view.type), [view.type]);
    /**
     * Validate if the view requires providers context
     */
    const shouldWrapWithProvidersContext = reactExports.useMemo(() => isProvidersContextFlow(view.type), [view.type]);
    /*
     * Show back button
     */
    const showBackButton = !!view.data?.showBackButton;
    return (jsx(ViewContextProvider, { children: jsxs(CommerceContext.Provider, { value: commerceReducerValues, children: [view.type === SharedViews.LOADING_VIEW && (jsx(LoadingView, { loadingText: t('views.LOADING_VIEW.text') })), view.type === SharedViews.ERROR_VIEW && (jsx(ErrorView, { onCloseClick: () => {
                        sendCheckoutEvent(eventTarget, {
                            type: mo.CLOSE,
                            data: {},
                        });
                    }, onActionClick: () => {
                        // TODO: trigger a retry
                    }, actionText: t('views.ERROR_VIEW.actionText') })), view.type === Ao.CONNECT && (jsx(ConnectWidget, { config: widgetsConfig, checkout: checkout, sendCloseEventOverride: () => {
                        sendCheckoutEvent(eventTarget, {
                            type: mo.CLOSE,
                            data: {},
                        });
                    }, ...(view.data.params || {}) })), view.type === Ao.BRIDGE && (jsx(BridgeWidget, { config: widgetsConfig, checkout: checkout, browserProvider: browserProvider, showBackButton: showBackButton, ...(view.data.params || {}) })), shouldWrapWithProvidersContext && view.type === Ao.ADD_TOKENS && (jsx(ProvidersContextProvider, { initialState: { checkout, toProvider: view.data.params.toProvider }, children: jsx(AddTokensWidget, { config: widgetsConfig, ...(view.data.params || {}), ...(view.data.config || {}), showBackButton: showBackButton }) })), shouldWrapWithProvidersContext && view.type === Ao.PURCHASE && (jsx(ProvidersContextProvider, { initialState: { checkout }, children: jsx(PurchaseWidget, { config: widgetsConfig, ...(view.data.params || {}), ...(view.data.config || {}), showBackButton: showBackButton }) })), shouldWrapWithConnectLoader && (jsx(ConnectLoader, { widgetConfig: widgetsConfig, params: connectLoaderParams, successEvent: connectLoaderSuccessEvent, closeEvent: () => {
                        sendCheckoutEvent(eventTarget, {
                            type: mo.CLOSE,
                            data: {},
                        });
                    }, showBackButton: showBackButton, goBackEvent: goToPreviousView, children: jsxs(reactExports.Suspense, { fallback: jsx(LoadingView, { loadingText: t('views.LOADING_VIEW.text') }), children: [view.type === Ao.WALLET && (jsx(WalletWidget, { config: widgetsConfig, walletConfig: {
                                    showNetworkMenu: true,
                                    showDisconnectButton: true,
                                    ...view.data.config,
                                }, ...(view.data.params || {}) })), view.type === Ao.SALE && (jsx(SaleWidget, { config: widgetsConfig, ...(view.data.params || {}), hideExcludedPaymentTypes: false,
                                waitFulfillmentSettlements: true,
                                ...view.data.config })), view.type === Ao.SWAP && (jsx(SwapWidget, { config: widgetsConfig, swapConfig: view.data.config, ...(view.data.params || {}), showBackButton: showBackButton })), view.type === Ao.ONRAMP && (jsx(OnRampWidget, { config: widgetsConfig, ...(view.data.params || {}), onrampConfig: view.data.config, showBackButton: showBackButton })), view.type === Ao.TRANSFER && (jsx(TransferWidget, { config: widgetsConfig, transferConfig: view.data.config, ...(view.data.params || {}), showBackButton: showBackButton }))] }) }))] }) }));
}

export { CommerceWidget as default };
