Skip to content

Commit b262fc3

Browse files
committed
feat(clerk-js,clerk-react): Support Base authentication
1 parent d61ea65 commit b262fc3

File tree

16 files changed

+380
-29
lines changed

16 files changed

+380
-29
lines changed

.changeset/silent-insects-cheat.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@clerk/clerk-js': minor
3+
'@clerk/shared': minor
4+
'@clerk/clerk-react': minor
5+
'@clerk/types': minor
6+
---
7+
8+
Added support for authentication with Base

packages/clerk-js/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
},
6464
"browserslist": "last 2 years",
6565
"dependencies": {
66+
"@base-org/account": "2.0.1",
6667
"@clerk/localizations": "workspace:^",
6768
"@clerk/shared": "workspace:^",
6869
"@clerk/types": "workspace:^",

packages/clerk-js/src/core/clerk.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type {
2424
__internal_UserVerificationModalProps,
2525
APIKeysNamespace,
2626
APIKeysProps,
27+
AuthenticateWithBaseParams,
2728
AuthenticateWithCoinbaseWalletParams,
2829
AuthenticateWithGoogleOneTapParams,
2930
AuthenticateWithMetamaskParams,
@@ -42,6 +43,7 @@ import type {
4243
EnvironmentJSON,
4344
EnvironmentJSONSnapshot,
4445
EnvironmentResource,
46+
GenerateSignatureParams,
4547
GoogleOneTapProps,
4648
HandleEmailLinkVerificationParams,
4749
HandleOAuthCallbackParams,
@@ -100,6 +102,7 @@ import {
100102
disabledAPIKeysFeature,
101103
disabledOrganizationsFeature,
102104
errorThrower,
105+
generateSignatureWithBase,
103106
generateSignatureWithCoinbaseWallet,
104107
generateSignatureWithMetamask,
105108
generateSignatureWithOKXWallet,
@@ -2148,6 +2151,13 @@ export class Clerk implements ClerkInterface {
21482151
});
21492152
};
21502153

2154+
public authenticateWithBase = async (props: AuthenticateWithBaseParams = {}): Promise<void> => {
2155+
await this.authenticateWithWeb3({
2156+
...props,
2157+
strategy: 'web3_base_signature',
2158+
});
2159+
};
2160+
21512161
public authenticateWithOKXWallet = async (props: AuthenticateWithOKXWalletParams = {}): Promise<void> => {
21522162
await this.authenticateWithWeb3({
21532163
...props,
@@ -2172,12 +2182,21 @@ export class Clerk implements ClerkInterface {
21722182

21732183
const provider = strategy.replace('web3_', '').replace('_signature', '') as Web3Provider;
21742184
const identifier = await getWeb3Identifier({ provider });
2175-
const generateSignature =
2176-
provider === 'metamask'
2177-
? generateSignatureWithMetamask
2178-
: provider === 'coinbase_wallet'
2179-
? generateSignatureWithCoinbaseWallet
2180-
: generateSignatureWithOKXWallet;
2185+
let generateSignature: (params: GenerateSignatureParams) => Promise<string>;
2186+
switch (provider) {
2187+
case 'metamask':
2188+
generateSignature = generateSignatureWithMetamask;
2189+
break;
2190+
case 'base':
2191+
generateSignature = generateSignatureWithBase;
2192+
break;
2193+
case 'coinbase_wallet':
2194+
generateSignature = generateSignatureWithCoinbaseWallet;
2195+
break;
2196+
default:
2197+
generateSignature = generateSignatureWithOKXWallet;
2198+
break;
2199+
}
21812200

21822201
const makeNavigate = (to: string) => () =>
21832202
customNavigate && typeof customNavigate === 'function' ? customNavigate(to) : this.navigate(to);

packages/clerk-js/src/core/resources/SignIn.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,11 @@ import type {
4444
} from '@clerk/types';
4545

4646
import {
47+
generateSignatureWithBase,
4748
generateSignatureWithCoinbaseWallet,
4849
generateSignatureWithMetamask,
4950
generateSignatureWithOKXWallet,
51+
getBaseIdentifier,
5052
getCoinbaseWalletIdentifier,
5153
getMetamaskIdentifier,
5254
getOKXWalletIdentifier,
@@ -143,11 +145,8 @@ export class SignIn extends BaseResource implements SignInResource {
143145
} as PhoneCodeConfig;
144146
break;
145147
case 'web3_metamask_signature':
146-
config = { web3WalletId: factor.web3WalletId } as Web3SignatureConfig;
147-
break;
148+
case 'web3_base_signature':
148149
case 'web3_coinbase_wallet_signature':
149-
config = { web3WalletId: factor.web3WalletId } as Web3SignatureConfig;
150-
break;
151150
case 'web3_okx_wallet_signature':
152151
config = { web3WalletId: factor.web3WalletId } as Web3SignatureConfig;
153152
break;
@@ -361,6 +360,15 @@ export class SignIn extends BaseResource implements SignInResource {
361360
});
362361
};
363362

363+
public authenticateWithBase = async (): Promise<SignInResource> => {
364+
const identifier = await getBaseIdentifier();
365+
return this.authenticateWithWeb3({
366+
identifier,
367+
generateSignature: generateSignatureWithBase,
368+
strategy: 'web3_base_signature',
369+
});
370+
};
371+
364372
public authenticateWithOKXWallet = async (): Promise<SignInResource> => {
365373
const identifier = await getOKXWalletIdentifier();
366374
return this.authenticateWithWeb3({

packages/clerk-js/src/core/resources/SignUp.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@ import type {
3030
} from '@clerk/types';
3131

3232
import {
33+
generateSignatureWithBase,
3334
generateSignatureWithCoinbaseWallet,
3435
generateSignatureWithMetamask,
3536
generateSignatureWithOKXWallet,
37+
getBaseIdentifier,
3638
getCoinbaseWalletIdentifier,
3739
getMetamaskIdentifier,
3840
getOKXWalletIdentifier,
@@ -276,6 +278,21 @@ export class SignUp extends BaseResource implements SignUpResource {
276278
});
277279
};
278280

281+
public authenticateWithBase = async (
282+
params?: SignUpAuthenticateWithWeb3Params & {
283+
legalAccepted?: boolean;
284+
},
285+
): Promise<SignUpResource> => {
286+
const identifier = await getBaseIdentifier();
287+
return this.authenticateWithWeb3({
288+
identifier,
289+
generateSignature: generateSignatureWithBase,
290+
unsafeMetadata: params?.unsafeMetadata,
291+
strategy: 'web3_base_signature',
292+
legalAccepted: params?.legalAccepted,
293+
});
294+
};
295+
279296
public authenticateWithOKXWallet = async (
280297
params?: SignUpAuthenticateWithWeb3Params & {
281298
legalAccepted?: boolean;

packages/clerk-js/src/utils/web3.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export async function getWeb3Identifier(params: GetWeb3IdentifierParams): Promis
2121
}
2222

2323
const identifiers = await ethereum.request({ method: 'eth_requestAccounts' });
24-
// @ts-ignore
24+
// @ts-ignore -- Provider SDKs may return unknown shape; use first address if present
2525
return (identifiers && identifiers[0]) || '';
2626
}
2727

@@ -58,6 +58,10 @@ export async function getOKXWalletIdentifier(): Promise<string> {
5858
return await getWeb3Identifier({ provider: 'okx_wallet' });
5959
}
6060

61+
export async function getBaseIdentifier(): Promise<string> {
62+
return await getWeb3Identifier({ provider: 'base' });
63+
}
64+
6165
type GenerateSignatureParams = {
6266
identifier: string;
6367
nonce: string;
@@ -75,6 +79,10 @@ export async function generateSignatureWithOKXWallet(params: GenerateSignaturePa
7579
return await generateWeb3Signature({ ...params, provider: 'okx_wallet' });
7680
}
7781

82+
export async function generateSignatureWithBase(params: GenerateSignatureParams): Promise<string> {
83+
return await generateWeb3Signature({ ...params, provider: 'base' });
84+
}
85+
7886
async function getEthereumProvider(provider: Web3Provider) {
7987
if (provider === 'coinbase_wallet') {
8088
if (__BUILD_DISABLE_RHC__) {
@@ -90,7 +98,22 @@ async function getEthereumProvider(provider: Web3Provider) {
9098
});
9199
return sdk.getProvider();
92100
}
101+
if (provider === 'base') {
102+
if (__BUILD_DISABLE_RHC__) {
103+
clerkUnsupportedEnvironmentWarning('Base');
104+
return null;
105+
}
106+
107+
try {
108+
const { createBaseAccountSDK } = await import('@base-org/account');
109+
const sdk = createBaseAccountSDK({
110+
appName: typeof document !== 'undefined' ? document.title || 'Clerk' : 'Clerk',
111+
});
112+
return sdk.getProvider();
113+
} catch {
114+
return null;
115+
}
116+
}
93117

94-
const injectedWeb3Providers = getInjectedWeb3Providers();
95-
return injectedWeb3Providers.get(provider);
118+
return getInjectedWeb3Providers().get(provider);
96119
}

packages/elements/src/internals/machines/sign-in/start.machine.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ export const SignInStartMachine = setup({
3636
if (strategy === 'web3_coinbase_wallet_signature') {
3737
return parent.getSnapshot().context.clerk.client.signIn.authenticateWithCoinbaseWallet();
3838
}
39+
if (strategy === 'web3_base_signature') {
40+
return parent.getSnapshot().context.clerk.client.signIn.authenticateWithWallet();
41+
}
3942
if (strategy === 'web3_okx_wallet_signature') {
4043
return parent.getSnapshot().context.clerk.client.signIn.authenticateWithOKXWallet();
4144
}

packages/elements/src/react/hooks/use-third-party-provider.hook.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ export const useThirdPartyProvider = <
7676
return ref.send({ type: 'AUTHENTICATE.ENTERPRISE_SSO' });
7777
}
7878

79+
if (provider === 'base') {
80+
return ref.send({ type: 'AUTHENTICATE.WEB3', strategy: 'web3_base_signature' });
81+
}
82+
7983
if (provider === 'metamask') {
8084
return ref.send({ type: 'AUTHENTICATE.WEB3', strategy: 'web3_metamask_signature' });
8185
}

packages/elements/src/react/utils/map-scope-to-strategy.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,15 @@ export function mapScopeToStrategy<T extends `provider:${Strategy}`>(scope: T):
1010
if (scope === 'provider:metamask') {
1111
return 'web3_metamask_signature';
1212
}
13+
1314
if (scope === 'provider:coinbase_wallet') {
1415
return 'web3_coinbase_wallet_signature';
1516
}
17+
18+
if (scope === 'provider:base') {
19+
return 'web3_base_signature';
20+
}
21+
1622
if (scope === 'provider:okx_wallet') {
1723
return 'web3_okx_wallet_signature';
1824
}

packages/react/src/isomorphicClerk.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
__internal_UserVerificationProps,
1212
APIKeysNamespace,
1313
APIKeysProps,
14+
AuthenticateWithBaseParams,
1415
AuthenticateWithCoinbaseWalletParams,
1516
AuthenticateWithGoogleOneTapParams,
1617
AuthenticateWithMetamaskParams,
@@ -1353,6 +1354,15 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk {
13531354
}
13541355
};
13551356

1357+
authenticateWithBase = async (params?: AuthenticateWithBaseParams) => {
1358+
const callback = () => this.clerkjs?.authenticateWithBase(params);
1359+
if (this.clerkjs && this.loaded) {
1360+
return callback() as Promise<void>;
1361+
} else {
1362+
this.premountMethodCalls.set('authenticateWithBase', callback);
1363+
}
1364+
};
1365+
13561366
authenticateWithOKXWallet = async (params?: AuthenticateWithOKXWalletParams) => {
13571367
const callback = () => this.clerkjs?.authenticateWithOKXWallet(params);
13581368
if (this.clerkjs && this.loaded) {

0 commit comments

Comments
 (0)