Skip to content
Merged
2 changes: 2 additions & 0 deletions .changeset/tame-icons-know.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
23 changes: 19 additions & 4 deletions packages/clerk-js/src/core/resources/SignIn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -469,13 +469,28 @@ export class SignIn extends BaseResource implements SignInResource {
});
};

public authenticateWithSolana = async (params: SignInAuthenticateWithSolanaParams): Promise<SignInResource> => {
const identifier = await getSolanaIdentifier(params.walletName);
/**
* Authenticates a user using a Solana Web3 wallet during sign-in.
*
* @param params - Configuration for Solana authentication
* @param params.walletName - The name of the Solana wallet to use for authentication
* @returns A promise that resolves to the updated SignIn resource
* @throws {ClerkRuntimeError} If walletName is not provided or wallet connection fails
*
* @example
* ```typescript
* await signIn.authenticateWithSolana({ walletName: 'phantom' });
* ```
*/
public authenticateWithSolana = async ({
walletName,
}: SignInAuthenticateWithSolanaParams): Promise<SignInResource> => {
const identifier = await getSolanaIdentifier(walletName);
return this.authenticateWithWeb3({
identifier,
generateSignature: p => generateSignatureWithSolana({ ...p, walletName: params.walletName }),
generateSignature: p => generateSignatureWithSolana({ ...p, walletName }),
strategy: 'web3_solana_signature',
walletName: params.walletName,
walletName,
});
};

Expand Down
34 changes: 28 additions & 6 deletions packages/clerk-js/src/core/resources/SignUp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,15 +366,37 @@ export class SignUp extends BaseResource implements SignUpResource {
});
};

public authenticateWithSolana = async (params: SignUpAuthenticateWithSolanaParams): Promise<SignUpResource> => {
const identifier = await getSolanaIdentifier(params.walletName);
/**
* Authenticates a user using a Solana Web3 wallet during sign-up.
*
* @param params - Configuration for Solana authentication
* @param params.walletName - The name of the Solana wallet to use (e.g., 'phantom')
* @param params.unsafeMetadata - Optional unsafe metadata to attach to the user
* @param params.legalAccepted - Optional flag indicating legal terms acceptance
* @returns A promise that resolves to the updated SignUp resource
* @throws {ClerkRuntimeError} If wallet connection fails
*
* @example
* ```typescript
* await signUp.authenticateWithSolana({
* walletName: 'phantom',
* legalAccepted: true
* });
* ```
*/
public authenticateWithSolana = async ({
walletName,
unsafeMetadata,
legalAccepted,
}: SignUpAuthenticateWithSolanaParams): Promise<SignUpResource> => {
const identifier = await getSolanaIdentifier(walletName);
return this.authenticateWithWeb3({
identifier,
generateSignature: p => generateSignatureWithSolana({ ...p, walletName: params.walletName }),
unsafeMetadata: params?.unsafeMetadata,
generateSignature: p => generateSignatureWithSolana({ ...p, walletName }),
unsafeMetadata,
strategy: 'web3_solana_signature',
legalAccepted: params?.legalAccepted,
walletName: params.walletName,
legalAccepted,
walletName,
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Header } from '@/ui/elements/Header';
import { web3CallbackErrorHandler } from '@/ui/utils/web3CallbackErrorHandler';

const Web3SolanaWalletButtons = lazy(() =>
import(/* webpackChunkName: "web3-wallet-buttons" */ '@/ui/elements/Web3SolanaWalletButtons').then(m => ({
import(/* webpackChunkName: "web3-solana-wallet-buttons" */ '@/ui/elements/Web3SolanaWalletButtons').then(m => ({
default: m.Web3SolanaWalletButtons,
})),
);
Expand Down Expand Up @@ -67,7 +67,7 @@ const SignInFactorOneSolanaWalletsCardInner = () => {
customNavigate: router.navigate,
redirectUrl: ctx.afterSignInUrl || '/',
secondFactorUrl: 'factor-two',
signUpContinueUrl: ctx.isCombinedFlow ? '../create/continue' : ctx.signUpContinueUrl,
signUpContinueUrl: ctx.isCombinedFlow ? 'create/continue' : ctx.signUpContinueUrl,
strategy: 'web3_solana_signature',
walletName,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Header } from '@/ui/elements/Header';
import { web3CallbackErrorHandler } from '@/ui/utils/web3CallbackErrorHandler';

const Web3SolanaWalletButtons = lazy(() =>
import(/* webpackChunkName: "web3-wallet-buttons" */ '@/ui/elements/Web3SolanaWalletButtons').then(m => ({
import(/* webpackChunkName: "web3-solana-wallet-buttons" */ '@/ui/elements/Web3SolanaWalletButtons').then(m => ({
default: m.Web3SolanaWalletButtons,
})),
);
Expand Down Expand Up @@ -66,7 +66,7 @@ const SignUpStartSolanaWalletsCardInner = () => {
.authenticateWithWeb3({
customNavigate: router.navigate,
redirectUrl: ctx.afterSignUpUrl || '/',
signUpContinueUrl: '../continue',
signUpContinueUrl: 'continue',
strategy: 'web3_solana_signature',
unsafeMetadata: ctx.unsafeMetadata,
walletName,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ClerkRuntimeError } from '@clerk/shared/error';
import type { Web3Strategy } from '@clerk/shared/types';
import { lazy, Suspense } from 'react';

Expand All @@ -6,11 +7,12 @@ import { useCardState } from '@/ui/elements/contexts';
import { Form } from '@/ui/elements/Form';
import { FormButtonContainer } from '@/ui/elements/FormButtons';
import { FormContainer } from '@/ui/elements/FormContainer';
import { handleError } from '@/ui/utils/errorHandler';

import { Button, descriptors, Flex, localizationKeys, Spinner } from '../../customizables';

const Web3SolanaWalletButtons = lazy(() =>
import(/* webpackChunkName: "web3-wallet-buttons" */ '@/ui/elements/Web3SolanaWalletButtons').then(m => ({
import(/* webpackChunkName: "web3-solana-wallet-buttons" */ '@/ui/elements/Web3SolanaWalletButtons').then(m => ({
default: m.Web3SolanaWalletButtons,
})),
);
Expand All @@ -30,9 +32,15 @@ export const Web3SelectSolanaWalletScreen = ({ onConnect }: Web3SelectWalletProp
card.setIdle();
} catch (err) {
card.setIdle();
console.error(err);
} finally {
close();
if (err instanceof Error) {
handleError(err, [], card.setError);
} else {
const error = new ClerkRuntimeError('An error occurred while generating the Solana signature.', {
code: 'web3_solana_signature_generation_failed',
cause: err instanceof Error ? err : undefined,
});
handleError(error, [], card.setError);
}
}
};

Expand Down Expand Up @@ -65,6 +73,7 @@ export const Web3SelectSolanaWalletScreen = ({ onConnect }: Web3SelectWalletProp
</Suspense>
<FormButtonContainer>
<Button
type='button'
variant='ghost'
onClick={() => {
close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ const WalletButtonIcon = forwardRef((props: WalletButtonProps, ref: Ref<HTMLButt
return (
<Button
ref={ref}
aria-label={label}
textVariant='buttonLarge'
variant='outline'
colorScheme='neutral'
Expand Down
5 changes: 5 additions & 0 deletions packages/clerk-js/src/utils/injectedWeb3SolanaProviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ import type { Wallet } from '@wallet-standard/core';

class InjectedWeb3SolanaProviders {
#wallets: readonly Wallet[] | undefined = undefined;
#initialized: boolean = false;
static #instance: InjectedWeb3SolanaProviders | null = null;

private constructor() {}

async #initialize() {
if (this.#initialized) {
return;
}
this.#initialized = true;
const wallets = await import('@wallet-standard/core').then(mod => mod.getWallets());
this.#wallets = wallets.get();

Expand Down
Loading