diff --git a/.changeset/brave-balloons-wait.md b/.changeset/brave-balloons-wait.md new file mode 100644 index 0000000000..ae36ec39d2 --- /dev/null +++ b/.changeset/brave-balloons-wait.md @@ -0,0 +1,25 @@ +--- +'@apps/laboratory': patch +'@reown/appkit-wallet': patch +'@apps/demo': patch +'@apps/gallery': patch +'@reown/appkit-adapter-ethers': patch +'@reown/appkit-adapter-ethers5': patch +'@reown/appkit-adapter-polkadot': patch +'@reown/appkit-adapter-solana': patch +'@reown/appkit-adapter-wagmi': patch +'@reown/appkit': patch +'@reown/appkit-utils': patch +'@reown/appkit-cdn': patch +'@reown/appkit-common': patch +'@reown/appkit-core': patch +'@reown/appkit-experimental': patch +'@reown/appkit-polyfills': patch +'@reown/appkit-scaffold-ui': patch +'@reown/appkit-siwe': patch +'@reown/appkit-siwx': patch +'@reown/appkit-ui': patch +--- + +Update secure site url to include version 2.0.0 parameter. +Defers frame load until it's needed on email or social connection or reconnection. diff --git a/apps/laboratory/tests/email.spec.ts b/apps/laboratory/tests/email.spec.ts index f29d47d0d7..058c861e4b 100644 --- a/apps/laboratory/tests/email.spec.ts +++ b/apps/laboratory/tests/email.spec.ts @@ -37,6 +37,9 @@ emailTest.beforeAll(async ({ browser, library }) => { } email = new Email(mailsacApiKey) tempEmail = await email.getEmailAddressToUse() + + // Iframe should not be injected until needed + validator.expectSecureSiteFrameNotInjected() await page.emailFlow(tempEmail, context, mailsacApiKey) await validator.expectConnected() diff --git a/apps/laboratory/tests/siwe-email.spec.ts b/apps/laboratory/tests/siwe-email.spec.ts index f3e8b41676..4decdb0c86 100644 --- a/apps/laboratory/tests/siwe-email.spec.ts +++ b/apps/laboratory/tests/siwe-email.spec.ts @@ -33,6 +33,9 @@ emailSiweTest.beforeAll(async ({ browser, library }) => { } const email = new Email(mailsacApiKey) const tempEmail = await email.getEmailAddressToUse() + + // Iframe should not be injected until needed + validator.expectSecureSiteFrameNotInjected() await page.emailFlow(tempEmail, context, mailsacApiKey) await page.promptSiwe() await page.approveSign() diff --git a/apps/laboratory/tests/siwe-sa.spec.ts b/apps/laboratory/tests/siwe-sa.spec.ts index 3fc54c2db7..d43b3bbe12 100644 --- a/apps/laboratory/tests/siwe-sa.spec.ts +++ b/apps/laboratory/tests/siwe-sa.spec.ts @@ -39,6 +39,9 @@ smartAccountSiweTest.beforeAll(async ({ browser, library }) => { await validator.expectSwitchedNetworkOnNetworksView('Polygon') await page.closeModal() const tempEmail = await email.getEmailAddressToUse() + + // Iframe should not be injected until needed + validator.expectSecureSiteFrameNotInjected() await page.emailFlow(tempEmail, context, mailsacApiKey) await page.promptSiwe() await page.approveSign() diff --git a/apps/laboratory/tests/smart-account.spec.ts b/apps/laboratory/tests/smart-account.spec.ts index 3a00c379de..787673e5f4 100644 --- a/apps/laboratory/tests/smart-account.spec.ts +++ b/apps/laboratory/tests/smart-account.spec.ts @@ -30,6 +30,10 @@ smartAccountTest.beforeAll(async ({ browser, library }) => { if (!mailsacApiKey) { throw new Error('MAILSAC_API_KEY is not set') } + + // Iframe should not be injected until needed + validator.expectSecureSiteFrameNotInjected() + const email = new Email(mailsacApiKey) // Switch to a SA enabled network diff --git a/apps/laboratory/tests/wallet-features.spec.ts b/apps/laboratory/tests/wallet-features.spec.ts index 6114651898..212b75d4f9 100644 --- a/apps/laboratory/tests/wallet-features.spec.ts +++ b/apps/laboratory/tests/wallet-features.spec.ts @@ -40,6 +40,9 @@ walletFeaturesTest.beforeAll(async ({ browser, browserName, library }) => { } const email = new Email(mailsacApiKey) const tempEmail = await email.getEmailAddressToUse() + + // Iframe should not be injected until needed + validator.expectSecureSiteFrameNotInjected() await page.emailFlow(tempEmail, context, mailsacApiKey) await validator.expectConnected() diff --git a/packages/appkit/exports/constants.ts b/packages/appkit/exports/constants.ts index 4d6fd5041c..783c72f7cc 100644 --- a/packages/appkit/exports/constants.ts +++ b/packages/appkit/exports/constants.ts @@ -1 +1 @@ -export const PACKAGE_VERSION = '1.4.1' +export const PACKAGE_VERSION = '1.5.0' diff --git a/packages/wallet/src/W3mFrame.ts b/packages/wallet/src/W3mFrame.ts index 498708039c..9d08687670 100644 --- a/packages/wallet/src/W3mFrame.ts +++ b/packages/wallet/src/W3mFrame.ts @@ -1,4 +1,4 @@ -import { SECURE_SITE_SDK, W3mFrameConstants } from './W3mFrameConstants.js' +import { SECURE_SITE_SDK, SECURE_SITE_SDK_VERSION, W3mFrameConstants } from './W3mFrameConstants.js' import { W3mFrameSchema } from './W3mFrameSchema.js' import { W3mFrameHelpers } from './W3mFrameHelpers.js' import type { W3mFrameTypes } from './W3mFrameTypes.js' @@ -39,7 +39,7 @@ export class W3mFrame { if (W3mFrameHelpers.isClient) { const iframe = document.createElement('iframe') iframe.id = 'w3m-iframe' - iframe.src = `${SECURE_SITE_SDK}?projectId=${projectId}&chainId=${chainId}` + iframe.src = `${SECURE_SITE_SDK}?projectId=${projectId}&chainId=${chainId}&version=${SECURE_SITE_SDK_VERSION}` iframe.name = 'w3m-secure-iframe' iframe.style.position = 'fixed' iframe.style.zIndex = '999999' @@ -47,18 +47,27 @@ export class W3mFrame { iframe.style.animationDelay = '0s, 50ms' iframe.style.borderBottomLeftRadius = `clamp(0px, var(--wui-border-radius-l), 44px)` iframe.style.borderBottomRightRadius = `clamp(0px, var(--wui-border-radius-l), 44px)` - document.body.appendChild(iframe) this.iframe = iframe - this.iframe.onload = () => { - this.frameLoadPromiseResolver?.resolve(undefined) - } this.iframe.onerror = () => { this.frameLoadPromiseResolver?.reject('Unable to load email login dependency') } + + this.events.onFrameEvent(event => { + if (event.type === '@w3m-frame/READY') { + this.frameLoadPromiseResolver?.resolve(undefined) + } + }) } } } + public initFrame = () => { + const isFrameInitialized = document.getElementById('w3m-iframe') + if (this.iframe && !isFrameInitialized) { + document.body.appendChild(this.iframe) + } + } + // -- Networks -------------------------------------------------------------- get networks(): Record { const data = [ @@ -136,6 +145,7 @@ export class W3mFrame { ) { return } + const frameEvent = W3mFrameSchema.frameEvent.parse(data) callback(frameEvent) }) diff --git a/packages/wallet/src/W3mFrameConstants.ts b/packages/wallet/src/W3mFrameConstants.ts index a60056e804..d85418d2c4 100644 --- a/packages/wallet/src/W3mFrameConstants.ts +++ b/packages/wallet/src/W3mFrameConstants.ts @@ -3,6 +3,8 @@ export const SECURE_SITE_SDK = export const DEFAULT_LOG_LEVEL = process.env['NEXT_PUBLIC_DEFAULT_LOG_LEVEL'] || 'error' +export const SECURE_SITE_SDK_VERSION = process.env['NEXT_PUBLIC_SECURE_SITE_SDK_VERSION'] || 2 + export const W3mFrameConstants = { APP_EVENT_KEY: '@w3m-app/', FRAME_EVENT_KEY: '@w3m-frame/', diff --git a/packages/wallet/src/W3mFrameProvider.ts b/packages/wallet/src/W3mFrameProvider.ts index cf495c8737..bd01ad6a36 100644 --- a/packages/wallet/src/W3mFrameProvider.ts +++ b/packages/wallet/src/W3mFrameProvider.ts @@ -33,6 +33,9 @@ export class W3mFrameProvider { this.w3mLogger = new W3mFrameLogger(projectId) this.w3mFrame = new W3mFrame(projectId, true, chainId) this.onTimeout = onTimeout + if (this.getLoginEmailUsed()) { + this.w3mFrame.initFrame() + } } // -- Extended Methods ------------------------------------------------ @@ -47,6 +50,7 @@ export class W3mFrameProvider { public async connectEmail(payload: W3mFrameTypes.Requests['AppConnectEmailRequest']) { try { W3mFrameHelpers.checkIfAllowedToTriggerEmail() + this.w3mFrame.initFrame() const response = await this.appEvent<'ConnectEmail'>({ type: W3mFrameConstants.APP_CONNECT_EMAIL, payload @@ -119,6 +123,8 @@ export class W3mFrameProvider { payload: W3mFrameTypes.Requests['AppGetSocialRedirectUriRequest'] ) { try { + this.w3mFrame.initFrame() + return this.appEvent<'GetSocialRedirectUri'>({ type: W3mFrameConstants.APP_GET_SOCIAL_REDIRECT_URI, payload @@ -283,6 +289,7 @@ export class W3mFrameProvider { public async getFarcasterUri() { try { + this.w3mFrame.initFrame() const response = await this.appEvent<'GetFarcasterUri'>({ type: W3mFrameConstants.APP_GET_FARCASTER_URI } as W3mFrameTypes.AppEvent) diff --git a/packages/wallet/tests/W3mFrameProvider.test.ts b/packages/wallet/tests/W3mFrameProvider.test.ts index 2af53e3c8f..79eca47542 100644 --- a/packages/wallet/tests/W3mFrameProvider.test.ts +++ b/packages/wallet/tests/W3mFrameProvider.test.ts @@ -105,7 +105,11 @@ describe('W3mFrameProvider', () => { it( 'should timeout after 30 seconds', async () => { - const postAppEventSpy = vi.spyOn(provider['w3mFrame'].events, 'postAppEvent') + const postAppEventSpy = vi + .spyOn(provider['w3mFrame'].events, 'postAppEvent') + .mockImplementation(() => { + // Do nothing + }) const mockTimeoutSpy = vi.spyOn(provider, 'onTimeout')