From b57b86f2e2bb337bbe5f6b1f18f38bf4ca73ebfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?txb=C3=AC?= <46839250+0xTxbi@users.noreply.github.com> Date: Wed, 4 Dec 2024 19:46:47 +0100 Subject: [PATCH] feature(unlock-app): remove Coinbase WaaS API handling and improve migration messaging (#15241) --- .../app/api/auth/[...nextauth]/route.ts | 68 ------ unlock-app/app/google-sign-in/page.tsx | 8 - unlock-app/app/providers.tsx | 25 +-- unlock-app/package.json | 2 - .../interface/connect/EnterCode.tsx | 99 --------- .../components/legacy-auth/ConnectToPrivy.tsx | 7 - .../legacy-auth/GoogleSignInContent.tsx | 40 ---- .../legacy-auth/MigrateUserCheckout.tsx | 36 +--- .../legacy-auth/MigrateUserContent.tsx | 34 ++- .../components/legacy-auth/SignInWithCode.tsx | 195 ------------------ .../legacy-auth/SignInWithGoogle.tsx | 152 -------------- unlock-app/src/types/next-auth.d.ts | 14 -- yarn.lock | 167 +-------------- 13 files changed, 36 insertions(+), 811 deletions(-) delete mode 100644 unlock-app/app/api/auth/[...nextauth]/route.ts delete mode 100644 unlock-app/app/google-sign-in/page.tsx delete mode 100644 unlock-app/src/components/interface/connect/EnterCode.tsx delete mode 100644 unlock-app/src/components/legacy-auth/GoogleSignInContent.tsx delete mode 100644 unlock-app/src/components/legacy-auth/SignInWithCode.tsx delete mode 100644 unlock-app/src/components/legacy-auth/SignInWithGoogle.tsx delete mode 100644 unlock-app/src/types/next-auth.d.ts diff --git a/unlock-app/app/api/auth/[...nextauth]/route.ts b/unlock-app/app/api/auth/[...nextauth]/route.ts deleted file mode 100644 index 65ec13e4bba..00000000000 --- a/unlock-app/app/api/auth/[...nextauth]/route.ts +++ /dev/null @@ -1,68 +0,0 @@ -import GoogleProvider from 'next-auth/providers/google' -import CredentialsProvider from 'next-auth/providers/credentials' -import NextAuth, { NextAuthOptions } from 'next-auth' -import { config } from '../../../../src/config/app' -import { locksmith } from '../../../../src/config/locksmith' - -// Create auth options -const authOptions: NextAuthOptions = { - secret: config.nexthAuthSecret as string, - pages: { - error: '/auth-error', - signIn: '/google-sign-in', - }, - providers: [ - GoogleProvider({ - clientId: config.googleClientId as string, - clientSecret: config.googleClientSecret as string, - }), - CredentialsProvider({ - name: 'EmailCode', - credentials: { - email: { label: 'Email', type: 'email' }, - code: { label: 'Code', type: 'text' }, - }, - async authorize(credentials) { - if (!credentials || !credentials.email || !credentials.code) return null - - const res = await locksmith.verifyEmailCode(credentials.email, { - code: credentials.code, - }) - - if (res.status == 200) { - return { id: res.data.token as string, email: credentials.email } - } - return null - }, - }), - ], - callbacks: { - async signIn({ user, account }: { user: any; account: any }) { - user.selectedProvider = account.provider - user.idToken = account.id_token - return true - }, - async jwt({ token, user }: { token: any; user: any }) { - if (user) { - token.selectedProvider = user.selectedProvider - token.idToken = user.idToken - } - return token - }, - async session({ session, token }: { session: any; token: any; user: any }) { - if (token) { - if (token.selectedProvider === 'google') { - session.user.email = token.email - session.user.token = token.idToken - } else { - session.user.token = token.sub - } - } - return session - }, - }, -} - -// Create and export handler -const handler = NextAuth(authOptions) -export { handler as GET, handler as POST } diff --git a/unlock-app/app/google-sign-in/page.tsx b/unlock-app/app/google-sign-in/page.tsx deleted file mode 100644 index 6898eeec8d8..00000000000 --- a/unlock-app/app/google-sign-in/page.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react' -import { GoogleSignInContent } from '~/components/legacy-auth/GoogleSignInContent' - -const GoogleSignInPage: React.FC = () => { - return -} - -export default GoogleSignInPage diff --git a/unlock-app/app/providers.tsx b/unlock-app/app/providers.tsx index c760d2e4cf3..d0ec4be2b71 100644 --- a/unlock-app/app/providers.tsx +++ b/unlock-app/app/providers.tsx @@ -18,7 +18,6 @@ import { ConnectModalProvider } from '~/hooks/useConnectModal' import Privy from '~/config/PrivyProvider' import LoadingFallback from './Components/LoadingFallback' import AuthenticationContext from '~/contexts/AuthenticationContext' -import { SessionProvider as NextAuthSessionProvider } from 'next-auth/react' function makeQueryClient() { return new QueryClient({ @@ -55,20 +54,18 @@ export default function Providers({ children }: { children: React.ReactNode }) { }> - - - + + } > - } - > - - {children} - - - - + + {children} + + + diff --git a/unlock-app/package.json b/unlock-app/package.json index b034e2f8f74..177e427f77f 100644 --- a/unlock-app/package.json +++ b/unlock-app/package.json @@ -8,7 +8,6 @@ }, "dependencies": { "@airstack/airstack-react": "0.6.4", - "@coinbase/waas-sdk-web": "3.3.3", "@crossmint/client-sdk-react-ui": "1.2.2", "@decent.xyz/box-common": "4.0.3", "@enzoferey/ethers-error-parser": "0.2.3", @@ -45,7 +44,6 @@ "graphql": "16.9.0", "lottie-react": "2.4.0", "next": "14.2.18", - "next-auth": "4.24.10", "node-forge": "1.3.1", "postmate": "1.5.2", "qr-scanner": "1.4.2", diff --git a/unlock-app/src/components/interface/connect/EnterCode.tsx b/unlock-app/src/components/interface/connect/EnterCode.tsx deleted file mode 100644 index c0a387f4cd4..00000000000 --- a/unlock-app/src/components/interface/connect/EnterCode.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { Button, Input } from '@unlock-protocol/ui' -import { signIn as nextAuthSignIn } from 'next-auth/react' -import { useEffect } from 'react' -import { useForm } from 'react-hook-form' -import { ToastHelper } from '~/components/helpers/toast.helper' - -interface UserDetails { - email: string - code: string -} - -export interface EnterCodeProps { - email: string - callbackUrl: string - onReturn?(): void -} - -export const EnterCode = ({ email, callbackUrl, onReturn }: EnterCodeProps) => { - const { - register, - handleSubmit, - setError, - formState: { errors, isSubmitting }, - setValue, - } = useForm() - - useEffect(() => { - if (email) { - setValue('email', email) - } - }, [email, setValue]) - - const onSubmit = async (data: UserDetails) => { - if (!data.email) return - try { - const value = await nextAuthSignIn('credentials', { - callbackUrl: callbackUrl, - email: email, - code: data.code, - redirect: false, - }) - - if (value?.error) { - ToastHelper.error('Invalid code') - } else { - // Call the onReturn callback upon successful verification - if (onReturn) { - await onReturn() - } - } - return - } catch (error) { - if (error instanceof Error) { - setError( - 'code', - { - type: 'value', - message: error.message, - }, - { - shouldFocus: true, - } - ) - } - } - } - - return ( -
-
- An email code has been sent. Check your inbox or spam folder. -
-
- - Continue - - } - /> -
-
- ) -} diff --git a/unlock-app/src/components/legacy-auth/ConnectToPrivy.tsx b/unlock-app/src/components/legacy-auth/ConnectToPrivy.tsx index 8fd5f542e4c..b52806d1e77 100644 --- a/unlock-app/src/components/legacy-auth/ConnectToPrivy.tsx +++ b/unlock-app/src/components/legacy-auth/ConnectToPrivy.tsx @@ -3,7 +3,6 @@ import { useLogin } from '@privy-io/react-auth' import { useEffect, useRef } from 'react' import { LoginModal } from '@privy-io/react-auth' -import { signOut as nextAuthSignOut, useSession } from 'next-auth/react' interface ConnectToPrivyProps { userEmail: string @@ -16,14 +15,8 @@ export default function ConnectToPrivy({ onNext, setPrivyConnected, }: ConnectToPrivyProps) { - const { data: session } = useSession() - const { login } = useLogin({ onComplete: async () => { - // When Privy login is complete, sign out of next-auth session - if (session) { - await nextAuthSignOut({ redirect: false }) - } // Set Privy connection status to true setPrivyConnected(true) // Then proceed to next step diff --git a/unlock-app/src/components/legacy-auth/GoogleSignInContent.tsx b/unlock-app/src/components/legacy-auth/GoogleSignInContent.tsx deleted file mode 100644 index 1d9b4662483..00000000000 --- a/unlock-app/src/components/legacy-auth/GoogleSignInContent.tsx +++ /dev/null @@ -1,40 +0,0 @@ -'use client' - -import { signIn, useSession } from 'next-auth/react' -import { useEffect } from 'react' - -export const GoogleSignInContent = () => { - const { data: session, status } = useSession() - - useEffect(() => { - const handleSignIn = async () => { - if (status === 'loading') return - - if (!session) { - // Sign in without redirect - const result = await signIn('google', { redirect: false }) - - if (result?.error) { - window.close() - } - } else if (session?.user?.token) { - // Notify opener and close popup - window.opener?.postMessage( - 'nextAuthGoogleSignInComplete', - window.location.origin - ) - window.close() - } - } - - void handleSignIn() - }, [session, status]) - - return ( -
-

Authenticating with Google...

-
- ) -} - -export default GoogleSignInContent diff --git a/unlock-app/src/components/legacy-auth/MigrateUserCheckout.tsx b/unlock-app/src/components/legacy-auth/MigrateUserCheckout.tsx index b069ce47105..e54d1b9518c 100644 --- a/unlock-app/src/components/legacy-auth/MigrateUserCheckout.tsx +++ b/unlock-app/src/components/legacy-auth/MigrateUserCheckout.tsx @@ -4,10 +4,7 @@ import { useState, useEffect } from 'react' import { useMutation } from '@tanstack/react-query' import { locksmith } from '~/config/locksmith' import MigrationFeedback from './MigrationFeedback' -import { UserAccountType } from '~/utils/userAccountType' import { SignInWithPassword } from './SignInWithPassword' -import { SignInWithCode } from './SignInWithCode' -import { SignInWithGoogle } from './SignInWithGoogle' import { Placeholder } from '@unlock-protocol/ui' interface MigrateUserCheckoutProps { @@ -20,29 +17,14 @@ export const MigrateUserCheckout = ({ onSignOut, }: MigrateUserCheckoutProps) => { const [walletPk, setWalletPk] = useState(null) - const [userAccountType, setUserAccountType] = useState([]) + const [isUnlockAccount, setIsUnlockAccount] = useState(false) // Mutation to handle the user account type const checkUserAccountType = useMutation({ mutationFn: async (email: string) => { const response = await locksmith.getUserAccountType(email) - // Map the API response to our local enum - const userAccountType = - response.data.userAccountType?.map((type: string) => { - switch (type) { - case 'EMAIL_CODE': - return UserAccountType.EmailCodeAccount - case 'UNLOCK_ACCOUNT': - return UserAccountType.UnlockAccount - case 'GOOGLE_ACCOUNT': - return UserAccountType.GoogleAccount - case 'PASSKEY_ACCOUNT': - return UserAccountType.PasskeyAccount - default: - throw new Error(`Unknown account type: ${type}`) - } - }) || [] - return userAccountType + // Check if user has an Unlock 1.0 account type + return response.data.userAccountType?.includes('UNLOCK_ACCOUNT') || false }, }) @@ -50,8 +32,8 @@ export const MigrateUserCheckout = ({ useEffect(() => { if (userEmail) { checkUserAccountType.mutate(userEmail, { - onSuccess: (types) => { - setUserAccountType(types) + onSuccess: (isUnlock) => { + setIsUnlockAccount(isUnlock) }, }) } @@ -68,15 +50,9 @@ export const MigrateUserCheckout = ({ ) } - if (userAccountType?.includes(UserAccountType.UnlockAccount)) { + if (isUnlockAccount) { return } - if (userAccountType?.includes(UserAccountType.EmailCodeAccount)) { - return - } - if (userAccountType?.includes(UserAccountType.GoogleAccount)) { - return - } return null } diff --git a/unlock-app/src/components/legacy-auth/MigrateUserContent.tsx b/unlock-app/src/components/legacy-auth/MigrateUserContent.tsx index d19eca2adb0..874228d79db 100644 --- a/unlock-app/src/components/legacy-auth/MigrateUserContent.tsx +++ b/unlock-app/src/components/legacy-auth/MigrateUserContent.tsx @@ -9,8 +9,6 @@ import MigrationFeedback from './MigrationFeedback' import ConnectToPrivy from './ConnectToPrivy' import { UserAccountType } from '~/utils/userAccountType' import { SignInWithPassword } from './SignInWithPassword' -import { SignInWithCode } from './SignInWithCode' -import { SignInWithGoogle } from './SignInWithGoogle' import { PromptSignOut } from './PromptSignOut' import { usePrivy } from '@privy-io/react-auth' @@ -107,25 +105,21 @@ export const MigrateUserContent = () => { /> ) } - if (userAccountType?.includes(UserAccountType.EmailCodeAccount)) { + if ( + userAccountType?.includes(UserAccountType.EmailCodeAccount) || + userAccountType?.includes(UserAccountType.GoogleAccount) + ) { return ( - { - setWalletPk(walletPk) - onNext() - }} - /> - ) - } - if (userAccountType?.includes(UserAccountType.GoogleAccount)) { - return ( - { - setWalletPk(walletPk) - onNext() - }} - /> +
+

+ Account Migration Not Available +

+

+ We apologize, but migration is currently only available for + Unlock 1.0 accounts. Migration support for these account types + has now been discontinued. +

+
) } return null diff --git a/unlock-app/src/components/legacy-auth/SignInWithCode.tsx b/unlock-app/src/components/legacy-auth/SignInWithCode.tsx deleted file mode 100644 index a0075a3c79a..00000000000 --- a/unlock-app/src/components/legacy-auth/SignInWithCode.tsx +++ /dev/null @@ -1,195 +0,0 @@ -import { useState } from 'react' -import { locksmith } from '~/config/locksmith' -import { useCaptcha } from '~/hooks/useCaptcha' -import { EnterCode } from '../interface/connect/EnterCode' -import { ToastHelper } from '../helpers/toast.helper' -import { - InitializeWaas, - PrivateKeyFormat, - RawPrivateKey, - Waas, -} from '@coinbase/waas-sdk-web' -import { config } from '~/config/app' -import { getUserWaasUuid } from '~/utils/getUserWaasUuid' -import { UserAccountType } from '~/utils/userAccountType' -import { Button } from '@unlock-protocol/ui' -import { getSession } from 'next-auth/react' -import ReCAPTCHA from 'react-google-recaptcha' - -// Singleton instance for WAAS -let waasInstance: Waas | null = null - -/** - * Initialize and return the WAAS instance. - * Ensures that WAAS is initialized only once (Singleton Pattern). - */ -const getWaasInstance = async (): Promise => { - if (waasInstance) { - return waasInstance - } - - waasInstance = await InitializeWaas({ - collectAndReportMetrics: true, - enableHostedBackups: true, - prod: config.env === 'prod', - projectId: config.coinbaseProjectId, - }) - - return waasInstance -} - -/** - * Retrieves the private key from WAAS. - * @param captcha - The CAPTCHA value. - * @param accountType - The type of user account. - * @returns The private key string or null if not found. - */ -export const getPrivateKeyFromWaas = async ( - captcha: string, - accountType: UserAccountType -): Promise => { - try { - const waas = await getWaasInstance() - - const user = await waas.auth.login({ - provideAuthToken: async () => { - const nextAuthSession = await getSession() - if ( - !nextAuthSession || - !nextAuthSession.user || - !nextAuthSession.user.email || - !nextAuthSession.user.token - ) { - throw new Error('Invalid session data') - } - - const waasToken = await getUserWaasUuid( - captcha, - nextAuthSession.user.email, - accountType, - nextAuthSession.user.token - ) - - if (!waasToken) { - throw new Error('Failed to retrieve WAAS token') - } - - return waasToken - }, - }) - - let wallet: any = null - - if (waas.wallets.wallet) { - // Resuming wallet - wallet = waas.wallets.wallet - } else if (user.hasWallet) { - // Restoring wallet - wallet = await waas.wallets.restoreFromHostedBackup() - } else { - // Creating wallet - wallet = await waas.wallets.create() - } - - if (!wallet) { - console.error('No wallet linked to that user. It cannot be migrated.') - return null - } - - const exportedKeys = await wallet.exportKeysFromHostedBackup( - undefined, - PrivateKeyFormat.RAW - ) - - // Use the first key's private key (ecKeyPrivate) - if (exportedKeys.length > 0) { - const firstKey = exportedKeys[0] as RawPrivateKey - return firstKey.ecKeyPrivate - } else { - console.error( - 'No private keys found in wallet, so it cannot be migrated.' - ) - return null - } - } catch (error) { - console.error('Error in getPrivateKeyFromWaas:', error) - return null - } -} - -export const SignInWithCode = ({ - email, - onNext, -}: { - email: string - onNext: (pkey: string) => void -}) => { - const [codeSent, setCodeSent] = useState(false) - const { getCaptchaValue, recaptchaRef } = useCaptcha() - - const sendEmailCode = async () => { - try { - const captcha = await getCaptchaValue() - if (!captcha) { - ToastHelper.error('CAPTCHA verification failed') - return - } - await locksmith.sendVerificationCode(captcha, email) - ToastHelper.success('Email code sent!') - setCodeSent(true) - } catch (error) { - console.error('Error sending email code:', error) - ToastHelper.error('Error sending email code, try again later') - } - } - - const onCodeCorrect = async () => { - try { - const captcha = await getCaptchaValue() - if (!captcha) { - ToastHelper.error('CAPTCHA verification failed') - return - } - const privateKey = await getPrivateKeyFromWaas( - captcha, - UserAccountType.EmailCodeAccount - ) - if (privateKey) { - onNext(privateKey) - } else { - ToastHelper.error('Error getting private key from WAAS') - } - } catch (error) { - console.error('Error in onCodeCorrect:', error) - ToastHelper.error('Error processing the code') - } - } - - return ( - <> - - {!codeSent && ( -
-

- Please, verify that you own this email address by entering the code - you will receive by email. -

- -
- )} - {codeSent && ( - - )} - - ) -} diff --git a/unlock-app/src/components/legacy-auth/SignInWithGoogle.tsx b/unlock-app/src/components/legacy-auth/SignInWithGoogle.tsx deleted file mode 100644 index a268d5f3f87..00000000000 --- a/unlock-app/src/components/legacy-auth/SignInWithGoogle.tsx +++ /dev/null @@ -1,152 +0,0 @@ -import SvgComponents from '../interface/svg' -import { popupCenter } from '~/utils/popup' -import { ConnectButton } from '../interface/connect/Custom' -import { getSession } from 'next-auth/react' -import { ToastHelper } from '../helpers/toast.helper' -import { useCaptcha } from '~/hooks/useCaptcha' -import { UserAccountType } from '~/utils/userAccountType' -import { getPrivateKeyFromWaas } from './SignInWithCode' -import ReCAPTCHA from 'react-google-recaptcha' -import { config } from '~/config/app' -import { useState, useEffect, useRef } from 'react' - -export interface SignInWithGoogleProps { - onNext: (privateKey: string) => void -} - -export const SignInWithGoogle = ({ onNext }: SignInWithGoogleProps) => { - const { getCaptchaValue, recaptchaRef } = useCaptcha() - const [isAuthenticating, setIsAuthenticating] = useState(false) - const cleanupRef = useRef<() => void>(() => {}) - - useEffect(() => { - // Cleanup on unmount - return () => { - cleanupRef.current() - } - }, []) - - const handleSignWithGoogle = async () => { - if (isAuthenticating) return - setIsAuthenticating(true) - - let sessionCheckInterval: NodeJS.Timeout | null = null - let popupWindow: Window | null = null - - // Cleanup function - const cleanup = () => { - if (sessionCheckInterval) { - clearInterval(sessionCheckInterval) - sessionCheckInterval = null - } - if (popupWindow && !popupWindow.closed) { - popupWindow.close() - popupWindow = null - } - window.removeEventListener('message', messageHandler) - } - - cleanupRef.current = cleanup - - // Handle message from the popup - const messageHandler = async (event: MessageEvent) => { - if (event.origin !== window.location.origin) { - return - } - - if (event.data === 'nextAuthGoogleSignInComplete') { - if (sessionCheckInterval) return // Already polling - - sessionCheckInterval = setInterval(async () => { - const session = await getSession() - if (session?.user) { - cleanup() - try { - const captcha = await getCaptchaValue() - if (!captcha) { - throw new Error('CAPTCHA verification failed') - } - const privateKey = await getPrivateKeyFromWaas( - captcha, - UserAccountType.GoogleAccount - ) - if (privateKey) { - onNext(privateKey) - } else { - ToastHelper.error('Error getting private key from WAAS') - } - } catch (error) { - console.error('Error during Google sign in:', error) - ToastHelper.error('Error during Google sign in') - } finally { - setIsAuthenticating(false) - } - } - }, 500) // Check every 500ms - } - } - - window.addEventListener('message', messageHandler) - - try { - popupWindow = popupCenter('/google-sign-in', 'Google Sign In') - if (!popupWindow) { - throw new Error('Failed to open popup') - } - - // Monitor popup closure - const popupCheckInterval = setInterval(() => { - if (popupWindow && popupWindow.closed) { - clearInterval(popupCheckInterval) - setTimeout(() => { - if (isAuthenticating) { - cleanup() - ToastHelper.error('Authentication was cancelled') - setIsAuthenticating(false) - } - }, 1000) - } - }, 1000) - - // Timeout after 2 minutes - const timeout = setTimeout(() => { - if (isAuthenticating) { - cleanup() - ToastHelper.error('Authentication timeout') - setIsAuthenticating(false) - } - }, 120000) - - // Update cleanup to include timeout - cleanupRef.current = () => { - clearInterval(popupCheckInterval) - clearTimeout(timeout) - cleanup() - } - } catch (error) { - console.error('Error initiating Google sign in:', error) - ToastHelper.error('Google sign in was cancelled') - setIsAuthenticating(false) - cleanup() - } - } - - return ( -
- - } - onClick={handleSignWithGoogle} - disabled={isAuthenticating} - > - {isAuthenticating ? 'Authenticating...' : 'Sign in with Google'} - -
- ) -} diff --git a/unlock-app/src/types/next-auth.d.ts b/unlock-app/src/types/next-auth.d.ts deleted file mode 100644 index f2b9e2c437a..00000000000 --- a/unlock-app/src/types/next-auth.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import NextAuth from 'next-auth' - -declare module 'next-auth' { - /** - * Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context - */ - interface Session { - user: { - email: string - selectedProvider: string | null - token: string | null - } - } -} diff --git a/yarn.lock b/yarn.lock index f0ce172602f..f2d7c5d982c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3383,7 +3383,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.24.8, @babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.25.9, @babel/runtime@npm:^7.26.0, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.24.8, @babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.25.9, @babel/runtime@npm:^7.26.0, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": version: 7.26.0 resolution: "@babel/runtime@npm:7.26.0" dependencies: @@ -3492,7 +3492,7 @@ __metadata: languageName: node linkType: hard -"@bugsnag/js@npm:^7.0.0, @bugsnag/js@npm:^7.20.0, @bugsnag/js@npm:^7.22.3": +"@bugsnag/js@npm:^7.0.0, @bugsnag/js@npm:^7.20.0": version: 7.25.0 resolution: "@bugsnag/js@npm:7.25.0" dependencies: @@ -3591,48 +3591,6 @@ __metadata: languageName: node linkType: hard -"@coinbase/cbpay-js@npm:^1.10.0": - version: 1.10.0 - resolution: "@coinbase/cbpay-js@npm:1.10.0" - peerDependencies: - regenerator-runtime: ^0.13.9 - peerDependenciesMeta: - regenerator-runtime: - optional: true - checksum: 10/f011abeac07b5dc9028ed6d766632874135c2182e9bcc6636e5cd026ddcfbe6f8c29432efe36cf2bdaf5df2197a56ccccde6c95b590964a80ef9b741f022b1f4 - languageName: node - linkType: hard - -"@coinbase/corekms@npm:0.1.12": - version: 0.1.12 - resolution: "@coinbase/corekms@npm:0.1.12" - checksum: 10/d8d828141d40a523a4dc693a2c01aba9423ea4b1eefca6bc5461c759cce9ae688cacfea872515639476b0d12a0a865bfcfb2399c40423d51511fa97f3cf7cffe - languageName: node - linkType: hard - -"@coinbase/sandbox-rpc@npm:1.1.6": - version: 1.1.6 - resolution: "@coinbase/sandbox-rpc@npm:1.1.6" - checksum: 10/af8ff89016459260f2b144fecce39258dbeb15ddf79dc96e934ff45fce1daf72c9255fac2fdee87fb88b012f493cbf52000dadd95b20f1790d9b8725e811540c - languageName: node - linkType: hard - -"@coinbase/waas-sdk-web@npm:3.3.3": - version: 3.3.3 - resolution: "@coinbase/waas-sdk-web@npm:3.3.3" - dependencies: - "@bugsnag/js": "npm:^7.22.3" - "@coinbase/cbpay-js": "npm:^1.10.0" - "@coinbase/corekms": "npm:0.1.12" - "@coinbase/sandbox-rpc": "npm:1.1.6" - client-analytics: "npm:0.0.8" - dependenciesMeta: - "@coinbase/cbpay-js": - optional: true - checksum: 10/28a7bef2eb0e0dcf13fd7e46625d2bd689484adc872da929f49cc8ecc7fd95526dfd63f3a18b105657e09fb06249a524064cff4b65d60d45bf5586c631ece07d - languageName: node - linkType: hard - "@coinbase/waas-server-auth@npm:3.1.2": version: 3.1.2 resolution: "@coinbase/waas-server-auth@npm:3.1.2" @@ -11781,13 +11739,6 @@ __metadata: languageName: node linkType: hard -"@panva/hkdf@npm:^1.0.2": - version: 1.2.1 - resolution: "@panva/hkdf@npm:1.2.1" - checksum: 10/a4a9d1812f88f02bc163b365524bbaa5239cc4711e5e7be1bda68dabae1c896cf1cd12520949b0925a6910733d1afcb25ab51fd3cf06f0f69aee988fffebf56e - languageName: node - linkType: hard - "@parcel/watcher-android-arm64@npm:2.5.0": version: 2.5.0 resolution: "@parcel/watcher-android-arm64@npm:2.5.0" @@ -17352,7 +17303,7 @@ __metadata: languageName: node linkType: hard -"@types/react-router@npm:*, @types/react-router@npm:^5.1.0, @types/react-router@npm:^5.1.20": +"@types/react-router@npm:*, @types/react-router@npm:^5.1.0": version: 5.1.20 resolution: "@types/react-router@npm:5.1.20" dependencies: @@ -18468,7 +18419,6 @@ __metadata: resolution: "@unlock-protocol/unlock-app@workspace:unlock-app" dependencies: "@airstack/airstack-react": "npm:0.6.4" - "@coinbase/waas-sdk-web": "npm:3.3.3" "@crossmint/client-sdk-react-ui": "npm:1.2.2" "@decent.xyz/box-common": "npm:4.0.3" "@enzoferey/ethers-error-parser": "npm:0.2.3" @@ -18518,7 +18468,6 @@ __metadata: jsdom: "npm:25.0.1" lottie-react: "npm:2.4.0" next: "npm:14.2.18" - next-auth: "npm:4.24.10" node-forge: "npm:1.3.1" postcss: "npm:8.4.49" postmate: "npm:1.5.2" @@ -23398,17 +23347,6 @@ __metadata: languageName: node linkType: hard -"client-analytics@npm:0.0.8": - version: 0.0.8 - resolution: "client-analytics@npm:0.0.8" - dependencies: - "@types/react-router": "npm:^5.1.20" - md5: "npm:^2.3.0" - perfume.js: "npm:^9.2.0" - checksum: 10/684d56459332dbf079ea6175efd8aed7781b4408db5468e3692f110bde4fe0b59857c2f84a7c60d7faa020b93fc724d78ed860c3b522dd865f28d29275b39623 - languageName: node - linkType: hard - "client-only@npm:0.0.1": version: 0.0.1 resolution: "client-only@npm:0.0.1" @@ -34426,7 +34364,7 @@ __metadata: languageName: node linkType: hard -"jose@npm:^4.10.4, jose@npm:^4.15.5, jose@npm:^4.15.9": +"jose@npm:^4.10.4, jose@npm:^4.15.5": version: 4.15.9 resolution: "jose@npm:4.15.9" checksum: 10/256234b6f85cdc080b1331f2d475bd58c8ccf459cb20f70ac5e4200b271bce10002b1c2f8e5b96dd975d83065ae5a586d52cdf89d28471d56de5d297992f9905 @@ -39000,34 +38938,6 @@ __metadata: languageName: node linkType: hard -"next-auth@npm:4.24.10": - version: 4.24.10 - resolution: "next-auth@npm:4.24.10" - dependencies: - "@babel/runtime": "npm:^7.20.13" - "@panva/hkdf": "npm:^1.0.2" - cookie: "npm:^0.7.0" - jose: "npm:^4.15.5" - oauth: "npm:^0.9.15" - openid-client: "npm:^5.4.0" - preact: "npm:^10.6.3" - preact-render-to-string: "npm:^5.1.19" - uuid: "npm:^8.3.2" - peerDependencies: - "@auth/core": 0.34.2 - next: ^12.2.5 || ^13 || ^14 || ^15 - nodemailer: ^6.6.5 - react: ^17.0.2 || ^18 - react-dom: ^17.0.2 || ^18 - peerDependenciesMeta: - "@auth/core": - optional: true - nodemailer: - optional: true - checksum: 10/59ba0c7dc20caf4f0004aa29bae2c15421988a158421435d640b758ef3b27625d556b83b85d3e2a43e1e05bde90e41d84b516ef908423e1e2dfc4a6998c675cc - languageName: node - linkType: hard - "next-seo@npm:6.6.0": version: 6.6.0 resolution: "next-seo@npm:6.6.0" @@ -39881,13 +39791,6 @@ __metadata: languageName: node linkType: hard -"oauth@npm:^0.9.15": - version: 0.9.15 - resolution: "oauth@npm:0.9.15" - checksum: 10/6b0b10be19a461da417a37ea2821a773ef74dd667563291e1e83b2024b88e6571b0323a0a6887f2390fbaf28cc6ce5bfe0484fc22162b975305b1e19b76f5597 - languageName: node - linkType: hard - "object-assign@npm:^4, object-assign@npm:^4.0.1, object-assign@npm:^4.1.0, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" @@ -39913,13 +39816,6 @@ __metadata: languageName: node linkType: hard -"object-hash@npm:^2.2.0": - version: 2.2.0 - resolution: "object-hash@npm:2.2.0" - checksum: 10/dee06b6271bf5769ae5f1a7386fdd52c1f18aae9fcb0b8d4bb1232f2d743d06cb5b662be42378b60a1c11829f96f3f86834a16bbaa57a085763295fff8b93e27 - languageName: node - linkType: hard - "object-inspect@npm:^1.13.1, object-inspect@npm:^1.13.2, object-inspect@npm:^1.13.3": version: 1.13.3 resolution: "object-inspect@npm:1.13.3" @@ -40094,13 +39990,6 @@ __metadata: languageName: node linkType: hard -"oidc-token-hash@npm:^5.0.3": - version: 5.0.3 - resolution: "oidc-token-hash@npm:5.0.3" - checksum: 10/35fa19aea9ff2c509029ec569d74b778c8a215b92bd5e6e9bc4ebbd7ab035f44304ff02430a6397c3fb7c1d15ebfa467807ca0bcd31d06ba610b47798287d303 - languageName: node - linkType: hard - "omit.js@npm:^2.0.2": version: 2.0.2 resolution: "omit.js@npm:2.0.2" @@ -40248,18 +40137,6 @@ __metadata: languageName: node linkType: hard -"openid-client@npm:^5.4.0": - version: 5.7.0 - resolution: "openid-client@npm:5.7.0" - dependencies: - jose: "npm:^4.15.9" - lru-cache: "npm:^6.0.0" - object-hash: "npm:^2.2.0" - oidc-token-hash: "npm:^5.0.3" - checksum: 10/d30e70082e8ae5222b29977cd944c3aa6ebaa159bf294348b6ae5cbcc8c5db9e731f21815ce41a6ebe2ebf4c6a697e26cad0ea0fc22d59ee922d3f7d3cd4aa43 - languageName: node - linkType: hard - "opentracing@npm:^0.14.4": version: 0.14.7 resolution: "opentracing@npm:0.14.7" @@ -41273,15 +41150,6 @@ __metadata: languageName: node linkType: hard -"perfume.js@npm:^9.2.0": - version: 9.4.0 - resolution: "perfume.js@npm:9.4.0" - dependencies: - web-vitals: "npm:^3.5.0" - checksum: 10/92e80e9a50700e289bdd01a11e867bd960eb0155f976655b096cf9a32a0c33c3b7ae7561f7bb89e0bf400e19820cfe932d354db4e8011ff3f4b250c60dfc1e46 - languageName: node - linkType: hard - "pg-cloudflare@npm:^1.1.1": version: 1.1.1 resolution: "pg-cloudflare@npm:1.1.1" @@ -42338,18 +42206,7 @@ __metadata: languageName: node linkType: hard -"preact-render-to-string@npm:^5.1.19": - version: 5.2.6 - resolution: "preact-render-to-string@npm:5.2.6" - dependencies: - pretty-format: "npm:^3.8.0" - peerDependencies: - preact: ">=10" - checksum: 10/356519f7640d1c49e11b4837b41a83b307f3f237f93de153b9dde833a701e3ce5cf1d45cb18e37a3ec9c568555e2f5373c128d8b5f6ef79de7658f3c400d3e70 - languageName: node - linkType: hard - -"preact@npm:^10.16.0, preact@npm:^10.6.3": +"preact@npm:^10.16.0": version: 10.24.3 resolution: "preact@npm:10.24.3" checksum: 10/e9c4c901a4ddd475a1072355b5c6c944b05797445e0d68f317ad0dbc976b831523573693ea75d2e12e7902042e3729af435377816d25558bf693ecf6b516c707 @@ -42477,13 +42334,6 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^3.8.0": - version: 3.8.0 - resolution: "pretty-format@npm:3.8.0" - checksum: 10/c80009217dea7fc8f6006f644cbefc3ec57833c1f1f325158d83a5bcbc3ccc15d1e2cc658cd7d87b9c196a43f15d6d9125a2415c5ec4357882643534e25e9829 - languageName: node - linkType: hard - "pretty-ms@npm:^2.1.0": version: 2.1.0 resolution: "pretty-ms@npm:2.1.0" @@ -51211,13 +51061,6 @@ __metadata: languageName: node linkType: hard -"web-vitals@npm:^3.5.0": - version: 3.5.2 - resolution: "web-vitals@npm:3.5.2" - checksum: 10/59c5d7775c32977eb9156d186113f4de66c235cfea7a113d2f430ef25db25a5efe1980d2ba466f7ceefc7b1a3847764933dc1567b6d9b8f340d12e75209e3f79 - languageName: node - linkType: hard - "web3-core-helpers@npm:1.10.4, web3-core-helpers@npm:^1.8.0": version: 1.10.4 resolution: "web3-core-helpers@npm:1.10.4"