From e47396c4b112b0eaba42c403a3dbe7cf11ddcace Mon Sep 17 00:00:00 2001 From: Mikhala <122326421+imx-mikhala@users.noreply.github.com> Date: Mon, 19 Feb 2024 08:32:56 +0800 Subject: [PATCH] WT-2017 Split checkout bundle by widget (#1441) Co-authored-by: Pano Skylakis <49353965+pano-skylakis@users.noreply.github.com> Co-authored-by: Zach Couchman Co-authored-by: Charlie McKenzie --- packages/checkout/sdk/src/sdk.ts | 108 +++++++++++++++--- packages/checkout/sdk/src/types/widgets.ts | 4 +- .../checkout/sdk/src/widgets/load.test.ts | 32 +++--- packages/checkout/sdk/src/widgets/load.ts | 29 ++--- packages/checkout/widgets-lib/package.json | 2 +- .../checkout/widgets-lib/rollup.config.js | 22 ++-- .../ConnectLoader/ConnectLoader.tsx | 2 +- .../src/widgets/bridge/BridgeWidget.cy.tsx | 2 +- .../src/widgets/bridge/BridgeWidget.tsx | 2 +- .../src/widgets/bridge/BridgeWidgetRoot.tsx | 27 +++-- .../src/widgets/connect/ConnectWidget.cy.tsx | 2 +- .../src/widgets/connect/ConnectWidget.tsx | 2 +- .../src/widgets/connect/ConnectWidgetRoot.tsx | 18 ++- .../src/widgets/on-ramp/OnRampWidget.cy.tsx | 2 +- .../src/widgets/on-ramp/OnRampWidget.tsx | 2 +- .../src/widgets/on-ramp/OnRampWidgetRoot.tsx | 20 ++-- .../src/widgets/sale/SaleWidget.tsx | 2 +- .../src/widgets/sale/SaleWidgetRoot.tsx | 28 +++-- .../FundingRouteExecute.tsx | 6 +- .../src/widgets/swap/SwapWidget.cy.tsx | 2 +- .../src/widgets/swap/SwapWidget.tsx | 2 +- .../src/widgets/swap/SwapWidgetRoot.tsx | 20 ++-- .../src/widgets/wallet/WalletWidget.cy.tsx | 2 +- .../src/widgets/wallet/WalletWidget.tsx | 2 +- .../src/widgets/wallet/WalletWidgetRoot.tsx | 16 ++- sdk/module-release.json | 7 +- sdk/scripts/copyBrowserBundles.js | 17 +++ 27 files changed, 252 insertions(+), 128 deletions(-) diff --git a/packages/checkout/sdk/src/sdk.ts b/packages/checkout/sdk/src/sdk.ts index 029ba9d673..42c2aa62b0 100644 --- a/packages/checkout/sdk/src/sdk.ts +++ b/packages/checkout/sdk/src/sdk.ts @@ -65,10 +65,13 @@ import { FiatRampService, FiatRampWidgetParams } from './fiatRamp'; import { getItemRequirementsFromRequirements } from './smartCheckout/itemRequirements'; import { CheckoutError, CheckoutErrorType } from './errors'; import { AvailabilityService, availabilityService } from './availability'; -import { loadUnresolved } from './widgets/load'; +import { getWidgetsEsmUrl, loadUnresolvedBundle } from './widgets/load'; import { WidgetsInit } from './types/widgets'; import { HttpClient } from './api/http'; import { isMatchingAddress } from './utils/utils'; +import { WidgetConfiguration } from './widgets/definitions/configurations'; +import { SemanticVersion } from './widgets/definitions/types'; +import { validateAndBuildVersion } from './widgets/version'; const SANDBOX_CONFIGURATION = { baseConfig: { @@ -76,7 +79,6 @@ const SANDBOX_CONFIGURATION = { }, passport: undefined, }; -const WIDGETS_SCRIPT_TIMEOUT = 100; // Checkout SDK export class Checkout { @@ -119,25 +121,71 @@ export class Checkout { // Preload the configurations await checkout.config.remote.getConfig(); - const factory = new Promise((resolve, reject) => { - function checkForWidgetsBundleLoaded() { - if (typeof ImmutableCheckoutWidgets !== 'undefined') { - resolve(new ImmutableCheckoutWidgets.WidgetsFactory(checkout, init.config)); - } else { - // If ImmutableCheckoutWidgets is not defined, wait for set amount of time. - // When time has elapsed, check again if ImmutableCheckoutWidgets is defined. - // Once it's defined, the promise will resolve and setTimeout won't be called again. - setTimeout(checkForWidgetsBundleLoaded, WIDGETS_SCRIPT_TIMEOUT); - } - } + try { + const factory = await this.loadEsModules(init.config, init.version); + return factory; + } catch (err: any) { + throw new CheckoutError( + 'Failed to load widgets script', + CheckoutErrorType.WIDGETS_SCRIPT_LOAD_ERROR, + { error: err }, + ); + } + } + private async loadUmdBundle( + config: WidgetConfiguration, + version?: SemanticVersion, + ) { + const checkout = this; + + const factory = new Promise((resolve, reject) => { try { - const script = loadUnresolved(init.version); - if (script.loaded && typeof ImmutableCheckoutWidgets !== 'undefined') { - resolve(new ImmutableCheckoutWidgets.WidgetsFactory(checkout, init.config)); - } else { - checkForWidgetsBundleLoaded(); + const scriptId = 'immutable-checkout-widgets-bundle'; + const validVersion = validateAndBuildVersion(version); + + // Prevent the script to be loaded more than once + // by checking the presence of the script and its version. + const initScript = document.getElementById(scriptId) as HTMLScriptElement; + if (initScript) { + if (typeof ImmutableCheckoutWidgets !== 'undefined') { + resolve(new ImmutableCheckoutWidgets.WidgetsFactory(checkout, config)); + } else { + reject( + new CheckoutError( + 'Failed to find ImmutableCheckoutWidgets script', + CheckoutErrorType.WIDGETS_SCRIPT_LOAD_ERROR, + ), + ); + } } + + const tag = document.createElement('script'); + + tag.addEventListener('load', () => { + if (typeof ImmutableCheckoutWidgets !== 'undefined') { + resolve(new ImmutableCheckoutWidgets.WidgetsFactory(checkout, config)); + } else { + reject( + new CheckoutError( + 'Failed to find ImmutableCheckoutWidgets script', + CheckoutErrorType.WIDGETS_SCRIPT_LOAD_ERROR, + ), + ); + } + }); + + tag.addEventListener('error', (err) => { + reject( + new CheckoutError( + 'Failed to load widgets script', + CheckoutErrorType.WIDGETS_SCRIPT_LOAD_ERROR, + { error: err }, + ), + ); + }); + + loadUnresolvedBundle(tag, scriptId, validVersion); } catch (err: any) { reject( new CheckoutError( @@ -152,6 +200,30 @@ export class Checkout { return factory; } + private async loadEsModules( + config: WidgetConfiguration, + version?: SemanticVersion, + ) { + const checkout = this; + try { + const cdnUrl = getWidgetsEsmUrl(version); + + // WebpackIgnore comment required to prevent webpack modifying the import statement and + // breaking the dynamic import in certain applications integrating checkout + const checkoutWidgetsModule = await import(/* webpackIgnore: true */ cdnUrl); + + if (checkoutWidgetsModule && checkoutWidgetsModule.WidgetsFactory) { + return new checkoutWidgetsModule.WidgetsFactory(checkout, config); + } + } catch (err: any) { + // eslint-disable-next-line no-console + console.warn(`Failed to resolve checkout widgets module, falling back to UMD bundle. Error: ${err.message}`); + } + + // Fallback to UMD bundle if esm bundle fails to load + return await checkout.loadUmdBundle(config, version); + } + /** * Creates a provider using the given parameters. * @param {CreateProviderParams} params - The parameters for creating the provider. diff --git a/packages/checkout/sdk/src/types/widgets.ts b/packages/checkout/sdk/src/types/widgets.ts index 626796fc5b..76f9ecf70d 100644 --- a/packages/checkout/sdk/src/types/widgets.ts +++ b/packages/checkout/sdk/src/types/widgets.ts @@ -4,9 +4,9 @@ import { SemanticVersion } from '../widgets/definitions/types'; /** * Represents the configuration options for instantiating the Checkout Widgets factory. * @property {WidgetConfiguration} config - global configuration options for the widgets. - * @property {SemanticVersion | undefined} version - version of the Checkout widgets bundle (default latest version will be used). + * @property {SemanticVersion | undefined} version - version of the Checkout widgets bundle(default latest version will be used). */ export type WidgetsInit = { config: WidgetConfiguration; - version?: SemanticVersion + version?: SemanticVersion; }; diff --git a/packages/checkout/sdk/src/widgets/load.test.ts b/packages/checkout/sdk/src/widgets/load.test.ts index 2c5a03d7bd..44b330c562 100644 --- a/packages/checkout/sdk/src/widgets/load.test.ts +++ b/packages/checkout/sdk/src/widgets/load.test.ts @@ -1,45 +1,41 @@ /** @jest-environment jsdom */ import { SDK_VERSION_MARKER } from '../env'; -import { loadUnresolved } from './load'; +import { getWidgetsEsmUrl, loadUnresolvedBundle } from './load'; describe('load', () => { const SDK_VERSION = SDK_VERSION_MARKER; + const scriptId = 'immutable-checkout-widgets-bundle'; beforeEach(() => { jest.spyOn(console, 'warn').mockImplementation(() => {}); }); - describe('Config', () => { + describe('load unresolved bundle', () => { it('should validate the versioning', () => { - loadUnresolved(); + const tag = document.createElement('script'); + loadUnresolvedBundle(tag, scriptId, SDK_VERSION); expect(document.head.innerHTML).toBe( '`, ); }); + }); - it('should not re-add script', () => { - loadUnresolved(); - loadUnresolved(); - loadUnresolved(); - expect(document.head.innerHTML).toBe( - '`, + describe('get widgets esm url', () => { + it('should validate the versioning', () => { + expect(getWidgetsEsmUrl()).toEqual( + `https://cdn.jsdelivr.net/npm/@imtbl/sdk@${SDK_VERSION}/dist/browser/checkout/widgets-esm.js`, ); }); it('should change version', () => { - loadUnresolved(); - loadUnresolved({ + expect(getWidgetsEsmUrl({ major: 1, minor: 2, - }); - expect(document.head.innerHTML).toBe( - '`, + patch: 3, + })).toEqual( + 'https://cdn.jsdelivr.net/npm/@imtbl/sdk@1.2.3/dist/browser/checkout/widgets-esm.js', ); }); }); diff --git a/packages/checkout/sdk/src/widgets/load.ts b/packages/checkout/sdk/src/widgets/load.ts index 213b64a4f9..4711a497b8 100644 --- a/packages/checkout/sdk/src/widgets/load.ts +++ b/packages/checkout/sdk/src/widgets/load.ts @@ -2,9 +2,12 @@ import { useLocalBundle } from '../env'; import { SemanticVersion } from './definitions/types'; import { validateAndBuildVersion } from './version'; -export function loadUnresolved( - version?: SemanticVersion, -): { loaded: boolean, element: HTMLScriptElement } { +// Loads the checkout widgets bundle from the CDN and appends the script to the document head +export function loadUnresolvedBundle( + tag: HTMLScriptElement, + scriptId: string, + validVersion: string, +) { if (window === undefined) { throw new Error('missing window object: please run Checkout client side'); } @@ -13,16 +16,6 @@ export function loadUnresolved( throw new Error('missing document object: please run Checkout client side'); } - const scriptId = 'immutable-checkout-widgets-bundle'; - const validVersion = validateAndBuildVersion(version); - - // Prevent the script to be loaded more than once - // by checking the presence of the script and its version. - const initScript = document.getElementById(scriptId) as HTMLScriptElement; - if (initScript) return { loaded: true, element: initScript }; - - const tag = document.createElement('script'); - let cdnUrl = `https://cdn.jsdelivr.net/npm/@imtbl/sdk@${validVersion}/dist/browser/checkout/widgets.js`; if (useLocalBundle()) cdnUrl = `http://${window.location.host}/lib/js/widgets.js`; @@ -31,6 +24,14 @@ export function loadUnresolved( tag.setAttribute('src', cdnUrl); document.head.appendChild(tag); +} - return { loaded: false, element: tag }; +// Gets the CDN url for the split checkout widgets bundle +export function getWidgetsEsmUrl( + version?: SemanticVersion, +): string { + const validVersion = validateAndBuildVersion(version); + let cdnUrl = `https://cdn.jsdelivr.net/npm/@imtbl/sdk@${validVersion}/dist/browser/checkout/widgets-esm.js`; + if (useLocalBundle()) cdnUrl = `http://${window.location.host}/lib/js/index.js`; + return cdnUrl; } diff --git a/packages/checkout/widgets-lib/package.json b/packages/checkout/widgets-lib/package.json index 37f048a2d2..f91c94018c 100644 --- a/packages/checkout/widgets-lib/package.json +++ b/packages/checkout/widgets-lib/package.json @@ -76,7 +76,7 @@ "private": true, "scripts": { "build": "rollup --config rollup.config.js", - "build:local": "yarn build && mkdir -p ../widgets-sample-app/public/lib/js && cp dist/widgets.js ../widgets-sample-app/public/lib/js/widgets.js", + "build:local": "yarn build && mkdir -p ../widgets-sample-app/public/lib/js && cp dist/*.js ../widgets-sample-app/public/lib/js/", "lint": "eslint ./src --ext .ts,.jsx,.tsx --max-warnings=0", "lint:fix": "eslint ./src --ext .ts,.jsx,.tsx --max-warnings=0 --fix", "start": "rollup --config rollup.config.js --watch", diff --git a/packages/checkout/widgets-lib/rollup.config.js b/packages/checkout/widgets-lib/rollup.config.js index af564b4685..19ddd39faa 100644 --- a/packages/checkout/widgets-lib/rollup.config.js +++ b/packages/checkout/widgets-lib/rollup.config.js @@ -7,12 +7,19 @@ import replace from '@rollup/plugin-replace'; import nodePolyfills from 'rollup-plugin-polyfill-node'; const defaultPlugin = [ + resolve({ + browser: true, + dedupe: ['react', 'react-dom'], + }), + nodePolyfills(), + commonjs(), json(), replace({ preventAssignment: true, 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production'), }), - typescript() + typescript(), + terser() ] export default [ @@ -23,7 +30,9 @@ export default [ dir: 'dist', format: 'es' }, - plugins: [...defaultPlugin ], + plugins: [ + ...defaultPlugin, + ] }, { watch: false, @@ -36,14 +45,7 @@ export default [ }, context: 'window', plugins: [ - resolve({ - browser: true, - dedupe: ['react', 'react-dom'], - }), - nodePolyfills(), - commonjs(), - ...defaultPlugin, - terser(), + ...defaultPlugin,, ] } ] diff --git a/packages/checkout/widgets-lib/src/components/ConnectLoader/ConnectLoader.tsx b/packages/checkout/widgets-lib/src/components/ConnectLoader/ConnectLoader.tsx index c55079c1f5..e72d9d27a5 100644 --- a/packages/checkout/widgets-lib/src/components/ConnectLoader/ConnectLoader.tsx +++ b/packages/checkout/widgets-lib/src/components/ConnectLoader/ConnectLoader.tsx @@ -21,7 +21,7 @@ import { initialConnectLoaderState, } from '../../context/connect-loader-context/ConnectLoaderContext'; import { LoadingView } from '../../views/loading/LoadingView'; -import { ConnectWidget } from '../../widgets/connect/ConnectWidget'; +import ConnectWidget from '../../widgets/connect/ConnectWidget'; import { ConnectWidgetViews } from '../../context/view-context/ConnectViewContextTypes'; import { StrongCheckoutWidgetsConfig } from '../../lib/withDefaultWidgetConfig'; import { useAnalytics } from '../../context/analytics-provider/SegmentAnalyticsProvider'; diff --git a/packages/checkout/widgets-lib/src/widgets/bridge/BridgeWidget.cy.tsx b/packages/checkout/widgets-lib/src/widgets/bridge/BridgeWidget.cy.tsx index 1e49fe320a..c43e997655 100644 --- a/packages/checkout/widgets-lib/src/widgets/bridge/BridgeWidget.cy.tsx +++ b/packages/checkout/widgets-lib/src/widgets/bridge/BridgeWidget.cy.tsx @@ -11,7 +11,7 @@ import { BigNumber } from 'ethers'; import { TokenBridge } from '@imtbl/bridge-sdk'; import { ViewContextTestComponent } from 'context/view-context/test-components/ViewContextTestComponent'; import { Transaction } from 'lib/clients'; -import { BridgeWidget } from './BridgeWidget'; +import BridgeWidget from './BridgeWidget'; import mockTransactionPending from './test-components/BridgeTransactionWithdrawalPending.json'; import mockTransactionInProgress from './test-components/BridgeTransactionInProgress.json'; diff --git a/packages/checkout/widgets-lib/src/widgets/bridge/BridgeWidget.tsx b/packages/checkout/widgets-lib/src/widgets/bridge/BridgeWidget.tsx index d35fcd2804..e214cd0be9 100644 --- a/packages/checkout/widgets-lib/src/widgets/bridge/BridgeWidget.tsx +++ b/packages/checkout/widgets-lib/src/widgets/bridge/BridgeWidget.tsx @@ -67,7 +67,7 @@ export type BridgeWidgetInputs = BridgeWidgetParams & { web3Provider?: Web3Provider; }; -export function BridgeWidget({ +export default function BridgeWidget({ checkout, web3Provider, config, diff --git a/packages/checkout/widgets-lib/src/widgets/bridge/BridgeWidgetRoot.tsx b/packages/checkout/widgets-lib/src/widgets/bridge/BridgeWidgetRoot.tsx index 4502a41d59..cb91b5b7e0 100644 --- a/packages/checkout/widgets-lib/src/widgets/bridge/BridgeWidgetRoot.tsx +++ b/packages/checkout/widgets-lib/src/widgets/bridge/BridgeWidgetRoot.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import { BridgeWidgetParams, IMTBLWidgetEvents, @@ -9,9 +9,12 @@ import { } from '@imtbl/checkout-sdk'; import { Base } from 'widgets/BaseWidgetRoot'; import { isValidWalletProvider, isValidAmount, isValidAddress } from 'lib/validations/widgetValidators'; -import { BridgeWidget } from 'widgets/bridge/BridgeWidget'; import { ThemeProvider } from 'components/ThemeProvider/ThemeProvider'; import { CustomAnalyticsProvider } from 'context/analytics-provider/CustomAnalyticsProvider'; +import { LoadingView } from 'views/loading/LoadingView'; +import i18n from '../../i18n'; + +const BridgeWidget = React.lazy(() => import('./BridgeWidget')); export class Bridge extends Base { protected eventTopic: IMTBLWidgetEvents = IMTBLWidgetEvents.IMTBL_BRIDGE_WIDGET_EVENT; @@ -57,18 +60,22 @@ export class Bridge extends Base { protected render() { if (!this.reactRoot) return; + const { t } = i18n; + this.reactRoot.render( - + }> + + , diff --git a/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidget.cy.tsx b/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidget.cy.tsx index 746160e38b..e114851e42 100644 --- a/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidget.cy.tsx +++ b/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidget.cy.tsx @@ -13,7 +13,7 @@ import { ExternalProvider, Web3Provider } from '@ethersproject/providers'; import { Passport } from '@imtbl/passport'; import { ViewContextTestComponent } from 'context/view-context/test-components/ViewContextTestComponent'; import { cyIntercept, cySmartGet } from '../../lib/testUtils'; -import { ConnectWidget } from './ConnectWidget'; +import ConnectWidget from './ConnectWidget'; import { StrongCheckoutWidgetsConfig } from '../../lib/withDefaultWidgetConfig'; describe('ConnectWidget tests', () => { diff --git a/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidget.tsx b/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidget.tsx index 1a28b3eb17..31b3385d1b 100644 --- a/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidget.tsx +++ b/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidget.tsx @@ -52,7 +52,7 @@ export type ConnectWidgetInputs = ConnectWidgetParams & { web3Provider?: Web3Provider; }; -export function ConnectWidget({ +export default function ConnectWidget({ config, sendCloseEventOverride, web3Provider, diff --git a/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidgetRoot.tsx b/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidgetRoot.tsx index 7a82b4b609..fb6c1ece96 100644 --- a/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidgetRoot.tsx +++ b/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidgetRoot.tsx @@ -1,12 +1,15 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import { ConnectWidgetParams, IMTBLWidgetEvents, WidgetProperties, WidgetType, } from '@imtbl/checkout-sdk'; import { ThemeProvider } from 'components/ThemeProvider/ThemeProvider'; import { CustomAnalyticsProvider } from 'context/analytics-provider/CustomAnalyticsProvider'; -import { ConnectWidget } from './ConnectWidget'; +import { LoadingView } from 'views/loading/LoadingView'; +import i18n from '../../i18n'; import { Base } from '../BaseWidgetRoot'; +const ConnectWidget = React.lazy(() => import('./ConnectWidget')); + export class Connect extends Base { protected eventTopic: IMTBLWidgetEvents = IMTBLWidgetEvents.IMTBL_CONNECT_WIDGET_EVENT; @@ -24,15 +27,18 @@ export class Connect extends Base { protected render() { if (!this.reactRoot) return; + const { t } = i18n; this.reactRoot.render( - + }> + + , diff --git a/packages/checkout/widgets-lib/src/widgets/on-ramp/OnRampWidget.cy.tsx b/packages/checkout/widgets-lib/src/widgets/on-ramp/OnRampWidget.cy.tsx index 441919b164..347fc9c430 100644 --- a/packages/checkout/widgets-lib/src/widgets/on-ramp/OnRampWidget.cy.tsx +++ b/packages/checkout/widgets-lib/src/widgets/on-ramp/OnRampWidget.cy.tsx @@ -6,7 +6,7 @@ import { } from '@imtbl/checkout-sdk'; import { Web3Provider } from '@ethersproject/providers'; import { cySmartGet } from '../../lib/testUtils'; -import { OnRampWidget, OnRampWidgetInputs } from './OnRampWidget'; +import OnRampWidget, { OnRampWidgetInputs } from './OnRampWidget'; import { StrongCheckoutWidgetsConfig } from '../../lib/withDefaultWidgetConfig'; import { ConnectLoaderTestComponent, diff --git a/packages/checkout/widgets-lib/src/widgets/on-ramp/OnRampWidget.tsx b/packages/checkout/widgets-lib/src/widgets/on-ramp/OnRampWidget.tsx index 864fd242a4..f1830042f1 100644 --- a/packages/checkout/widgets-lib/src/widgets/on-ramp/OnRampWidget.tsx +++ b/packages/checkout/widgets-lib/src/widgets/on-ramp/OnRampWidget.tsx @@ -29,7 +29,7 @@ export type OnRampWidgetInputs = OnRampWidgetParams & { config: StrongCheckoutWidgetsConfig }; -export function OnRampWidget({ +export default function OnRampWidget({ amount, tokenAddress, config, }: OnRampWidgetInputs) { const { diff --git a/packages/checkout/widgets-lib/src/widgets/on-ramp/OnRampWidgetRoot.tsx b/packages/checkout/widgets-lib/src/widgets/on-ramp/OnRampWidgetRoot.tsx index 0d3b49dec0..494254f5fb 100644 --- a/packages/checkout/widgets-lib/src/widgets/on-ramp/OnRampWidgetRoot.tsx +++ b/packages/checkout/widgets-lib/src/widgets/on-ramp/OnRampWidgetRoot.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import { ConnectTargetLayer, IMTBLWidgetEvents, @@ -14,8 +14,11 @@ import { getL1ChainId, getL2ChainId } from 'lib'; import { isValidAddress, isValidAmount } from 'lib/validations/widgetValidators'; import { ThemeProvider } from 'components/ThemeProvider/ThemeProvider'; import { CustomAnalyticsProvider } from 'context/analytics-provider/CustomAnalyticsProvider'; -import { OnRampWidget } from './OnRampWidget'; +import { LoadingView } from 'views/loading/LoadingView'; import { sendOnRampWidgetCloseEvent } from './OnRampWidgetEvents'; +import i18n from '../../i18n'; + +const OnRampWidget = React.lazy(() => import('./OnRampWidget')); export class OnRamp extends Base { protected eventTopic: IMTBLWidgetEvents = IMTBLWidgetEvents.IMTBL_ONRAMP_WIDGET_EVENT; @@ -57,6 +60,7 @@ export class OnRamp extends Base { protected render() { if (!this.reactRoot) return; + const { t } = i18n; const connectLoaderParams: ConnectLoaderParams = { targetLayer: ConnectTargetLayer.LAYER2, walletProviderName: this.parameters.walletProviderName, @@ -74,11 +78,13 @@ export class OnRamp extends Base { params={connectLoaderParams} closeEvent={() => sendOnRampWidgetCloseEvent(window)} > - + }> + + diff --git a/packages/checkout/widgets-lib/src/widgets/sale/SaleWidget.tsx b/packages/checkout/widgets-lib/src/widgets/sale/SaleWidget.tsx index 0b4f882005..dc1a37bc90 100644 --- a/packages/checkout/widgets-lib/src/widgets/sale/SaleWidget.tsx +++ b/packages/checkout/widgets-lib/src/widgets/sale/SaleWidget.tsx @@ -36,7 +36,7 @@ export interface SaleWidgetProps extends Required import('./SaleWidget')); export class Sale extends Base { protected eventTopic: IMTBLWidgetEvents = IMTBLWidgetEvents.IMTBL_SALE_WIDGET_EVENT; @@ -91,6 +94,7 @@ export class Sale extends Base { protected render() { if (!this.reactRoot) return; + const { t } = i18n; const connectLoaderParams: ConnectLoaderParams = { targetLayer: ConnectTargetLayer.LAYER2, web3Provider: this.web3Provider, @@ -111,15 +115,17 @@ export class Sale extends Base { sendSaleWidgetCloseEvent(window); }} > - + }> + + diff --git a/packages/checkout/widgets-lib/src/widgets/sale/components/FundingRouteExecute/FundingRouteExecute.tsx b/packages/checkout/widgets-lib/src/widgets/sale/components/FundingRouteExecute/FundingRouteExecute.tsx index 16fb5c6dbf..10cde212a9 100644 --- a/packages/checkout/widgets-lib/src/widgets/sale/components/FundingRouteExecute/FundingRouteExecute.tsx +++ b/packages/checkout/widgets-lib/src/widgets/sale/components/FundingRouteExecute/FundingRouteExecute.tsx @@ -19,7 +19,7 @@ import { useContext, useEffect, useMemo, useReducer, useRef, useState, } from 'react'; -import { BridgeWidget } from 'widgets/bridge/BridgeWidget'; +import BridgeWidget from 'widgets/bridge/BridgeWidget'; import { useTranslation } from 'react-i18next'; import { ConnectLoaderActions, @@ -33,8 +33,8 @@ import { SaleWidgetViews } from '../../../../context/view-context/SaleViewContex import { ViewActions, ViewContext } from '../../../../context/view-context/ViewContext'; import { getL1ChainId, getL2ChainId } from '../../../../lib/networkUtils'; import { LoadingView } from '../../../../views/loading/LoadingView'; -import { ConnectWidget } from '../../../connect/ConnectWidget'; -import { SwapWidget } from '../../../swap/SwapWidget'; +import ConnectWidget from '../../../connect/ConnectWidget'; +import SwapWidget from '../../../swap/SwapWidget'; import { useSaleContext } from '../../context/SaleContextProvider'; import { SaleErrorTypes } from '../../types'; diff --git a/packages/checkout/widgets-lib/src/widgets/swap/SwapWidget.cy.tsx b/packages/checkout/widgets-lib/src/widgets/swap/SwapWidget.cy.tsx index ef26943e97..6903726f2b 100644 --- a/packages/checkout/widgets-lib/src/widgets/swap/SwapWidget.cy.tsx +++ b/packages/checkout/widgets-lib/src/widgets/swap/SwapWidget.cy.tsx @@ -10,7 +10,7 @@ import { Environment } from '@imtbl/config'; import { Web3Provider } from '@ethersproject/providers'; import { ViewContextTestComponent } from 'context/view-context/test-components/ViewContextTestComponent'; import { cyIntercept, cySmartGet } from '../../lib/testUtils'; -import { SwapWidget } from './SwapWidget'; +import SwapWidget from './SwapWidget'; import { StrongCheckoutWidgetsConfig } from '../../lib/withDefaultWidgetConfig'; import { quotesProcessor } from './functions/FetchQuote'; import { ConnectionStatus } from '../../context/connect-loader-context/ConnectLoaderContext'; diff --git a/packages/checkout/widgets-lib/src/widgets/swap/SwapWidget.tsx b/packages/checkout/widgets-lib/src/widgets/swap/SwapWidget.tsx index da20d6d856..c64e3ffc03 100644 --- a/packages/checkout/widgets-lib/src/widgets/swap/SwapWidget.tsx +++ b/packages/checkout/widgets-lib/src/widgets/swap/SwapWidget.tsx @@ -56,7 +56,7 @@ export type SwapWidgetInputs = SwapWidgetParams & { config: StrongCheckoutWidgetsConfig; }; -export function SwapWidget({ +export default function SwapWidget({ amount, fromTokenAddress, toTokenAddress, diff --git a/packages/checkout/widgets-lib/src/widgets/swap/SwapWidgetRoot.tsx b/packages/checkout/widgets-lib/src/widgets/swap/SwapWidgetRoot.tsx index 5cc0a43a5b..42fc7dcb30 100644 --- a/packages/checkout/widgets-lib/src/widgets/swap/SwapWidgetRoot.tsx +++ b/packages/checkout/widgets-lib/src/widgets/swap/SwapWidgetRoot.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import { ConnectTargetLayer, IMTBLWidgetEvents, @@ -18,11 +18,13 @@ import { ServiceType } from 'views/error/serviceTypes'; import { isValidAddress, isValidAmount, isValidWalletProvider } from 'lib/validations/widgetValidators'; import { ThemeProvider } from 'components/ThemeProvider/ThemeProvider'; import { CustomAnalyticsProvider } from 'context/analytics-provider/CustomAnalyticsProvider'; +import { LoadingView } from 'views/loading/LoadingView'; import { topUpBridgeOption, topUpOnRampOption } from './helpers'; import { sendSwapWidgetCloseEvent } from './SwapWidgetEvents'; -import { SwapWidget } from './SwapWidget'; import i18n from '../../i18n'; +const SwapWidget = React.lazy(() => import('./SwapWidget')); + export class Swap extends Base { protected eventTopic: IMTBLWidgetEvents = IMTBLWidgetEvents.IMTBL_SWAP_WIDGET_EVENT; @@ -125,12 +127,14 @@ export class Swap extends Base { widgetConfig={this.strongConfig()} closeEvent={() => sendSwapWidgetCloseEvent(window)} > - + }> + + ) : ( diff --git a/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidget.cy.tsx b/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidget.cy.tsx index a3fe4930eb..2666cad14e 100644 --- a/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidget.cy.tsx +++ b/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidget.cy.tsx @@ -9,7 +9,7 @@ import { ExternalProvider, Web3Provider } from '@ethersproject/providers'; import { BigNumber } from 'ethers'; import { Environment } from '@imtbl/config'; import { CryptoFiat } from '@imtbl/cryptofiat'; -import { WalletWidget } from './WalletWidget'; +import WalletWidget from './WalletWidget'; import { cyIntercept, cySmartGet } from '../../lib/testUtils'; import { StrongCheckoutWidgetsConfig } from '../../lib/withDefaultWidgetConfig'; import { diff --git a/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidget.tsx b/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidget.tsx index 796c79fd49..2c8d4590c0 100644 --- a/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidget.tsx +++ b/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidget.tsx @@ -38,7 +38,7 @@ export type WalletWidgetInputs = WalletWidgetParams & { config: StrongCheckoutWidgetsConfig }; -export function WalletWidget(props: WalletWidgetInputs) { +export default function WalletWidget(props: WalletWidgetInputs) { const { t } = useTranslation(); const errorActionText = t('views.ERROR_VIEW.actionText'); const loadingText = t('views.LOADING_VIEW.text'); diff --git a/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidgetRoot.tsx b/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidgetRoot.tsx index 14e027cf2c..64505d0b17 100644 --- a/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidgetRoot.tsx +++ b/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidgetRoot.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import { ConnectTargetLayer, IMTBLWidgetEvents, @@ -14,8 +14,11 @@ import { getL1ChainId, getL2ChainId } from 'lib'; import { isValidWalletProvider } from 'lib/validations/widgetValidators'; import { ThemeProvider } from 'components/ThemeProvider/ThemeProvider'; import { CustomAnalyticsProvider } from 'context/analytics-provider/CustomAnalyticsProvider'; -import { WalletWidget } from './WalletWidget'; +import { LoadingView } from 'views/loading/LoadingView'; import { sendWalletWidgetCloseEvent } from './WalletWidgetEvents'; +import i18n from '../../i18n'; + +const WalletWidget = React.lazy(() => import('./WalletWidget')); export class Wallet extends Base { protected eventTopic: IMTBLWidgetEvents = IMTBLWidgetEvents.IMTBL_WALLET_WIDGET_EVENT; @@ -50,6 +53,7 @@ export class Wallet extends Base { protected render() { if (!this.reactRoot) return; + const { t } = i18n; const connectLoaderParams: ConnectLoaderParams = { targetLayer: ConnectTargetLayer.LAYER2, walletProviderName: this.parameters?.walletProviderName, @@ -67,9 +71,11 @@ export class Wallet extends Base { params={connectLoaderParams} closeEvent={() => sendWalletWidgetCloseEvent(window)} > - + }> + + diff --git a/sdk/module-release.json b/sdk/module-release.json index 4390e2c26d..198fc230e8 100644 --- a/sdk/module-release.json +++ b/sdk/module-release.json @@ -16,9 +16,10 @@ }, "fileCopy": [ { - "src": "../packages/checkout/widgets-lib/dist/widgets.js", - "dest": "./dist/browser/checkout/widgets.js", - "stage": "prod" + "src": "../packages/checkout/widgets-lib/dist/index.js", + "dest": "./dist/browser/checkout/widgets-esm.js", + "stage": "prod", + "copyAllJsFiles": true }, { "src": "../packages/checkout/sdk/dist/browser.js", diff --git a/sdk/scripts/copyBrowserBundles.js b/sdk/scripts/copyBrowserBundles.js index d711352af0..7e5591b999 100755 --- a/sdk/scripts/copyBrowserBundles.js +++ b/sdk/scripts/copyBrowserBundles.js @@ -53,6 +53,23 @@ const main = () => { // data = findAndReplace(data, , ); fs.writeFileSync(destPath, data); + + // Copy over all js files when the copyAllJsFiles flag is set + if (item.copyAllJsFiles) { + const srcDirectory = path.dirname(sourceFile); + const jsFiles = fs.readdirSync(srcDirectory); + jsFiles.forEach((jsFile) => { + // Check if the file is a .js file + if (path.extname(jsFile) === '.js') { + // Skip copying the original file and copy over all other .js files + if (jsFile !== path.basename(sourceFile)) { + const jsSrcPath = path.join(srcDirectory, jsFile); + const jsDestPath = path.join(directoryPath, jsFile); + fs.copyFileSync(jsSrcPath, jsDestPath); + } + } + }); + } }); } });