From 5a7bba9447919b5b96c8a3825f2c9871dbe7712f Mon Sep 17 00:00:00 2001 From: Jimmy Hardwick Date: Tue, 6 Feb 2024 16:05:26 +1100 Subject: [PATCH] feat: [GPR-385][Sale Widget] Add Coins View and Events (#1432) --- .../src/widgets/definitions/events/sale.ts | 3 ++ .../sdk/src/widgets/definitions/types.ts | 3 ++ .../src/widgets/sale/SaleWidget.tsx | 24 ++++++++++- .../src/widgets/sale/views/PaymentMethods.tsx | 23 ++++++----- .../src/components/ui/sale/sale.tsx | 40 +++++++++++++++++-- 5 files changed, 79 insertions(+), 14 deletions(-) diff --git a/packages/checkout/sdk/src/widgets/definitions/events/sale.ts b/packages/checkout/sdk/src/widgets/definitions/events/sale.ts index 26ccadeb5e..48d334ec7f 100644 --- a/packages/checkout/sdk/src/widgets/definitions/events/sale.ts +++ b/packages/checkout/sdk/src/widgets/definitions/events/sale.ts @@ -9,6 +9,9 @@ export enum SaleEventType { TRANSACTION_SUCCESS = 'transaction-success', LANGUAGE_CHANGED = 'language-changed', PAYMENT_METHOD = 'payment-method', + REQUEST_BRIDGE = 'request-bridge', + REQUEST_ONRAMP = 'request-onramp', + REQUEST_SWAP = 'request-swap', } /** diff --git a/packages/checkout/sdk/src/widgets/definitions/types.ts b/packages/checkout/sdk/src/widgets/definitions/types.ts index d2d8345e0e..d87d0c0391 100644 --- a/packages/checkout/sdk/src/widgets/definitions/types.ts +++ b/packages/checkout/sdk/src/widgets/definitions/types.ts @@ -161,6 +161,9 @@ export type WidgetEventData = { [SaleEventType.CLOSE_WIDGET]: {}, [SaleEventType.TRANSACTION_SUCCESS]: SaleTransactionSuccess, [SaleEventType.PAYMENT_METHOD]: SalePaymentMethod, + [SaleEventType.REQUEST_BRIDGE]: {}, + [SaleEventType.REQUEST_SWAP]: {}, + [SaleEventType.REQUEST_ONRAMP]: {}, } & OrchestrationMapping & ProviderEventMapping }; diff --git a/packages/checkout/widgets-lib/src/widgets/sale/SaleWidget.tsx b/packages/checkout/widgets-lib/src/widgets/sale/SaleWidget.tsx index 095c5bff99..0b4f882005 100644 --- a/packages/checkout/widgets-lib/src/widgets/sale/SaleWidget.tsx +++ b/packages/checkout/widgets-lib/src/widgets/sale/SaleWidget.tsx @@ -2,7 +2,9 @@ import { useCallback, useContext, useEffect, useMemo, useReducer, useRef, } from 'react'; -import { BlockExplorerService, ChainId, SaleWidgetParams } from '@imtbl/checkout-sdk'; +import { + BlockExplorerService, ChainId, IMTBLWidgetEvents, SaleWidgetParams, +} from '@imtbl/checkout-sdk'; import { Environment } from '@imtbl/config'; import { useTranslation } from 'react-i18next'; import { ConnectLoaderContext } from '../../context/connect-loader-context/ConnectLoaderContext'; @@ -25,6 +27,10 @@ import { PaymentMethods } from './views/PaymentMethods'; import { SaleErrorView } from './views/SaleErrorView'; import { SaleSuccessView } from './views/SaleSuccessView'; import { CryptoFiatProvider } from '../../context/crypto-fiat-context/CryptoFiatProvider'; +import { TopUpView } from '../../views/top-up/TopUpView'; +import { UserJourney } from '../../context/analytics-provider/SegmentAnalyticsProvider'; +import { sendSaleWidgetCloseEvent } from './SaleWidgetEvents'; +import { EventTargetContext } from '../../context/event-target-context/EventTargetContext'; export interface SaleWidgetProps extends Required> { config: StrongCheckoutWidgetsConfig; @@ -44,6 +50,10 @@ export function SaleWidget(props: SaleWidgetProps) { const { checkout, provider } = connectLoaderState; const chainId = useRef(); + const { + eventTargetState: { eventTarget }, + } = useContext(EventTargetContext); + const { theme } = config; const biomeTheme = useMemo(() => widgetTheme(theme), [theme]); @@ -131,6 +141,18 @@ export function SaleWidget(props: SaleWidgetProps) { {viewState.view.type === SaleWidgetViews.FUND_WITH_SMART_CHECKOUT && ( )} + {viewState.view.type === SharedViews.TOP_UP_VIEW && ( + sendSaleWidgetCloseEvent(eventTarget)} + /> + )} diff --git a/packages/checkout/widgets-lib/src/widgets/sale/views/PaymentMethods.tsx b/packages/checkout/widgets-lib/src/widgets/sale/views/PaymentMethods.tsx index d33786b198..c72a7ea2e1 100644 --- a/packages/checkout/widgets-lib/src/widgets/sale/views/PaymentMethods.tsx +++ b/packages/checkout/widgets-lib/src/widgets/sale/views/PaymentMethods.tsx @@ -3,8 +3,8 @@ import { } from '@biom3/react'; import { useContext, useEffect } from 'react'; +import { SalePaymentTypes } from '@imtbl/checkout-sdk'; import { useTranslation } from 'react-i18next'; -import { IMTBLWidgetEvents, SalePaymentTypes } from '@imtbl/checkout-sdk'; import { FooterLogo } from '../../../components/Footer/FooterLogo'; import { HeaderNavigation } from '../../../components/Header/HeaderNavigation'; import { SimpleLayout } from '../../../components/SimpleLayout/SimpleLayout'; @@ -14,8 +14,6 @@ import { ViewActions, ViewContext, } from '../../../context/view-context/ViewContext'; -import { orchestrationEvents } from '../../../lib/orchestrationEvents'; -import { EventTargetContext } from '../../../context/event-target-context/EventTargetContext'; import { PaymentOptions } from '../components/PaymentOptions'; import { useSaleContext } from '../context/SaleContextProvider'; @@ -27,8 +25,6 @@ export function PaymentMethods() { const { viewState, viewDispatch } = useContext(ViewContext); const { sign, - amount, - fromTokenAddress: tokenAddress, goToErrorView, paymentMethod, setPaymentMethod, @@ -36,7 +32,6 @@ export function PaymentMethods() { invalidParameters, } = useSaleContext(); const { sendPageView, sendCloseEvent, sendSelectedPaymentMethod } = useSaleEvent(); - const { eventTargetState: { eventTarget } } = useContext(EventTargetContext); const handleOptionClick = (type: SalePaymentTypes) => setPaymentMethod(type); @@ -81,6 +76,17 @@ export function PaymentMethods() { } }, [paymentMethod]); + const onClickInsufficientCoinsBanner = () => { + viewDispatch({ + payload: { + type: ViewActions.UPDATE_VIEW, + view: { + type: SharedViews.TOP_UP_VIEW, + }, + }, + }); + }; + const insufficientCoinsBanner = ( @@ -90,10 +96,7 @@ export function PaymentMethods() { orchestrationEvents - .sendRequestBridgeEvent(eventTarget, IMTBLWidgetEvents.IMTBL_SALE_WIDGET_EVENT, { - amount, tokenAddress, - }) + () => onClickInsufficientCoinsBanner() } > {t('views.PAYMENT_METHODS.insufficientCoinsBanner.captionCTA')} diff --git a/packages/checkout/widgets-sample-app/src/components/ui/sale/sale.tsx b/packages/checkout/widgets-sample-app/src/components/ui/sale/sale.tsx index a79740c56e..1c5de5e085 100644 --- a/packages/checkout/widgets-sample-app/src/components/ui/sale/sale.tsx +++ b/packages/checkout/widgets-sample-app/src/components/ui/sale/sale.tsx @@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from 'react'; import { Environment } from '@imtbl/config'; import { config, passport } from '@imtbl/sdk'; import { WidgetsFactory } from '@imtbl/checkout-widgets'; -import { SaleEventType, SaleItem, WidgetTheme, WidgetType } from '@imtbl/checkout-sdk'; +import { BridgeEventType, OnRampEventType, SaleEventType, SaleItem, SwapEventType, WidgetTheme, WidgetType } from '@imtbl/checkout-sdk'; import { Checkout } from '@imtbl/checkout-sdk'; import { Passport } from '@imtbl/passport'; @@ -86,7 +86,16 @@ export function SaleUI() { const factory = useMemo(() => new WidgetsFactory(checkout, {theme: WidgetTheme.DARK}), [checkout]) const saleWidget = useMemo(() => factory.create(WidgetType.SALE, { config: { theme: WidgetTheme.DARK } }), [factory, amount, environmentId, fromTokenAddress, collectionName, defaultItems] - ) + ); + const bridgeWidget = useMemo(() => factory.create(WidgetType.BRIDGE, { config: { theme: WidgetTheme.DARK } }), + [factory, amount, environmentId, fromTokenAddress, collectionName, defaultItems] + ); + const swapWidget = useMemo(() => factory.create(WidgetType.SWAP, { config: { theme: WidgetTheme.DARK } }), + [factory, amount, environmentId, fromTokenAddress, collectionName, defaultItems] + ); + const onrampWidget = useMemo(() => factory.create(WidgetType.ONRAMP, { config: { theme: WidgetTheme.DARK } }), + [factory, amount, environmentId, fromTokenAddress, collectionName, defaultItems] + ); // mount sale widget and subscribe to close event useEffect(() => { @@ -98,7 +107,29 @@ export function SaleUI() { items: defaultItems }); saleWidget.addListener(SaleEventType.CLOSE_WIDGET, () => { saleWidget.unmount()}) - }, [saleWidget]) + + saleWidget.addListener(SaleEventType.REQUEST_BRIDGE, (event) => { + saleWidget.unmount(); + + bridgeWidget.mount('bridge'); + bridgeWidget.addListener(BridgeEventType.CLOSE_WIDGET, () => { bridgeWidget.unmount()}) + return; + }); + saleWidget.addListener(SaleEventType.REQUEST_SWAP, (event) => { + saleWidget.unmount(); + + swapWidget.mount('swap'); + swapWidget.addListener(SwapEventType.CLOSE_WIDGET, () => { swapWidget.unmount()}) + return; + }); + saleWidget.addListener(SaleEventType.REQUEST_ONRAMP, (event) => { + saleWidget.unmount(); + + onrampWidget.mount('onramp'); + onrampWidget.addListener(OnRampEventType.CLOSE_WIDGET, () => { onrampWidget.unmount()}) + return; + }); + }, [saleWidget, swapWidget, bridgeWidget, onrampWidget]) const handlePassportConfigChange = (e: any) => { setPassportConfig(e.target.value); @@ -157,6 +188,9 @@ export function SaleUI() { return ( <>
+
+
+