diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index 4b0ca388918..3ee14bd9cc7 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -19,6 +19,7 @@ import type { ActiveSessionResource, AuthenticateWithGoogleOneTapParams, AuthenticateWithMetamaskParams, + AuthenticateWithWeb3Params, Clerk as ClerkInterface, ClerkAPIError, ClerkOptions, @@ -1321,25 +1322,31 @@ export class Clerk implements ClerkInterface { }) as Promise; }; - public authenticateWithMetamask = async ({ + public authenticateWithMetamask = async (props: AuthenticateWithMetamaskParams = {}): Promise => { + await this.authenticateWithWeb3({ ...props, strategy: 'web3_metamask_signature' }); + }; + + public authenticateWithWeb3 = async ({ redirectUrl, signUpContinueUrl, customNavigate, unsafeMetadata, - }: AuthenticateWithMetamaskParams = {}): Promise => { + strategy, + }: AuthenticateWithWeb3Params = {}): Promise => { if (!this.client || !this.environment) { return; } - + const provider = + (strategy === 'web3_metamask_signature' && 'metamask') || (strategy === 'web3_coinbase_signature' && 'coinbase'); const navigate = (to: string) => customNavigate && typeof customNavigate === 'function' ? customNavigate(to) : this.navigate(to); let signInOrSignUp: SignInResource | SignUpResource; try { - signInOrSignUp = await this.client.signIn.authenticateWithMetamask(); + signInOrSignUp = await this.client.signIn.authenticateWeb3Provider(provider); } catch (err) { if (isError(err, ERROR_CODES.FORM_IDENTIFIER_NOT_FOUND)) { - signInOrSignUp = await this.client.signUp.authenticateWithMetamask({ unsafeMetadata }); + signInOrSignUp = await this.client.signUp.authenticateWeb3Provider({ unsafeMetadata, provider }); if ( signUpContinueUrl && diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts index 77562861556..383128b04da 100644 --- a/packages/clerk-js/src/core/resources/SignIn.ts +++ b/packages/clerk-js/src/core/resources/SignIn.ts @@ -31,7 +31,7 @@ import type { Web3SignatureFactor, } from '@clerk/types'; -import { generateSignatureWithMetamask, getMetamaskIdentifier, windowNavigate } from '../../utils'; +import { generateSignatureWithWeb3, getWeb3Identifier, windowNavigate } from '../../utils'; import { ClerkWebAuthnError, convertJSONToPublicKeyRequestOptions, @@ -107,6 +107,9 @@ export class SignIn extends BaseResource implements SignInResource { case 'web3_metamask_signature': config = { web3WalletId: factor.web3WalletId } as Web3SignatureConfig; break; + case 'web3_coinbase_signature': + config = { web3WalletId: factor.web3WalletId } as Web3SignatureConfig; + break; case 'reset_password_phone_code': config = { phoneNumberId: factor.phoneNumberId } as ResetPasswordPhoneCodeFactorConfig; break; @@ -223,16 +226,16 @@ export class SignIn extends BaseResource implements SignInResource { }; public authenticateWithWeb3 = async (params: AuthenticateWithWeb3Params): Promise => { - const { identifier, generateSignature } = params || {}; - if (!(typeof generateSignature === 'function')) { + const { identifier, provider } = params || {}; + const strategy = provider ? `web3_${provider}_signature` : 'web3_metamask_signature'; + + if (!(typeof generateSignatureWithWeb3 === 'function')) { clerkMissingOptionError('generateSignature'); } await this.create({ identifier }); - const web3FirstFactor = this.supportedFirstFactors.find( - f => f.strategy === 'web3_metamask_signature', - ) as Web3SignatureFactor; + const web3FirstFactor = this.supportedFirstFactors.find(f => f.strategy === strategy) as Web3SignatureFactor; if (!web3FirstFactor) { clerkVerifyWeb3WalletCalledBeforeCreate('SignIn'); @@ -241,25 +244,35 @@ export class SignIn extends BaseResource implements SignInResource { await this.prepareFirstFactor(web3FirstFactor); const { nonce } = this.firstFactorVerification; - const signature = await generateSignature({ + const signature = await generateSignatureWithWeb3({ identifier: this.identifier!, nonce: nonce!, + provider: provider, }); return this.attemptFirstFactor({ signature, - strategy: 'web3_metamask_signature', + strategy, }); }; - public authenticateWithMetamask = async (): Promise => { - const identifier = await getMetamaskIdentifier(); + public authenticateWeb3Provider = async (provider: 'metamask' | 'coinbase'): Promise => { + const identifier = await getWeb3Identifier(provider); + return this.authenticateWithWeb3({ identifier, - generateSignature: generateSignatureWithMetamask, + provider: provider, }); }; + public authenticateWithMetamask = async (): Promise => { + return this.authenticateWeb3Provider('metamask'); + }; + + public authenticateWithCoinbase = async (): Promise => { + return this.authenticateWeb3Provider('coinbase'); + }; + public authenticateWithPasskey = async (params?: AuthenticateWithPasskeyParams): Promise => { const { flow } = params || {}; diff --git a/packages/clerk-js/src/core/resources/SignUp.ts b/packages/clerk-js/src/core/resources/SignUp.ts index 6b610699b28..7e26d489880 100644 --- a/packages/clerk-js/src/core/resources/SignUp.ts +++ b/packages/clerk-js/src/core/resources/SignUp.ts @@ -10,18 +10,20 @@ import type { PrepareEmailAddressVerificationParams, PreparePhoneNumberVerificationParams, PrepareVerificationParams, - SignUpAuthenticateWithMetamaskParams, + PrepareWeb3WalletVerificationParams, + SignUpAuthenticateWithWeb3Params, SignUpCreateParams, SignUpField, SignUpIdentificationField, SignUpJSON, SignUpResource, SignUpStatus, + SignUpUnsafeMetadata, SignUpUpdateParams, StartEmailLinkFlowParams, } from '@clerk/types'; -import { generateSignatureWithMetamask, getMetamaskIdentifier, windowNavigate } from '../../utils'; +import { generateSignatureWithWeb3, getWeb3Identifier, windowNavigate } from '../../utils'; import { getCaptchaToken, retrieveCaptchaInfo } from '../../utils/captcha'; import { createValidatePassword } from '../../utils/passwords/password'; import { normalizeUnsafeMetadata } from '../../utils/resourceParams'; @@ -170,40 +172,52 @@ export class SignUp extends BaseResource implements SignUpResource { return this.attemptVerification({ ...params, strategy: 'phone_code' }); }; - prepareWeb3WalletVerification = (): Promise => { - return this.prepareVerification({ strategy: 'web3_metamask_signature' }); + prepareWeb3WalletVerification = (params?: PrepareWeb3WalletVerificationParams): Promise => { + return this.prepareVerification(params || { strategy: 'web3_metamask_signature' }); }; attemptWeb3WalletVerification = async (params: AttemptWeb3WalletVerificationParams): Promise => { - const { signature } = params; - return this.attemptVerification({ signature, strategy: 'web3_metamask_signature' }); + const { signature, strategy } = params; + return this.attemptVerification({ signature, strategy }); }; public authenticateWithWeb3 = async ( params: AuthenticateWithWeb3Params & { unsafeMetadata?: SignUpUnsafeMetadata }, ): Promise => { - const { generateSignature, identifier, unsafeMetadata } = params || {}; + const { identifier, unsafeMetadata, provider } = params || {}; + const strategy = provider ? `web3_${provider}_signature` : 'web3_metamask_signature'; const web3Wallet = identifier || this.web3wallet!; await this.create({ web3Wallet, unsafeMetadata }); - await this.prepareWeb3WalletVerification(); + await this.prepareWeb3WalletVerification(strategy); const { nonce } = this.verifications.web3Wallet; if (!nonce) { clerkVerifyWeb3WalletCalledBeforeCreate('SignUp'); } - const signature = await generateSignature({ identifier, nonce }); - return this.attemptWeb3WalletVerification({ signature }); + const signature = await generateSignatureWithWeb3({ identifier, nonce, provider }); + + return this.attemptWeb3WalletVerification({ signature, strategy }); }; - public authenticateWithMetamask = async (params?: SignUpAuthenticateWithMetamaskParams): Promise => { - const identifier = await getMetamaskIdentifier(); + public authenticateWeb3Provider = async ( + provider: 'metamask' | 'coinbase', + params?: SignUpAuthenticateWithWeb3Params, + ): Promise => { + const identifier = await getWeb3Identifier(provider); return this.authenticateWithWeb3({ identifier, - generateSignature: generateSignatureWithMetamask, unsafeMetadata: params?.unsafeMetadata, + provider, }); }; + public authenticateWithMetamask = async (params?: SignUpAuthenticateWithWeb3Params): Promise => { + return this.authenticateWeb3Provider('metamask', params); + }; + + public authenticateWithCoinbase = async (params?: SignUpAuthenticateWithWeb3Params): Promise => { + return this.authenticateWeb3Provider('coinbase', params); + }; public authenticateWithRedirect = async ({ redirectUrl, diff --git a/packages/clerk-js/src/ui/common/constants.ts b/packages/clerk-js/src/ui/common/constants.ts index f14f0e8af8f..3f9ff3eb4c9 100644 --- a/packages/clerk-js/src/ui/common/constants.ts +++ b/packages/clerk-js/src/ui/common/constants.ts @@ -92,6 +92,10 @@ export const WEB3_PROVIDERS: Web3Providers = Object.freeze({ id: 'metamask', name: 'MetaMask', }, + coinbase: { + id: 'coinbase', + name: 'Coinbase Wallet' + } }); export function getWeb3ProviderData(name: Web3Provider): Web3ProviderData | undefined | null { diff --git a/packages/clerk-js/src/ui/components/SignIn/SignInSocialButtons.tsx b/packages/clerk-js/src/ui/components/SignIn/SignInSocialButtons.tsx index 2ba1b6aae35..fb9e6c3c9bf 100644 --- a/packages/clerk-js/src/ui/components/SignIn/SignInSocialButtons.tsx +++ b/packages/clerk-js/src/ui/components/SignIn/SignInSocialButtons.tsx @@ -28,12 +28,13 @@ export const SignInSocialButtons = React.memo((props: SocialButtonsProps) => { .authenticateWithRedirect({ strategy, redirectUrl, redirectUrlComplete }) .catch(err => handleError(err, [], card.setError)); }} - web3Callback={() => { + web3Callback={strategy => { return clerk - .authenticateWithMetamask({ + .authenticateWithWeb3({ customNavigate: navigate, redirectUrl: redirectUrlComplete, signUpContinueUrl: ctx.signUpContinueUrl, + strategy, }) .catch(err => handleError(err, [], card.setError)); }} diff --git a/packages/clerk-js/src/ui/components/SignUp/SignUpSocialButtons.tsx b/packages/clerk-js/src/ui/components/SignUp/SignUpSocialButtons.tsx index 4dd84f36039..9a8cb98a839 100644 --- a/packages/clerk-js/src/ui/components/SignUp/SignUpSocialButtons.tsx +++ b/packages/clerk-js/src/ui/components/SignUp/SignUpSocialButtons.tsx @@ -38,13 +38,14 @@ export const SignUpSocialButtons = React.memo((props: SignUpSocialButtonsProps) }) .catch(err => handleError(err, [], card.setError)); }} - web3Callback={() => { + web3Callback={strategy => { return clerk - .authenticateWithMetamask({ + .authenticateWithWeb3({ customNavigate: navigate, redirectUrl: redirectUrlComplete, signUpContinueUrl: 'continue', unsafeMetadata: ctx.unsafeMetadata, + strategy: strategy, }) .catch(err => handleError(err, [], card.setError)); }} diff --git a/packages/clerk-js/src/ui/components/UserProfile/Web3Form.tsx b/packages/clerk-js/src/ui/components/UserProfile/Web3Form.tsx index b2f8509e40d..29b1d4d4102 100644 --- a/packages/clerk-js/src/ui/components/UserProfile/Web3Form.tsx +++ b/packages/clerk-js/src/ui/components/UserProfile/Web3Form.tsx @@ -32,7 +32,7 @@ export const AddWeb3WalletActionMenu = withCardStateProvider(() => { web3Wallet = await web3Wallet.prepareVerification({ strategy: 'web3_metamask_signature' }); const nonce = web3Wallet.verification.nonce as string; const signature = await generateSignatureWithMetamask({ identifier, nonce }); - await web3Wallet.attemptVerification({ signature }); + await web3Wallet.attemptVerification({ signature, strategy }); card.setIdle(); } catch (err) { card.setIdle(); diff --git a/packages/clerk-js/src/utils/web3.ts b/packages/clerk-js/src/utils/web3.ts index 464582497d9..10ab09274d7 100644 --- a/packages/clerk-js/src/utils/web3.ts +++ b/packages/clerk-js/src/utils/web3.ts @@ -1,15 +1,29 @@ import { toHex } from './hex'; -export async function getMetamaskIdentifier(): Promise { +export async function getWeb3Identifier(provider: string): Promise { + const ethereum = + (provider === 'metamask' && getMetamaskProvider()) || (provider === 'coinbase' && getCoinbaseProvider()); + + if (!ethereum) { + return ''; + } + // @ts-ignore - if (!global.ethereum) { - // Do nothing when ethereum doesn't exist. We might revise this in the future - // to offer an Install Metamask prompt to our users. + const identifiers = await ethereum.request({ + method: 'eth_requestAccounts', + }); + + return (identifiers && identifiers[0]) || ''; +} + +export async function getMetamaskIdentifier(): Promise { + const ethereum = getMetamaskProvider(); + if (!ethereum) { return ''; } // @ts-ignore - const identifiers = await global.ethereum.request({ + const identifiers = await ethereum.request({ method: 'eth_requestAccounts', }); @@ -19,21 +33,111 @@ export async function getMetamaskIdentifier(): Promise { export type GenerateSignatureParams = { identifier: string; nonce: string; + provider?: 'metamask' | 'coinbase'; }; export async function generateSignatureWithMetamask({ identifier, nonce }: GenerateSignatureParams): Promise { + const ethereum = getMetamaskProvider(); + if (!ethereum) { + return ''; + } + // @ts-ignore - if (!global.ethereum) { - // Do nothing when ethereum doesn't exist. We might revise this in the future - // to offer an Install Metamask prompt to our users. + const signature: string = await ethereum.request({ + method: 'personal_sign', + params: [`0x${toHex(nonce)}`, identifier], + }); + + return signature; +} +export async function generateSignatureWithWeb3({ + identifier, + nonce, + provider, +}: GenerateSignatureParams): Promise { + const ethereum = + (provider === 'metamask' && getMetamaskProvider()) || (provider === 'coinbase' && getCoinbaseProvider()); + + if (!ethereum) { return ''; } // @ts-ignore - const signature: string = await global.ethereum.request({ + const signature: string = await ethereum.request({ method: 'personal_sign', params: [`0x${toHex(nonce)}`, identifier], }); return signature; } + +export async function getCoinbaseIdentifier(): Promise { + const ethereum = getCoinbaseProvider(); + if (!ethereum) { + return ''; + } + + // @ts-ignore + const identifiers = await ethereum.request({ + method: 'eth_requestAccounts', + }); + + return (identifiers && identifiers[0]) || ''; +} + +export async function generateSignatureWithCoinbase({ identifier, nonce }: GenerateSignatureParams): Promise { + const ethereum = getCoinbaseProvider(); + if (!ethereum) { + return ''; + } + + // @ts-ignore + const signature: string = await ethereum.request({ + method: 'personal_sign', + params: [`0x${toHex(nonce)}`, identifier], + }); + + return signature; +} + +function getMetamaskProvider(): any { + // @ts-ignore + if (!global.ethereum) { + return undefined; + } + + // @ts-ignore + if (global.ethereum.providers) { + // @ts-ignore + return global.ethereum.providers[1]; + } + + // @ts-ignore + if (!global.ethereum.isMetaMask) { + return undefined; + } + + // @ts-ignore + return global.ethereum; +} + +function getCoinbaseProvider(): any { + // @ts-ignore + if (!global.ethereum) { + return undefined; + } + + // @ts-ignore + if (global.ethereum.providers) { + // @ts-ignore + return global.ethereum.providers[0]; + } + + // @ts-ignore + if (!global.ethereum.isCoinbaseWallet) { + return undefined; + } + + // @ts-ignore + return global.ethereum; +} diff --git a/packages/elements/src/internals/machines/sign-in/start.machine.ts b/packages/elements/src/internals/machines/sign-in/start.machine.ts index 0569abecc0b..03ab9ca605f 100644 --- a/packages/elements/src/internals/machines/sign-in/start.machine.ts +++ b/packages/elements/src/internals/machines/sign-in/start.machine.ts @@ -29,6 +29,9 @@ export const SignInStartMachine = setup({ if (strategy === 'web3_metamask_signature') { return parent.getSnapshot().context.clerk.client.signIn.authenticateWithMetamask(); } + if (strategy === 'web3_coinbase_signature') { + return parent.getSnapshot().context.clerk.client.signIn.authenticateWithCoinbase(); + } throw new ClerkElementsRuntimeError(`Unsupported Web3 strategy: ${strategy}`); }, ), diff --git a/packages/elements/src/internals/machines/sign-in/verification.machine.ts b/packages/elements/src/internals/machines/sign-in/verification.machine.ts index 259390fa14b..600f86bc351 100644 --- a/packages/elements/src/internals/machines/sign-in/verification.machine.ts +++ b/packages/elements/src/internals/machines/sign-in/verification.machine.ts @@ -439,6 +439,17 @@ export const SignInFirstFactorMachine = SignInVerificationMachine.provide({ break; } + case 'web3_coinbase_signature': { + const signature = fields.get('signature')?.value as string | undefined; + assertIsDefined(signature, 'Web3 Coinbase signature'); + + attemptParams = { + strategy, + signature, + } satisfies Web3Attempt; + + break; + } default: throw new ClerkElementsRuntimeError(`Invalid strategy: ${strategy}`); } diff --git a/packages/elements/src/internals/machines/sign-up/start.machine.ts b/packages/elements/src/internals/machines/sign-up/start.machine.ts index 27cd3cab926..ee79be96561 100644 --- a/packages/elements/src/internals/machines/sign-up/start.machine.ts +++ b/packages/elements/src/internals/machines/sign-up/start.machine.ts @@ -35,6 +35,9 @@ export const SignUpStartMachine = setup({ if (strategy === 'web3_metamask_signature') { return parent.getSnapshot().context.clerk.client.signUp.authenticateWithMetamask(); } + if (strategy === 'web3_coinbase_signature') { + return parent.getSnapshot().context.clerk.client.signUp.authenticateWithCoinbase(); + } throw new ClerkElementsRuntimeError(`Unsupported Web3 strategy: ${strategy}`); }, ), diff --git a/packages/elements/src/react/common/loading.tsx b/packages/elements/src/react/common/loading.tsx index a0a4d55626a..99847ed62f0 100644 --- a/packages/elements/src/react/common/loading.tsx +++ b/packages/elements/src/react/common/loading.tsx @@ -1,6 +1,6 @@ import { useClerk } from '@clerk/clerk-react'; import { eventComponentMounted } from '@clerk/shared/telemetry'; -import type { OAuthProvider, SamlStrategy } from '@clerk/types'; +import type { OAuthProvider, SamlStrategy, Web3Provider } from '@clerk/types'; import { useSelector } from '@xstate/react'; import * as React from 'react'; @@ -15,7 +15,7 @@ import type { TSignUpStep } from '~/react/sign-up/step'; import { SIGN_UP_STEPS } from '~/react/sign-up/step'; import { isProviderStrategyScope, mapScopeToStrategy } from '~/react/utils/map-scope-to-strategy'; -type Strategy = OAuthProvider | SamlStrategy | 'metamask'; +type Strategy = OAuthProvider | SamlStrategy | Web3Provider; type LoadingScope = 'global' | `step:${T}` | `provider:${Strategy}` | undefined; type LoadingProps = { diff --git a/packages/elements/src/react/hooks/use-third-party-provider.hook.ts b/packages/elements/src/react/hooks/use-third-party-provider.hook.ts index d0f31b41d84..5addd558afe 100644 --- a/packages/elements/src/react/hooks/use-third-party-provider.hook.ts +++ b/packages/elements/src/react/hooks/use-third-party-provider.hook.ts @@ -66,6 +66,9 @@ export const useThirdPartyProvider = < if (provider === 'metamask') { return ref.send({ type: 'AUTHENTICATE.WEB3', strategy: 'web3_metamask_signature' }); } + if (provider === 'coinbase') { + return ref.send({ type: 'AUTHENTICATE.WEB3', strategy: 'web3_coinbase_signature' }); + } return ref.send({ type: 'AUTHENTICATE.OAUTH', strategy: `oauth_${provider}` }); }, diff --git a/packages/elements/src/react/utils/map-scope-to-strategy.ts b/packages/elements/src/react/utils/map-scope-to-strategy.ts index 8bac8fbc43a..5d1b298b18f 100644 --- a/packages/elements/src/react/utils/map-scope-to-strategy.ts +++ b/packages/elements/src/react/utils/map-scope-to-strategy.ts @@ -1,6 +1,6 @@ -import type { OAuthProvider, SamlStrategy, SignInStrategy } from '@clerk/types'; +import type { OAuthProvider, SamlStrategy, SignInStrategy, Web3Provider } from '@clerk/types'; -type Strategy = OAuthProvider | SamlStrategy | 'metamask'; +type Strategy = OAuthProvider | SamlStrategy | Web3Provider; export function isProviderStrategyScope(value: string): value is Strategy { return value.startsWith('provider:'); @@ -10,6 +10,9 @@ export function mapScopeToStrategy(scope: T): if (scope === 'provider:metamask') { return 'web3_metamask_signature'; } + if (scope === 'provider:coinbase') { + return 'web3_coinbase_signature'; + } if (scope === 'provider:saml') { return 'saml'; diff --git a/packages/react/src/isomorphicClerk.ts b/packages/react/src/isomorphicClerk.ts index 09071059c7f..50a89e8306d 100644 --- a/packages/react/src/isomorphicClerk.ts +++ b/packages/react/src/isomorphicClerk.ts @@ -5,6 +5,7 @@ import type { ActiveSessionResource, AuthenticateWithGoogleOneTapParams, AuthenticateWithMetamaskParams, + AuthenticateWithWeb3Params, Clerk, ClientResource, CreateOrganizationParams, @@ -90,6 +91,7 @@ type IsomorphicLoadedClerk = Without< | 'handleGoogleOneTapCallback' | 'handleUnauthenticated' | 'authenticateWithMetamask' + | 'authenticateWithWeb3' | 'authenticateWithGoogleOneTap' | 'createOrganization' | 'getOrganization' @@ -109,6 +111,7 @@ type IsomorphicLoadedClerk = Without< handleUnauthenticated: () => void; // TODO: Align Promise unknown authenticateWithMetamask: (params: AuthenticateWithMetamaskParams) => Promise; + authenticateWithWeb3: (params: AuthenticateWithMetamaskParams) => Promise; authenticateWithGoogleOneTap: ( params: AuthenticateWithGoogleOneTapParams, ) => Promise; @@ -993,7 +996,14 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk { this.premountMethodCalls.set('authenticateWithMetamask', callback); } }; - + authenticateWithWeb3 = async (params: AuthenticateWithWeb3Params): Promise => { + const callback = () => this.clerkjs?.authenticateWithWeb3(params); + if (this.clerkjs && this.#loaded) { + return callback() as Promise; + } else { + this.premountMethodCalls.set('authenticateWithWeb3', callback); + } + }; authenticateWithGoogleOneTap = async ( params: AuthenticateWithGoogleOneTapParams, ): Promise => { diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index b7478735c78..ceb07ac75d1 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -34,6 +34,7 @@ import type { import type { ActiveSessionResource } from './session'; import type { SignInResource } from './signIn'; import type { SignUpResource } from './signUp'; +import type { Web3Strategy } from './strategies'; import type { UserResource } from './user'; import type { Autocomplete, DeepPartial, DeepSnakeToCamel } from './utils'; @@ -478,6 +479,11 @@ export interface Clerk { */ authenticateWithMetamask: (params?: AuthenticateWithMetamaskParams) => Promise; + /** + * Authenticates user using their Web3 Wallet browser extension + */ + authenticateWithWeb3: (params?: AuthenticateWithWeb3Params) => Promise; + /** * Authenticates user using a Google token generated from Google identity services. */ @@ -1117,6 +1123,15 @@ export interface AuthenticateWithMetamaskParams { redirectUrl?: string; signUpContinueUrl?: string; unsafeMetadata?: SignUpUnsafeMetadata; + strategy?: Web3Strategy; +} + +export interface AuthenticateWithWeb3Params { + customNavigate?: (to: string) => Promise; + redirectUrl?: string; + signUpContinueUrl?: string; + unsafeMetadata?: SignUpUnsafeMetadata; + strategy?: Web3Strategy; } export interface AuthenticateWithGoogleOneTapParams { diff --git a/packages/types/src/signIn.ts b/packages/types/src/signIn.ts index ddd6323b396..a1bffa9c046 100644 --- a/packages/types/src/signIn.ts +++ b/packages/types/src/signIn.ts @@ -98,6 +98,8 @@ export interface SignInResource extends ClerkResource { authenticateWithMetamask: () => Promise; + authenticateWithCoinbase: () => Promise; + authenticateWithPasskey: (params?: AuthenticateWithPasskeyParams) => Promise; createEmailLinkFlow: () => CreateEmailLinkFlowReturn; diff --git a/packages/types/src/signUp.ts b/packages/types/src/signUp.ts index 8dc35b83394..49078272017 100644 --- a/packages/types/src/signUp.ts +++ b/packages/types/src/signUp.ts @@ -23,7 +23,11 @@ import type { } from './strategies'; import type { SnakeToCamel } from './utils'; import type { CreateEmailLinkFlowReturn, StartEmailLinkFlowParams, VerificationResource } from './verification'; -import type { AttemptWeb3WalletVerificationParams, AuthenticateWithWeb3Params } from './web3Wallet'; +import type { + AttemptWeb3WalletVerificationParams, + AuthenticateWithWeb3Params, + PrepareWeb3WalletVerificationParams, +} from './web3Wallet'; declare global { /** @@ -72,7 +76,7 @@ export interface SignUpResource extends ClerkResource { attemptPhoneNumberVerification: (params: AttemptPhoneNumberVerificationParams) => Promise; - prepareWeb3WalletVerification: () => Promise; + prepareWeb3WalletVerification: (params?: PrepareWeb3WalletVerificationParams) => Promise; attemptWeb3WalletVerification: (params: AttemptWeb3WalletVerificationParams) => Promise; @@ -88,7 +92,8 @@ export interface SignUpResource extends ClerkResource { params: AuthenticateWithWeb3Params & { unsafeMetadata?: SignUpUnsafeMetadata }, ) => Promise; - authenticateWithMetamask: (params?: SignUpAuthenticateWithMetamaskParams) => Promise; + authenticateWithMetamask: (params?: SignUpAuthenticateWithWeb3Params) => Promise; + authenticateWithCoinbase: (params?: SignUpAuthenticateWithWeb3Params) => Promise; } export type SignUpStatus = 'missing_requirements' | 'complete' | 'abandoned'; @@ -161,7 +166,9 @@ export type SignUpCreateParams = Partial< export type SignUpUpdateParams = SignUpCreateParams; -export type SignUpAuthenticateWithMetamaskParams = { +export type SignUpAuthenticateWithMetamaskParams = SignUpAuthenticateWithWeb3Params; + +export type SignUpAuthenticateWithWeb3Params = { unsafeMetadata?: SignUpUnsafeMetadata; }; diff --git a/packages/types/src/web3.ts b/packages/types/src/web3.ts index 2e9ced36066..de9c71bcb30 100644 --- a/packages/types/src/web3.ts +++ b/packages/types/src/web3.ts @@ -7,8 +7,9 @@ export interface Web3ProviderData { } export type MetamaskWeb3Provider = 'metamask'; +export type CoinbaseWeb3Provider = 'coinbase'; -export type Web3Provider = MetamaskWeb3Provider; +export type Web3Provider = MetamaskWeb3Provider | CoinbaseWeb3Provider; export const WEB3_PROVIDERS: Web3ProviderData[] = [ { @@ -16,6 +17,11 @@ export const WEB3_PROVIDERS: Web3ProviderData[] = [ strategy: 'web3_metamask_signature', name: 'MetaMask', }, + { + provider: 'coinbase', + strategy: 'web3_coinbase_signature', + name: 'Coinbase Wallet', + }, ]; interface getWeb3ProviderDataProps { diff --git a/packages/types/src/web3Wallet.ts b/packages/types/src/web3Wallet.ts index 2087a325644..9297113d26b 100644 --- a/packages/types/src/web3Wallet.ts +++ b/packages/types/src/web3Wallet.ts @@ -8,6 +8,7 @@ export type PrepareWeb3WalletVerificationParams = { export type AttemptWeb3WalletVerificationParams = { signature: string; + strategy?: Web3Strategy; }; export interface Web3WalletResource extends ClerkResource { @@ -26,6 +27,7 @@ export type GenerateSignature = (opts: GenerateSignatureParams) => Promise