-
Notifications
You must be signed in to change notification settings - Fork 419
feat(clerk-js,react,localizations,shared,ui): Add Solana feature support to core 3 #7450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: bca9f40 The changes in this PR will be included in the next version bump. This PR includes changesets to release 19 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds Solana Web3 wallet support across SDKs and UI: new authenticateWithSolana flows, Solana provider discovery and signMessage signing, wallet-selection UI and routes, type and localization additions, dependency updates, and bundling/config adjustments. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as Client UI
participant ClerkJS as Clerk JS
participant WalletUI as Wallet Selection UI
participant Wallet as Solana Wallet
participant Backend as Clerk Backend
User->>UI: Click "Sign in with Solana"
UI->>ClerkJS: web3Callback(strategy: web3_solana_signature)
ClerkJS->>UI: navigate('choose-wallet')
UI->>WalletUI: render wallet options
WalletUI->>Wallet: query installed wallets
Wallet-->>WalletUI: return wallets
WalletUI-->>User: show wallet buttons
User->>WalletUI: select wallet (walletName)
WalletUI->>ClerkJS: authenticateWithSolana({ walletName, redirect... })
ClerkJS->>Wallet: connect / request public key
Wallet-->>ClerkJS: public key (identifier)
ClerkJS->>Wallet: signMessage(nonce)
Wallet->>User: prompt to approve signature
User->>Wallet: approve
Wallet-->>ClerkJS: signature (base64)
ClerkJS->>Backend: authenticateWithWeb3({ identifier, signature, strategy })
Backend-->>ClerkJS: auth token / session
ClerkJS-->>UI: complete sign-in (redirect)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Areas to focus review on:
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
@clerk/agent-toolkit
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/dev-cli
@clerk/expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
a565591 to
647c5d6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (13)
packages/shared/src/internal/clerk-js/injectedWeb3SolanaProviders.ts-54-60 (1)
54-60: Unsafe type cast for fallback provider.The fallback
window.solanais cast toSolanaWalletAdapterWalletafter only checking forconnectandsignMessagemethods. TheSolanaWalletAdapterWalletinterface likely requires additional properties (likeaccounts,chains,features) that the legacywindow.solanaprovider may not have, potentially causing runtime errors ingenerateWeb3Signaturewhen accessingwallet.accountsorwallet.features.Consider either:
- Adding more comprehensive validation before casting
- Returning a different type for the fallback case
- Adding a comment documenting the expected behavior with legacy providers
packages/clerk-js/package.json-65-67 (1)
65-67: Remove@solana/wallet-adapter-reactdependency.
@solana/wallet-adapter-reactis included in dependencies but has no imports or usage anywhere in the codebase. Remove it to reduce bundle size.packages/localizations/src/ro-RO.ts-1344-1347 (1)
1344-1347: Wallet selection screen strings: consider informal voice to match the rest of the locale.packages/localizations/src/ro-RO.ts-763-766 (1)
763-766: Keep tone consistent: consider switching “Selectați” → “Selectează”.
This file generally speaks informally, so the new Solana copy reads inconsistent.packages/localizations/src/ro-RO.ts-860-863 (1)
860-863: Keep tone consistent: consider switching “Selectați” → “Selectează”.packages/localizations/src/ro-RO.ts-973-975 (1)
973-975: New Web3 error strings: OK, but keep tone consistent (“Ați/Încercați” vs informal).packages/localizations/src/de-DE.ts-1402-1407 (1)
1402-1407: Same tone issue here (“Bitte installiere …”): align with formal “Sie”.- 'Keine Solana-Web3-Wallets erkannt. Bitte installiere eine Web3-unterstützte {{ solanaWalletsLink || link("wallet extension") }}.', + 'Keine Solana-Web3-Wallets erkannt. Bitte installieren Sie eine Web3-unterstützte {{ solanaWalletsLink || link("wallet extension") }}.',packages/localizations/src/de-DE.ts-983-986 (1)
983-986: Fix pronoun/tone consistency (Sie vs du) in new de-DE error strings. The surrounding German copy is predominantly formal (“Sie”), but these lines switch to informal (“Du …”).- web3_signature_request_rejected: - 'Du hast die Signaturanfrage abgelehnt. Bitte versuche es erneut, um fortzufahren.', - web3_solana_signature_generation_failed: - 'Beim Erstellen der Signatur ist ein Fehler aufgetreten. Bitte versuche es erneut, um fortzufahren.', + web3_signature_request_rejected: + 'Sie haben die Signaturanfrage abgelehnt. Bitte versuchen Sie es erneut, um fortzufahren.', + web3_solana_signature_generation_failed: + 'Beim Erstellen der Signatur ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut, um fortzufahren.',packages/localizations/src/es-UY.ts-1380-1385 (1)
1380-1385: Localize the user-visible link label ("wallet extension") innoneAvailable.web3SolanaWalletButtons: { connect: 'Conectar con {{walletName}}', continue: 'Continuar con {{walletName}}', noneAvailable: - 'No se detectaron billeteras Web3 de Solana. Instala una {{ solanaWalletsLink || link("wallet extension") }} compatible con Web3.', + 'No se detectaron billeteras Web3 de Solana. Instalá una {{ solanaWalletsLink || link("extensión de billetera") }} compatible con Web3.', },packages/localizations/src/es-UY.ts-968-970 (1)
968-970: Keep voseo consistent in the new error messages (“Intentá”, not “Inténtalo”).
Current strings switch to “tú” imperative, while the rest of es-UY uses voseo.- web3_signature_request_rejected: 'Has rechazado la solicitud de firma. Inténtalo de nuevo para continuar.', + web3_signature_request_rejected: 'Has rechazado la solicitud de firma. Intentá de nuevo para continuar.', web3_solana_signature_generation_failed: - 'Se produjo un error al generar la firma. Inténtalo de nuevo para continuar.', + 'Se produjo un error al generar la firma. Intentá de nuevo para continuar.',packages/localizations/src/be-BY.ts-1376-1381 (1)
1376-1381: Localize the user-visible link label ("wallet extension") innoneAvailable.
link("wallet extension")will render English text in a be-BY UI.web3SolanaWalletButtons: { connect: 'Падключыцца з {{walletName}}', continue: 'Працягнуць з {{walletName}}', noneAvailable: - 'Кашалькі Solana Web3 не выяўлены. Калі ласка, усталюйце {{ solanaWalletsLink || link("wallet extension") }} з падтрымкай Web3.', + 'Кашалькі Solana Web3 не выяўлены. Калі ласка, усталюйце {{ solanaWalletsLink || link("пашырэнне кашалька") }} з падтрымкай Web3.', },packages/localizations/src/bn-IN.ts-1378-1383 (1)
1378-1383: Localize the user-visible link label ("wallet extension") innoneAvailable.web3SolanaWalletButtons: { connect: '{{walletName}} দিয়ে সংযুক্ত করুন', continue: '{{walletName}} দিয়ে চালিয়ে যান', noneAvailable: - 'কোনো Solana Web3 ওয়ালেট শনাক্ত হয়নি। অনুগ্রহ করে Web3 সমর্থিত {{ solanaWalletsLink || link("wallet extension") }} ইনস্টল করুন।', + 'কোনো Solana Web3 ওয়ালেট শনাক্ত হয়নি। অনুগ্রহ করে Web3 সমর্থিত {{ solanaWalletsLink || link("ওয়ালেট এক্সটেনশন") }} ইনস্টল করুন।', },packages/localizations/src/ko-KR.ts-1350-1355 (1)
1350-1355: Localize the user-visible link label ("wallet extension") innoneAvailable.web3SolanaWalletButtons: { connect: '{{walletName}}(으)로 연결', continue: '{{walletName}}(으)로 계속', noneAvailable: - 'Solana Web3 지갑을 찾을 수 없습니다. Web3를 지원하는 {{ solanaWalletsLink || link("wallet extension") }}을(를) 설치해 주세요.', + 'Solana Web3 지갑을 찾을 수 없습니다. Web3를 지원하는 {{ solanaWalletsLink || link("지갑 확장 프로그램") }}을(를) 설치해 주세요.', },
🧹 Nitpick comments (40)
packages/localizations/src/te-IN.ts (1)
1379-1384: Localize the link label insidelink("wallet extension")for te-INRight now the surrounding sentence is Telugu, but the link label defaults to English (“wallet extension”), which will likely surface as English UI in this locale. Suggest translating just the link label while keeping the token structure identical.
web3SolanaWalletButtons: { connect: '{{walletName}} తో కనెక్ట్ అవ్వండి', continue: '{{walletName}} తో కొనసాగించండి', noneAvailable: - 'Solana Web3 వాలెట్లు ఏవీ గుర్తించబడలేదు. Web3 కి మద్దతు ఉన్న {{ solanaWalletsLink || link("wallet extension") }} ను ఇన్స్టాల్ చేయండి.', + 'Solana Web3 వాలెట్లు ఏవీ గుర్తించబడలేదు. Web3 కి మద్దతు ఉన్న {{ solanaWalletsLink || link("వాలెట్ ఎక్స్టెన్షన్") }} ను ఇన్స్టాల్ చేయండి.', },packages/ui/src/utils/web3CallbackErrorHandler.ts (1)
6-8: Preferunknownoveranyfor the error parameter.The
errparameter is typed asany, which violates the coding guidelines. Since the type is uncertain and you're already usingisClerkAPIResponseErroras a type guard, consider refactoring to useunknownfor better type safety.As per coding guidelines, prefer
unknownoveranyfor type safety.Apply this diff:
type Web3CallbackErrorHandler = { - (err: any, setError?: (err: ClerkRuntimeErrorType | ClerkAPIError | string | undefined) => void): void; + (err: unknown, setError?: (err: ClerkRuntimeErrorType | ClerkAPIError | string | undefined) => void): void; };packages/ui/src/common/WalletInitialIcon.tsx (1)
5-11: Consider documenting the expected value format.The
valueprop represents the wallet name/label but lacks documentation about format requirements. Consider adding a JSDoc comment explaining whatvaluerepresents and any format expectations.Apply this diff to improve documentation:
type WalletInitialIconProps = PropsOfComponent<typeof Box> & { + /** + * The wallet name or label to display the initial of + */ value: string; /** * The wallet provider name */ id: string; };packages/shared/src/internal/clerk-js/web3.ts (3)
80-81: Potential issue with large signature byte arrays.Using
String.fromCharCode(...signedMessages[0].signature)with the spread operator may fail for largeUint8Arrayvalues due to stack size limitations. While Solana signatures are typically 64 bytes (well within limits), consider using a more robust approach:- return signedMessages?.[0]?.signature ? btoa(String.fromCharCode(...signedMessages[0].signature)) : ''; + if (!signedMessages?.[0]?.signature) { + return ''; + } + // Convert Uint8Array to base64 without spread operator stack limitations + const bytes = signedMessages[0].signature; + let binary = ''; + for (let i = 0; i < bytes.length; i++) { + binary += String.fromCharCode(bytes[i]); + } + return btoa(binary);Alternatively, if the environment supports it, use
Buffer.from(bytes).toString('base64').
82-87: Brittle error detection based on message string.Checking
err.message.includes('User rejected the request.')is fragile as the exact message may vary across wallet implementations or change in future versions.Consider checking for common error codes or error types if available:
- if (err instanceof Error && err.message.includes('User rejected the request.')) { + // Check for user rejection - wallets may use different error patterns + const isUserRejection = err instanceof Error && ( + err.message.includes('User rejected') || + err.message.includes('user rejected') || + (err as any).code === 4001 // Standard rejection code + ); + if (isUserRejection) {
46-49: Consider adding a feature existence check before accessingStandardConnect.The code assumes
wallet.features[StandardConnect]exists. If a wallet doesn't support this feature,connect()will fail with an unclear error.if (provider === 'solana') { + if (!walletProvider.features?.[StandardConnect]) { + console.warn('Solana wallet does not support StandardConnect feature'); + return ''; + } const identifiers = await walletProvider.features[StandardConnect].connect(); return (identifiers && identifiers.accounts[0].address) || ''; }packages/shared/src/types/web3Wallet.ts (1)
30-35: Add JSDoc for the newwalletNameproperty.As per coding guidelines, public API properties should be documented with JSDoc comments. Consider adding documentation for
walletNameto clarify its purpose and when it's required (e.g., for Solana sign-ins).export interface AuthenticateWithWeb3Params { identifier: string; generateSignature: GenerateSignature; strategy?: Web3Strategy; + /** + * The name of the wallet to use for Solana sign-ins. + * Required when using Solana-based Web3 authentication. + */ walletName?: string; }packages/shared/src/types/signInFuture.ts (1)
243-256: Consider using a discriminated union for compile-time safety.The JSDoc correctly states that
walletNameis "Required whenprovideris set to'solana'", but this constraint isn't enforced at the type level. Using a discriminated union would catch missingwalletNameat compile time for Solana flows.Example approach:
export type SignInFutureWeb3Params = | { strategy: Web3Strategy; provider: Exclude<Web3Provider, 'solana'>; walletName?: string; } | { strategy: Web3Strategy; provider: 'solana'; walletName: string; };That said, the current implementation with runtime validation is acceptable for this feature port.
packages/shared/src/types/signUp.ts (1)
111-111: Add JSDoc for the newauthenticateWithSolanamethod.The new method follows the established pattern for Web3 wallet authentication. Note that unlike other Web3 methods (lines 107-110) which have optional params, this correctly requires params since
walletNameis mandatory for Solana flows.Consider adding JSDoc documentation to maintain consistency with other public API methods.
+ /** + * Authenticates the user with a Solana wallet. + * @param params - The authentication parameters including the required wallet name. + * @returns A promise that resolves to the updated SignUpResource. + */ authenticateWithSolana: (params: SignUpAuthenticateWithSolanaParams) => Promise<SignUpResource>;packages/localizations/src/vi-VN.ts (1)
1374-1379: Localize the link label insidelink("wallet extension").
Right now the CTA label is English; consider Vietnamese (e.g.,link("tiện ích mở rộng ví")) to keep the whole sentence localized.packages/localizations/src/ro-RO.ts (1)
1383-1388: Localizelink("wallet extension")and align formality (“Instalați” vs informal).
E.g., considerlink("extensie de portofel")(and corresponding verb form).packages/localizations/src/es-MX.ts (1)
1381-1386: Localize the link label insidelink("wallet extension").
For es-MX, consider something likelink("extensión de billetera")so the CTA isn’t English.packages/ui/src/components/SignIn/SignInFactorOneSolanaWalletsCard.tsx (1)
12-16: Lazy-load setup looks fine; consider adding an error boundary for render-time failures.
Suspense won’t catch exceptions thrown by wallet/provider initialization; an error boundary would prevent a hard crash and can surfacecard.setError.packages/ui/src/components/SignUp/SignUpStartSolanaWalletsCard.tsx (1)
21-89: Considerctx.afterSignUpUrl ?? '/'instead of||to avoid treating''as missing (if empty-string is meaningful).- redirectUrl: ctx.afterSignUpUrl || '/', + redirectUrl: ctx.afterSignUpUrl ?? '/',packages/ui/src/elements/Web3SolanaWalletButtons.tsx (2)
57-66: Don’t silently swallow unexpected auth callback failures.
Ifweb3AuthCallbackthrows (e.g., a future refactor removes the.catchin callers), consider surfacing something viacard.setError(...)(and/or rethrow) rather than sleeping and returning.const startWeb3AuthFlow = (walletName: string) => async () => { card.setLoading(walletName); try { await web3AuthCallback({ walletName }); - } catch { - await sleep(1000); + } catch (err) { + card.setError(err instanceof Error ? err.message : 'Web3 authentication failed'); + await sleep(1000); } finally { card.setIdle(); } };
195-263:WalletButtonBlockicon handling has a dead branch / mismatched types.
WalletButtonProps.iconis aReactElement, soisValidElement(icon)is almost always true and the!isIconElement && iconbranch is effectively unreachable. Either:
- simplify by removing that branch, or
- widen
icon’s type toReactNode | React.ComponentTypeand handle both intentionally.(Keeping this tight also avoids the
as unknown as React.ComponentTypecast.)packages/localizations/src/nl-NL.ts (1)
1365-1370: Consider localizing the link label (“wallet extension”) for nl-NL.
Everything else (placeholder +link()fallback) looks correct. Based on learnings,undefinedkeys elsewhere are expected.packages/shared/src/types/clerk.ts (1)
2250-2259:walletName?: stringonClerkAuthenticateWithWeb3Paramsis a bit under-typed—consider making it strategy-discriminated.
Ifstrategy: 'web3_solana' | ...(or equivalent) exists, prefer a union wherewalletNameis required only for the Solana variant to prevent runtime “missing walletName” failures.packages/localizations/src/ja-JP.ts (1)
1378-1383: Optional: localize the link label (“wallet extension”) for ja-JP.
ThesolanaWalletsLink || link(...)fallback usage looks correct. Based on learnings,undefinedkeys elsewhere are expected.packages/localizations/src/pt-PT.ts (1)
1365-1370: Optional: localize the link label (“wallet extension”) for pt-PT.
Fallback linking pattern looks correct. Based on learnings,undefinedkeys elsewhere are expected.packages/localizations/src/fi-FI.ts (1)
1368-1373: Consider localizing the link label insidelink("wallet extension").
Right now the clickable label is English inside an otherwise Finnish sentence.web3SolanaWalletButtons: { connect: 'Yhdistä {{walletName}}', continue: 'Jatka {{walletName}}', noneAvailable: - 'Solana Web3 -lompakoita ei havaittu. Asenna Web3-yhteensopiva {{ solanaWalletsLink || link("wallet extension") }}.', + 'Solana Web3 -lompakoita ei havaittu. Asenna Web3-yhteensopiva {{ solanaWalletsLink || link("lompakkolaajennus") }}.', },packages/localizations/src/el-GR.ts (1)
1376-1381: Consider localizing the link label insidelink("wallet extension").
The rest of the sentence is Greek; the linked label is English.web3SolanaWalletButtons: { connect: 'Σύνδεση με {{walletName}}', continue: 'Συνέχεια με {{walletName}}', noneAvailable: - 'Δεν εντοπίστηκαν πορτοφόλια Solana Web3. Εγκαταστήστε ένα {{ solanaWalletsLink || link("wallet extension") }} με υποστήριξη Web3.', + 'Δεν εντοπίστηκαν πορτοφόλια Solana Web3. Εγκαταστήστε ένα {{ solanaWalletsLink || link("επέκταση πορτοφολιού") }} με υποστήριξη Web3.', },packages/localizations/src/fr-FR.ts (1)
1391-1396: Consider localizing the link label insidelink("wallet extension").
The linked label is English in an otherwise French sentence.web3SolanaWalletButtons: { connect: 'Se connecter avec {{walletName}}', continue: 'Continuer avec {{walletName}}', noneAvailable: - 'Aucun portefeuille Solana Web3 détecté. Veuillez installer une {{ solanaWalletsLink || link("wallet extension") }} compatible Web3.', + 'Aucun portefeuille Solana Web3 détecté. Veuillez installer une {{ solanaWalletsLink || link("extension de portefeuille") }} compatible Web3.', },packages/localizations/src/uk-UA.ts (1)
1364-1369: Consider localizing the link label insidelink("wallet extension").
The linked label is English in an otherwise Ukrainian sentence.web3SolanaWalletButtons: { connect: 'Підключитися через {{walletName}}', continue: 'Продовжити через {{walletName}}', noneAvailable: - 'Гаманці Solana Web3 не виявлено. Установіть {{ solanaWalletsLink || link("wallet extension") }} з підтримкою Web3.', + 'Гаманці Solana Web3 не виявлено. Установіть {{ solanaWalletsLink || link("розширення гаманця") }} з підтримкою Web3.', },packages/localizations/src/pt-BR.ts (1)
1385-1390: Consider localizing the fallback link label (“wallet extension”) for pt-BR. It’s user-facing ifsolanaWalletsLinkisn’t provided.- 'Nenhuma carteira Solana Web3 foi detectada. Instale uma {{ solanaWalletsLink || link("wallet extension") }} compatível com Web3.', + 'Nenhuma carteira Solana Web3 foi detectada. Instale uma {{ solanaWalletsLink || link("extensão de carteira") }} compatível com Web3.',packages/localizations/src/ca-ES.ts (1)
1373-1378: Consider localizing the fallback link label (“wallet extension”) for ca-ES.- 'No s\'han detectat carteres Web3 de Solana. Instal·la una {{ solanaWalletsLink || link("wallet extension") }} compatible amb Web3.', + 'No s\'han detectat carteres Web3 de Solana. Instal·la una {{ solanaWalletsLink || link("extensió de cartera") }} compatible amb Web3.',packages/localizations/src/zh-CN.ts (1)
1332-1337: Optional: localize the fallback link label (“wallet extension”) for zh-CN.- '未检测到 Solana Web3 钱包。请安装支持 Web3 的 {{ solanaWalletsLink || link("wallet extension") }}。', + '未检测到 Solana Web3 钱包。请安装支持 Web3 的 {{ solanaWalletsLink || link("钱包扩展") }}。',packages/localizations/src/cs-CZ.ts (1)
1380-1385: Optional: localize fallback link label (“wallet extension”) for cs-CZ.- 'Nebyla zjištěna žádná Solana Web3 peněženka. Nainstalujte si prosím {{ solanaWalletsLink || link("wallet extension") }} s podporou Web3.', + 'Nebyla zjištěna žádná Solana Web3 peněženka. Nainstalujte si prosím {{ solanaWalletsLink || link("rozšíření peněženky") }} s podporou Web3.',packages/clerk-js/src/core/resources/SignIn.ts (3)
368-416: Consider narrowingerrbefore readingerr.code(TS safety), but overall Solana walletName propagation looks solid.
- Requiring
walletNamewhenprovider === 'solana'is a good guardrail.- Passing
{ walletName, provider }intogenerateSignatureand preserving Coinbase retry is consistent.Suggested small hardening (keeps behavior identical):
} catch (err) { + const code = (err as { code?: unknown } | null)?.code; // ... - if (provider === 'coinbase_wallet' && err.code === 4001) { + if (provider === 'coinbase_wallet' && code === 4001) { signature = await generateSignature({ identifier, nonce: message, provider, walletName }); } else { throw err; } }
454-462: Add JSDoc for new public APIauthenticateWithSolana(public surface).
This is a new exported capability and should be documented alongside the other auth helpers.
975-1063: SignInFuture.web3 Solana branch looks correct; drop the unnecessaryas stringcast.
Since you already throw when!params.walletName, you can avoid the assertion:case 'solana': if (!params.walletName) { throw new ClerkRuntimeError('Wallet name is required for Solana authentication.', { code: 'web3_solana_wallet_name_required', }); } identifier = await web3().getSolanaIdentifier(params.walletName); generateSignature = p => - web3().generateSignatureWithSolana({ ...p, walletName: params.walletName as string }); + web3().generateSignatureWithSolana({ ...p, walletName: params.walletName }); break;packages/localizations/src/en-US.ts (1)
1367-1372:web3SolanaWalletButtons.noneAvailableplaceholder/link pattern is correct; consider a small grammar tweak.
“a Web3 supported …” reads a bit off; “a Web3-supported …” would scan better.packages/ui/src/components/UserProfile/Web3Form.tsx (1)
65-73: Avoidcatch (err: any); useunknownand narrow.
This keeps the error-handling path type-safe and matches TS guidelines.- } catch (err: any) { + } catch (err: unknown) { card.setIdle(); const fieldError = getFieldError(err); if (fieldError) { card.setError(fieldError.longMessage); } else { handleError(err, [], card.setError); } }packages/clerk-js/src/core/clerk.ts (1)
2342-2348: Add JSDoc for the new public APIauthenticateWithSolana.
This is a new externally-facing method; please document params (esp.walletName) + redirects. As per coding guidelines.packages/localizations/src/ru-RU.ts (1)
1389-1394: Localize the link label innoneAvailable(currently English: “wallet extension”).
This will show up in Russian UI.web3SolanaWalletButtons: { connect: 'Подключиться через {{walletName}}', continue: 'Продолжить через {{walletName}}', noneAvailable: - 'Кошельки Solana Web3 не обнаружены. Установите {{ solanaWalletsLink || link("wallet extension") }} с поддержкой Web3.', + 'Кошельки Solana Web3 не обнаружены. Установите {{ solanaWalletsLink || link("расширение кошелька") }} с поддержкой Web3.', },Based on learnings,
undefinedlocalization values are expected fallbacks and should remain as-is.packages/localizations/src/he-IL.ts (1)
1343-1348: Consider localizing the link label innoneAvailable(“wallet extension”).web3SolanaWalletButtons: { connect: 'התחבר/י עם {{walletName}}', continue: 'המשך/י עם {{walletName}}', noneAvailable: - 'לא זוהו ארנקי Solana Web3. נא להתקין {{ solanaWalletsLink || link("wallet extension") }} התומך ב‑Web3.', + 'לא זוהו ארנקי Solana Web3. נא להתקין {{ solanaWalletsLink || link("תוסף ארנק") }} התומך ב‑Web3.', },Based on learnings,
undefinedlocalization values are expected fallbacks and should remain as-is.packages/localizations/src/bg-BG.ts (1)
1367-1372: Localize the link label innoneAvailable(currently English: “wallet extension”).web3SolanaWalletButtons: { connect: 'Свързване с {{walletName}}', continue: 'Продължаване с {{walletName}}', noneAvailable: - 'Не са открити Solana Web3 портфейли. Моля, инсталирайте {{ solanaWalletsLink || link("wallet extension") }} с поддръжка на Web3.', + 'Не са открити Solana Web3 портфейли. Моля, инсталирайте {{ solanaWalletsLink || link("разширение за портфейл") }} с поддръжка на Web3.', },Based on learnings,
undefinedlocalization values are expected fallbacks and should remain as-is.packages/clerk-js/src/core/resources/SignUp.ts (2)
260-309: Harden Web3 signature flow: narrowerrand keep retry args consistent
- If
useUnknownInCatchVariablesis enabled,err.code(Line 301) will be unsafe without narrowing.- Coinbase retry (Line 302) currently drops
walletName; harmless today, but better to keep call shapes consistent.@@ - } catch (err) { + } catch (err) { @@ - if (provider === 'coinbase_wallet' && err.code === 4001) { - signature = await generateSignature({ identifier, nonce: message, provider }); + const code = typeof err === 'object' && err !== null && 'code' in err ? (err as any).code : undefined; + if (provider === 'coinbase_wallet' && code === 4001) { + signature = await generateSignature({ identifier, nonce: message, provider, walletName }); } else { throw err; } }
361-371: ValidatewalletNameearly to avoid opaque Solana failures
authenticateWithSolanaassumesparams.walletNameis valid (Line 362). Consider failing fast with a clear error (and keepparamsaccess non-optional since it’s required).@@ public authenticateWithSolana = async (params: SignUpAuthenticateWithSolanaParams): Promise<SignUpResource> => { + if (!params.walletName?.trim()) { + clerkMissingOptionError('walletName'); + } const identifier = await web3().getSolanaIdentifier(params.walletName); return this.authenticateWithWeb3({ @@ - unsafeMetadata: params?.unsafeMetadata, + unsafeMetadata: params.unsafeMetadata, strategy: 'web3_solana_signature', - legalAccepted: params?.legalAccepted, + legalAccepted: params.legalAccepted, walletName: params.walletName, }); };packages/localizations/src/th-TH.ts (1)
753-757: LGTM: placeholders align with the new Solana localization params
{{walletName}}and{{ solanaWalletsLink || link("wallet extension") }}match the expected param names, and the new keys are correctly placed undersignIn,signUp,unstable__errors,web3WalletsSection, andweb3SolanaWalletButtons. (Also noting: existingundefinedkeys in this repo’s localization files are intentional fallbacks, so no concerns there.) Based on learnings, undefined values are expected.
Optional: consider localizing the"wallet extension"fallback label inside thelink(...)call for a fully Thai experience.Also applies to: 848-852, 954-956, 1315-1323, 1358-1364
| get = async (walletName: string): Promise<SolanaWalletAdapterWallet | undefined> => { | ||
| await this.#initialize(); | ||
| const wallet = (this.#wallets || []).find( | ||
| w => w.name === walletName && this.#isSolanaWallet(w) && this.#hasSignMessage(w), | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Repeated initialization causes event listener memory leak.
#initialize() is called on every get() invocation, which re-registers event listeners without cleanup. This will accumulate listeners over time and cause a memory leak.
Consider adding an initialization guard:
+ #initialized = false;
+
async #initialize() {
+ if (this.#initialized) {
+ return;
+ }
+ this.#initialized = true;
const wallets = await import('@wallet-standard/core').then(mod => mod.getWallets());
this.#wallets = wallets.get();
wallets.on('register', () => {
this.#wallets = wallets.get();
});
wallets.on('unregister', () => {
this.#wallets = wallets.get();
});
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In packages/shared/src/internal/clerk-js/injectedWeb3SolanaProviders.ts around
lines 39 to 43, calling this.#initialize() on every get() re-registers event
listeners and leaks memory; change initialization to run only once by adding an
initialized guard (e.g., a private boolean like #initialized) and have
#initialize() set that flag after registering listeners, then early-return if
already initialized; ensure any listener registration remains inside
#initialize() and do not call it from get() more than when the guard is false.
| width: '100%', | ||
| }} | ||
| > | ||
| {value[0].toUpperCase()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add safety check for empty value.
Line 39 accesses value[0] without checking if the string is non-empty. If an empty string is passed, this will result in undefined.toUpperCase(), causing a runtime error.
Apply this diff to add a safety check:
- {value[0].toUpperCase()}
+ {value[0]?.toUpperCase() ?? ''}Or add a runtime check at the component level:
export const WalletInitialIcon = (props: WalletInitialIconProps) => {
const { value, id, ...rest } = props;
+
+ if (!value) {
+ return null;
+ }
return (📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {value[0].toUpperCase()} | |
| {value[0]?.toUpperCase() ?? ''} |
🤖 Prompt for AI Agents
In packages/ui/src/common/WalletInitialIcon.tsx around line 39, the component
directly calls value[0].toUpperCase() which will throw if value is an empty
string or undefined; add a runtime guard to ensure value is a non-empty string
before accessing index 0 (e.g., compute an initial like const initial = value &&
value.length ? value[0].toUpperCase() : fallback and render that), or
validate/normalize the prop earlier so the rendered expression never calls
toUpperCase on undefined/empty.
| return ( | ||
| <Flow.Part part='chooseWallet'> | ||
| <Card.Root> | ||
| <Card.Content> | ||
| <Header.Root showLogo> | ||
| <Header.Title localizationKey={localizationKeys('signIn.web3Solana.title')} /> | ||
| <Header.Subtitle localizationKey={localizationKeys('signIn.web3Solana.subtitle')} /> | ||
| </Header.Root> | ||
| <Card.Alert>{card.error}</Card.Alert> | ||
| <Flex | ||
| direction='col' | ||
| gap={4} | ||
| > | ||
| <Suspense | ||
| fallback={ | ||
| <Flex | ||
| direction={'row'} | ||
| align={'center'} | ||
| justify={'center'} | ||
| sx={t => ({ | ||
| height: '100%', | ||
| minHeight: t.sizes.$32, | ||
| })} | ||
| > | ||
| <Spinner | ||
| size={'lg'} | ||
| colorScheme={'primary'} | ||
| elementDescriptor={descriptors.spinner} | ||
| /> | ||
| </Flex> | ||
| } | ||
| > | ||
| <Web3SolanaWalletButtons | ||
| web3AuthCallback={({ walletName }) => { | ||
| return clerk | ||
| .authenticateWithWeb3({ | ||
| customNavigate: router.navigate, | ||
| redirectUrl: ctx.afterSignInUrl || '/', | ||
| secondFactorUrl: 'factor-two', | ||
| signUpContinueUrl: ctx.isCombinedFlow ? '../create/continue' : ctx.signUpContinueUrl, | ||
| strategy: 'web3_solana_signature', | ||
| walletName, | ||
| }) | ||
| .catch(err => web3CallbackErrorHandler(err, card.setError)); | ||
| }} | ||
| /> | ||
| </Suspense> | ||
|
|
||
| <BackLink | ||
| boxElementDescriptor={descriptors.backRow} | ||
| linkElementDescriptor={descriptors.backLink} | ||
| onClick={onBackLinkClick} | ||
| /> | ||
| </Flex> | ||
| </Card.Content> | ||
| <Card.Footer /> | ||
| </Card.Root> | ||
| </Flow.Part> | ||
| ); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
rg -n --type=ts --type=tsx "authenticateWithWeb3\(" -C4 packages/ui/srcRepository: clerk/javascript
Length of output: 87
🏁 Script executed:
rg -n --type=ts --type=tsx "secondFactorUrl\s*:" -C3 packages/ui/srcRepository: clerk/javascript
Length of output: 87
🏁 Script executed:
rg -n --type=ts --type=tsx "signUpContinueUrl\s*:" -C3 packages/ui/srcRepository: clerk/javascript
Length of output: 87
🏁 Script executed:
rg -n "authenticateWithWeb3\(" -g "*.ts" -g "*.tsx" -C4 packages/ui/src | head -300Repository: clerk/javascript
Length of output: 3976
🏁 Script executed:
rg -n "secondFactorUrl\s*:" -g "*.ts" -g "*.tsx" -C3 packages/ui/srcRepository: clerk/javascript
Length of output: 2254
🏁 Script executed:
rg -n "signUpContinueUrl\s*:" -g "*.ts" -g "*.tsx" -C3 packages/ui/srcRepository: clerk/javascript
Length of output: 3795
🏁 Script executed:
fd -t f "SignInSocialButtons.tsx|SignInFactorOneSolanaWalletsCard.tsx" packages/ui/srcRepository: clerk/javascript
Length of output: 188
🏁 Script executed:
rg -n "router.navigate|navigate\(" -g "*.tsx" packages/ui/src/components/SignIn/SignInFactorOneSolanaWalletsCard.tsx -C2Repository: clerk/javascript
Length of output: 411
🏁 Script executed:
rg -n "create/continue|../create/continue" -g "*.ts" -g "*.tsx" packages/ui/srcRepository: clerk/javascript
Length of output: 397
🏁 Script executed:
rg -n "signUpContinueUrl\s*:" -g "*.tsx" packages/ui/src/components/SignIn -B2 -A2Repository: clerk/javascript
Length of output: 1295
🏁 Script executed:
rg -n "Flow.Part.*SignIn\|Flow.Part.*chooseWallet" -g "*.tsx" packages/ui/src/components/SignInRepository: clerk/javascript
Length of output: 42
Fix inconsistent signUpContinueUrl path in combined-flow condition: use 'create/continue' to match SignInSocialButtons.tsx.
SignInSocialButtons.tsx (same directory) uses 'create/continue' while this component uses '../create/continue' for the combined-flow override. Both components are siblings in the same routing context, so the relative path syntax should match. The extra ../ prefix will navigate to an incorrect step.
secondFactorUrl: 'factor-two' is consistent across both SignIn components and correct.
🤖 Prompt for AI Agents
In packages/ui/src/components/SignIn/SignInFactorOneSolanaWalletsCard.tsx around
lines 31 to 90, the combined-flow override uses a relative path
'../create/continue' which is inconsistent with SignInSocialButtons.tsx and
causes navigation to the wrong step; change the signUpContinueUrl value from
'../create/continue' to 'create/continue' so it matches the sibling component
and stays within the same routing context.
| export const Web3SelectSolanaWalletScreen = ({ onConnect }: Web3SelectWalletProps) => { | ||
| const card = useCardState(); | ||
| const { close } = useActionContext(); | ||
|
|
||
| const onClick = async ({ walletName }: { walletName: string }) => { | ||
| card.setLoading(walletName); | ||
| try { | ||
| await onConnect({ strategy: 'web3_solana_signature', walletName }); | ||
| card.setIdle(); | ||
| } catch (err) { | ||
| card.setIdle(); | ||
| console.error(err); | ||
| } finally { | ||
| close(); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don’t silently close the screen on connect errors; surface a user-visible error (and consider staying open).
Right now failures only console.error(err) and then close() in finally, which can look like a no-op to the user and prevents retry. Prefer card.setError(...) (and only close on success).
const onClick = async ({ walletName }: { walletName: string }) => {
card.setLoading(walletName);
try {
await onConnect({ strategy: 'web3_solana_signature', walletName });
- card.setIdle();
+ card.setIdle();
+ close();
} catch (err) {
card.setIdle();
- console.error(err);
- } finally {
- close();
+ card.setError(err as unknown);
}
};🤖 Prompt for AI Agents
In packages/ui/src/components/UserProfile/Web3SelectSolanaWalletScreen.tsx
around lines 22 to 37, the onClick handler currently logs errors and always
calls close() in finally which hides failures from the user and prevents retry;
change the flow so that on success you call close(), and on error you set a
visible error on the card (e.g., card.setError(message)) and return the screen
open for retry. Concretely: remove close() from the finally block, move close()
to the successful path after card.setIdle(), on catch call card.setIdle() then
card.setError(...) with a user-friendly message (and optionally log the raw
error to console for debugging), and do not close the modal on error so users
can retry.
| <FormButtonContainer> | ||
| <Button | ||
| variant='ghost' | ||
| onClick={() => { | ||
| close(); | ||
| }} | ||
| localizationKey={localizationKeys('userProfile.formButtonReset')} | ||
| elementDescriptor={descriptors.formButtonReset} | ||
| /> | ||
| </FormButtonContainer> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set reset button type="button" to avoid accidental form submit.
If Button renders a native <button> without an explicit type, HTML defaults to submit, which can trigger unintended submit behavior inside Form.Root.
<Button
variant='ghost'
+ type="button"
onClick={() => {
close();
}}
localizationKey={localizationKeys('userProfile.formButtonReset')}
elementDescriptor={descriptors.formButtonReset}
/>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <FormButtonContainer> | |
| <Button | |
| variant='ghost' | |
| onClick={() => { | |
| close(); | |
| }} | |
| localizationKey={localizationKeys('userProfile.formButtonReset')} | |
| elementDescriptor={descriptors.formButtonReset} | |
| /> | |
| </FormButtonContainer> | |
| <FormButtonContainer> | |
| <Button | |
| variant='ghost' | |
| type="button" | |
| onClick={() => { | |
| close(); | |
| }} | |
| localizationKey={localizationKeys('userProfile.formButtonReset')} | |
| elementDescriptor={descriptors.formButtonReset} | |
| /> | |
| </FormButtonContainer> |
🤖 Prompt for AI Agents
In packages/ui/src/components/UserProfile/Web3SelectSolanaWalletScreen.tsx
around lines 66 to 75, the reset Button currently may render a native <button>
without an explicit type so it defaults to submit inside Form.Root; update the
Button invocation to include type="button" (pass the prop through the Button
component) so clicking it does not trigger form submission; ensure the Button
component accepts and forwards the type prop to the underlying element.
| const WalletButtonIcon = forwardRef((props: WalletButtonProps, ref: Ref<HTMLButtonElement> | null): JSX.Element => { | ||
| const { icon, label, id, ...rest } = props; | ||
|
|
||
| return ( | ||
| <Button | ||
| ref={ref} | ||
| textVariant='buttonLarge' | ||
| variant='outline' | ||
| colorScheme='neutral' | ||
| hoverAsFocus | ||
| sx={t => ({ | ||
| minHeight: t.sizes.$8, | ||
| width: '100%', | ||
| })} | ||
| {...rest} | ||
| > | ||
| {icon} | ||
| </Button> | ||
| ); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add an explicit accessible name for icon-only wallet buttons.
Relying on child image alt / initials is brittle; set aria-label on the button so SR users consistently get “Connect with X”.
const WalletButtonIcon = forwardRef((props: WalletButtonProps, ref: Ref<HTMLButtonElement> | null): JSX.Element => {
const { icon, label, id, ...rest } = props;
return (
<Button
ref={ref}
+ aria-label={label}
textVariant='buttonLarge'
variant='outline'
colorScheme='neutral'
hoverAsFocus
sx={t => ({
minHeight: t.sizes.$8,
width: '100%',
})}
{...rest}
>
{icon}
</Button>
);
});Also applies to: 127-160
🤖 Prompt for AI Agents
In packages/ui/src/elements/Web3SolanaWalletButtons.tsx around lines 174 to 193
(and also apply same change to lines 127-160), the WalletButtonIcon component
renders an icon-only button without an explicit accessible name; add an
aria-label to the Button using the provided label (or fallback to id) so screen
readers get a consistent phrase like "Connect with X" — e.g. set
aria-label={`Connect with ${label ?? id}`} on the Button and pass no other
changes.
| export const Web3SolanaWalletButtons = (props: Web3WalletButtonsProps) => { | ||
| const network = MAINNET_ENDPOINT; | ||
| const wallets = useMemo(() => [], [network]); | ||
| return ( | ||
| <ConnectionProvider endpoint={network}> | ||
| <WalletProvider | ||
| wallets={wallets} | ||
| onError={err => { | ||
| console.error(err); | ||
| }} | ||
| > | ||
| <Web3SolanaWalletButtonsInner web3AuthCallback={props.web3AuthCallback} /> | ||
| </WalletProvider> | ||
| </ConnectionProvider> | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
find . -type f -name "package.json" | grep -E "packages/ui|package\.json$" | head -20Repository: clerk/javascript
Length of output: 176
🏁 Script executed:
cat packages/ui/package.json | grep -A 5 -B 5 "wallet-adapter"Repository: clerk/javascript
Length of output: 524
🏁 Script executed:
rg "WalletProvider|useMemo.*\[\].*network" packages/ui/src --type tsx -B 3 -A 3Repository: clerk/javascript
Length of output: 87
🏁 Script executed:
rg "@solana/wallet-adapter" packages/ui/src --type tsxRepository: clerk/javascript
Length of output: 87
🏁 Script executed:
rg "WalletProvider|useMemo.*\[\]" packages/ui/src -B 3 -A 3Repository: clerk/javascript
Length of output: 4915
🏁 Script executed:
cat packages/ui/src/elements/Web3SolanaWalletButtons.tsxRepository: clerk/javascript
Length of output: 8457
🏁 Script executed:
find . -name "pnpm-lock.yaml" -o -name "yarn.lock" -o -name "package-lock.json" | head -1Repository: clerk/javascript
Length of output: 136
🏁 Script executed:
rg "wallet-adapter-react" . --type json | head -20Repository: clerk/javascript
Length of output: 336
🏁 Script executed:
head -100 pnpm-lock.yaml | grep -A 10 "wallet-adapter-react"Repository: clerk/javascript
Length of output: 337
🏁 Script executed:
rg "wallet-adapter|Wallet.*Adapter" packages/ui/src --no-heading | grep -i import | head -20Repository: clerk/javascript
Length of output: 323
🏁 Script executed:
rg "Web3SolanaWalletButtons" . --no-heading | grep -v "node_modules" | head -20Repository: clerk/javascript
Length of output: 2055
🏁 Script executed:
rg "WalletProvider" . --no-heading -B 5 -A 5 | grep -v "node_modules" | head -40Repository: clerk/javascript
Length of output: 2194
WalletProvider receives an empty wallets array, causing the component to always display the "none available" message.
The useWallet() hook in Web3SolanaWalletButtonsInner relies on wallets passed to WalletProvider. With wallets={useMemo(() => [], [network])}, the hook will always return an empty list, triggering the fallback UI regardless of which wallets are installed on the user's system. No wallet adapter instances are provided or imported anywhere in the file.
To fix: instantiate and pass wallet adapters (e.g., PhantomWalletAdapter) to the wallets prop, or provide a wallet-standard adapter that discovers installed wallets. Ensure adapters are tree-shaking friendly by importing them from a central module.
🤖 Prompt for AI Agents
In packages/ui/src/elements/Web3SolanaWalletButtons.tsx around lines 265 to 279,
the WalletProvider is given an empty wallets array so useWallet() in the inner
component always finds no adapters; replace the useMemo(() => [], [network])
with a useMemo that instantiates and returns the appropriate wallet adapter
instances (e.g., PhantomWalletAdapter and any others you support) configured for
the network, and import those adapter constructors from the central adapters
module so they are tree-shakable; pass that memoized array to WalletProvider and
keep onError as-is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
packages/shared/src/types/signInFuture.ts (1)
243-256: All 16.web3()call sites in tests are missing the requiredproviderparameter and will fail TypeScript compilation.The
SignInFutureWeb3Paramsinterface requiresprovider: Web3Provideras a mandatory field, but the implementation derives the provider from thestrategyparameter and never uses the passed-inprovider. All test call sites only passstrategy(e.g.,.web3({ strategy: 'web3_metamask_signature' })), which violates the type signature. Withstrict: trueenabled in tsconfig, these tests will fail to compile.Either
providershould be removed from the required parameters and derived entirely fromstrategy, or marked as optional with a default value. The current type definition does not match the implementation's contract.packages/shared/src/types/clerk.ts (1)
2251-2259: Add JSDoc to clarify thatwalletNameis required for Solana, or use a discriminated union to enforce at the type level.Currently,
ClerkAuthenticateWithWeb3Paramsallows callers to passstrategy: 'web3_solana_signature'without providingwalletName, yet the runtime code throws an error in this case. Either document this constraint clearly in JSDoc, or better yet, use a discriminated union keyed bystrategyto enforcewalletNameas required whenstrategyis Solana (matching the pattern used inSignUpAuthenticateWithSolanaParamsandSignInAuthenticateWithSolanaParams, wherewalletNameis already required).packages/clerk-js/src/core/resources/SignUp.ts (3)
260-309: Add walletName validation for Solana strategy.The
authenticateWithWeb3method is missing validation to ensurewalletNameis provided when the strategy is'web3_solana_signature'. This validation exists inSignIn.ts(lines 376-378) but is absent here, creating inconsistency and allowing late-stage failures.Add the validation after Line 278:
if (!(typeof generateSignature === 'function')) { clerkMissingOptionError('generateSignature'); } + + if (provider === 'solana' && !walletName) { + clerkMissingOptionError('walletName'); + } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const web3Wallet = identifier || this.web3wallet!;
311-359: Address signature inconsistency across wallet authentication methods.Lines 327, 339, and 350 update
authenticateWithCoinbaseWallet,authenticateWithBase, andauthenticateWithOKXWalletto acceptSignUpAuthenticateWithWeb3Params, butauthenticateWithMetamask(lines 311-324) retains an inline type with explicitlegalAcceptedfield. This creates an inconsistency in the public API.Normalize
authenticateWithMetamaskto match the other methods:- public authenticateWithMetamask = async ( - params?: SignUpAuthenticateWithWeb3Params & { - legalAccepted?: boolean; - }, - ): Promise<SignUpResource> => { + public authenticateWithMetamask = async (params?: SignUpAuthenticateWithWeb3Params): Promise<SignUpResource> => {
874-938: Critical: Missing Solana case in SignUpFuture.web3.The
SignUpFuture.web3method lacks a'solana'case in the provider switch statement (lines 881-900), causing any Solana authentication attempt via the Future API to throw "Unsupported Web3 provider: solana". This is inconsistent withSignInFuture.web3inSignIn.ts(lines 999-1008), which correctly implements Solana support.Add the Solana case after the
okx_walletcase:case 'okx_wallet': identifier = await web3().getOKXWalletIdentifier(); generateSignature = web3().generateSignatureWithOKXWallet; break; + case 'solana': + if (!params.walletName) { + throw new ClerkRuntimeError('Wallet name is required for Solana authentication.', { + code: 'web3_solana_wallet_name_required', + }); + } + identifier = await web3().getSolanaIdentifier(params.walletName); + generateSignature = p => + web3().generateSignatureWithSolana({ ...p, walletName: params.walletName as string }); + break; default: throw new Error(`Unsupported Web3 provider: ${provider}`);Additionally, update the retry logic to preserve
walletNameif present:} catch (err) { // ... comment ... if (provider === 'coinbase_wallet' && err.code === 4001) { - signature = await generateSignature({ identifier, nonce: message }); + signature = await generateSignature({ identifier, nonce: message, walletName: params?.walletName }); } else { throw err; }
♻️ Duplicate comments (6)
.changeset/legal-jokes-beg.md (1)
1-9: Past review comment still applies.The incorrect package names (@clerk/clerk-react and @clerk/elements) have already been flagged in a previous review. Please update to @clerk/react and @clerk/ui respectively.
packages/ui/src/components/UserProfile/Web3SelectSolanaWalletScreen.tsx (2)
26-37: Past review comment still applies: Error handling needs improvement.The
close()call in thefinallyblock (line 35) means the screen closes on both success and error, hiding failures from the user and preventing retry. This issue was already flagged in a previous review.
66-75: Past review comment still applies: Button needs explicit type.The reset Button should include
type="button"to prevent accidental form submission when insideForm.Root. This issue was already flagged in a previous review.packages/ui/src/elements/Web3SolanaWalletButtons.tsx (2)
174-193: Icon-only wallet buttons need an explicit accessible name (aria-label).
265-279:WalletProviderwithwallets=[]makes “no wallets available” the only possible outcome.You’ll need to pass actual adapter instances (or a wallet-standard discovery adapter) instead of an empty array, and confirm the correct adapter packages/versions for this repo.
packages/shared/src/internal/clerk-js/injectedWeb3SolanaProviders.ts (1)
39-43: Memory leak from repeated initialization.The
#initialize()method is called on everyget()invocation, which re-registers event listeners without cleanup. This will accumulate listeners over time.Add an initialization guard:
+ #initialized = false; + async #initialize() { + if (this.#initialized) { + return; + } + this.#initialized = true; const wallets = await import('@wallet-standard/core').then(mod => mod.getWallets()); // ... }
🟡 Minor comments (20)
packages/localizations/src/id-ID.ts-1365-1370 (1)
1365-1370: Localize the link label text (“wallet extension”) to Indonesian. The surrounding sentence is Indonesian but the link label is English.web3SolanaWalletButtons: { connect: 'Hubungkan dengan {{walletName}}', continue: 'Lanjutkan dengan {{walletName}}', noneAvailable: - 'Tidak ada dompet Solana Web3 yang terdeteksi. Silakan instal {{ solanaWalletsLink || link("wallet extension") }} yang mendukung Web3.', + 'Tidak ada dompet Solana Web3 yang terdeteksi. Silakan instal {{ solanaWalletsLink || link("ekstensi dompet") }} yang mendukung Web3.', },packages/localizations/src/hr-HR.ts-1372-1377 (1)
1372-1377: Fix Croatian grammar + consider translating the link label innoneAvailable.
Current: “Nisu otkrivene Solana Web3 novčanike …” mixes gender/case. Suggested: “Nisu otkriveni Solana Web3 novčanici …”. Also consider translatinglink("wallet extension")(e.g., “proširenje novčanika”) if other locales localize that label.web3SolanaWalletButtons: { connect: 'Poveži se s {{walletName}}', continue: 'Nastavi s {{walletName}}', noneAvailable: - 'Nisu otkrivene Solana Web3 novčanike. Instalirajte {{ solanaWalletsLink || link("wallet extension") }} s podrškom za Web3.', + 'Nisu otkriveni Solana Web3 novčanici. Instalirajte {{ solanaWalletsLink || link("wallet extension") }} s podrškom za Web3.', },packages/localizations/src/ms-MY.ts-757-760 (1)
757-760: Prefer consistent “daftar masuk” phrasing (vs “log masuk”) in Solana sign-in copy.
Elsewhere in this file you consistently use “Daftar masuk”, so “log masuk” may read inconsistent in the same flow.web3Solana: { - subtitle: 'Pilih dompet di bawah untuk log masuk', - title: 'Log masuk dengan Solana', + subtitle: 'Pilih dompet di bawah untuk daftar masuk', + title: 'Daftar masuk dengan Solana', },packages/localizations/src/ms-MY.ts-1385-1390 (1)
1385-1390: Localize the default link label (“wallet extension”) in the “noneAvailable” message.
IfsolanaWalletsLinkisn’t provided, users will see the English fallback text.noneAvailable: - 'Tiada dompet Solana Web3 dikesan. Sila pasang {{ solanaWalletsLink || link("wallet extension") }} yang menyokong Web3.', + 'Tiada dompet Solana Web3 dikesan. Sila pasang {{ solanaWalletsLink || link("sambungan dompet") }} yang menyokong Web3.',packages/localizations/src/nl-NL.ts-1365-1370 (1)
1365-1370: Translate fallback link text to Dutch for consistency.The
noneAvailablemessage on line 1369 contains English text"wallet extension"within the link fallback. For consistency with the Dutch locale and the pattern used elsewhere in this file (e.g., line 808), this should be translated to Dutch.Apply this diff to translate the fallback text:
noneAvailable: - 'Geen Solana Web3-wallets gedetecteerd. Installeer een Web3-ondersteunde {{ solanaWalletsLink || link("wallet extension") }}.', + 'Geen Solana Web3-wallets gedetecteerd. Installeer een Web3-ondersteunde {{ solanaWalletsLink || link("wallet-extensie") }}.',packages/localizations/src/es-UY.ts-1341-1344 (1)
1341-1344: Use vos conjugation and consistent wallet terminology.This is directly inconsistent with line 1359 in the same
web3WalletsSection, which correctly uses "Seleccioná una cartera Web3".Apply this diff:
web3SelectSolanaWalletScreen: { - subtitle: 'Selecciona una billetera de Solana para conectarla a tu cuenta.', - title: 'Agregar una billetera de Solana', + subtitle: 'Seleccioná una cartera de Solana para conectarla a tu cuenta.', + title: 'Agregar una cartera de Solana', },packages/localizations/src/es-UY.ts-854-857 (1)
854-857: Use vos conjugation and consistent wallet terminology.Same inconsistency as the sign-in flow: should use vos form "Seleccioná" and "cartera" to match the established locale conventions.
Apply this diff:
web3Solana: { - subtitle: 'Selecciona una billetera abajo para registrarte', + subtitle: 'Seleccioná una cartera abajo para registrarte', title: 'Registrarse con Solana', },packages/localizations/src/es-UY.ts-1380-1385 (1)
1380-1385: Use consistent wallet terminology.The
noneAvailablemessage uses "billeteras" but should use "carteras" to match the existing Web3 wallet terminology in this locale.Apply this diff:
web3SolanaWalletButtons: { connect: 'Conectar con {{walletName}}', continue: 'Continuar con {{walletName}}', noneAvailable: - 'No se detectaron billeteras Web3 de Solana. Instala una {{ solanaWalletsLink || link("wallet extension") }} compatible con Web3.', + 'No se detectaron carteras Web3 de Solana. Instala una {{ solanaWalletsLink || link("wallet extension") }} compatible con Web3.', },packages/localizations/src/es-UY.ts-968-970 (1)
968-970: Use vos conjugation for imperative forms.The imperative "Inténtalo" is tú form. In Uruguayan Spanish (vos), it should be "Intentalo" without the accent.
Apply this diff:
- web3_signature_request_rejected: 'Has rechazado la solicitud de firma. Inténtalo de nuevo para continuar.', + web3_signature_request_rejected: 'Has rechazado la solicitud de firma. Intentalo de nuevo para continuar.', web3_solana_signature_generation_failed: - 'Se produjo un error al generar la firma. Inténtalo de nuevo para continuar.', + 'Se produjo un error al generar la firma. Intentalo de nuevo para continuar.',packages/localizations/src/es-UY.ts-756-759 (1)
756-759: Use vos conjugation and consistent wallet terminology.The es-UY locale uses vos conjugation throughout (e.g., "Seleccioná" on line 1167), but these new additions use tú form. Additionally, existing Web3 wallet translations use "cartera" (lines 1337-1340), not "billetera".
Apply this diff for consistency:
web3Solana: { - subtitle: 'Selecciona una billetera abajo para iniciar sesión', + subtitle: 'Seleccioná una cartera abajo para iniciar sesión', title: 'Iniciar sesión con Solana', },packages/localizations/src/hi-IN.ts-1378-1383 (1)
1378-1383: Localize the remaining English fragment (“wallet extension”) for hi-IN.Suggested tweak:
noneAvailable: - 'कोई Solana Web3 वॉलेट नहीं मिला। कृपया Web3 समर्थित {{ solanaWalletsLink || link("wallet extension") }} इंस्टॉल करें।', + 'कोई Solana Web3 वॉलेट नहीं मिला। कृपया Web3 समर्थित {{ solanaWalletsLink || link("वॉलेट एक्सटेंशन") }} इंस्टॉल करें।',packages/shared/src/types/clerk.ts-916-920 (1)
916-920: Add full JSDoc for this new public API (param details + expectedwalletName).
Current comment doesn’t document required inputs / behavior./** * Authenticates user using their Solana supported Web3 wallet browser extension + * + * @param params - Configuration options for the Solana authentication flow. + * @returns A promise that resolves when the authentication flow completes. */ authenticateWithSolana: (params: AuthenticateWithSolanaParams) => Promise<unknown>;packages/ui/src/elements/Web3SolanaWalletButtons.tsx-28-30 (1)
28-30: Public export needs JSDoc + explicit return type (and keep the prop type stable). This is a new exported UI API inpackages/**/src/**/*.tsx.type Web3WalletButtonsProps = { web3AuthCallback: ({ walletName }: { walletName: string }) => Promise<unknown>; }; +/** + * Renders installed Solana wallets and invokes `web3AuthCallback` with the selected wallet name. + */ -export const Web3SolanaWalletButtons = (props: Web3WalletButtonsProps) => { +export const Web3SolanaWalletButtons = (props: Web3WalletButtonsProps): JSX.Element => { const network = MAINNET_ENDPOINT; const wallets = useMemo(() => [], [network]); return ( <ConnectionProvider endpoint={network}> <WalletProvider wallets={wallets} onError={err => { console.error(err); }} > <Web3SolanaWalletButtonsInner web3AuthCallback={props.web3AuthCallback} /> </WalletProvider> </ConnectionProvider> ); };Also applies to: 265-280
packages/localizations/src/fr-FR.ts-1391-1396 (1)
1391-1396: Localize the fallback link label (“wallet extension”). The surrounding sentence is French; the link text should be too.web3SolanaWalletButtons: { connect: 'Se connecter avec {{walletName}}', continue: 'Continuer avec {{walletName}}', noneAvailable: - 'Aucun portefeuille Solana Web3 détecté. Veuillez installer une {{ solanaWalletsLink || link("wallet extension") }} compatible Web3.', + 'Aucun portefeuille Solana Web3 détecté. Veuillez installer une {{ solanaWalletsLink || link("extension de portefeuille") }} compatible Web3.', },packages/ui/src/elements/Web3SolanaWalletButtons.tsx-195-263 (1)
195-263:idis dropped in both button variants; forward it (or remove it). Currentlyidis destructured and never applied, so passingid={w.name}has no effect.const WalletButtonIcon = forwardRef((props: WalletButtonProps, ref: Ref<HTMLButtonElement> | null): JSX.Element => { const { icon, label, id, ...rest } = props; return ( <Button ref={ref} + id={id} textVariant='buttonLarge' variant='outline' colorScheme='neutral' hoverAsFocus sx={t => ({ minHeight: t.sizes.$8, width: '100%', })} {...rest} > {icon} </Button> ); }); const WalletButtonBlock = forwardRef((props: WalletButtonProps, ref: Ref<HTMLButtonElement> | null): JSX.Element => { const { id, icon, isLoading, label, ...rest } = props; const isIconElement = isValidElement(icon); return ( <SimpleButton + id={id} variant='outline' block isLoading={isLoading} hoverAsFocus ref={ref} {...rest} sx={theme => [ { gap: theme.space.$4, position: 'relative', justifyContent: 'flex-start', }, props.sx, ]} >packages/localizations/src/sr-RS.ts-1364-1369 (1)
1364-1369: Localize the fallback link label ("wallet extension") to Serbian.The string passed to
link()is currently English but should be translated to Serbian to match the surrounding text. The suggested translation is appropriate.web3SolanaWalletButtons: { connect: 'Poveži se sa {{walletName}}', continue: 'Nastavi sa {{walletName}}', noneAvailable: - 'Nisu detektovani Solana Web3 novčanici. Instaliraj {{ solanaWalletsLink || link("wallet extension") }} koji podržava Web3.', + 'Nisu detektovani Solana Web3 novčanici. Instaliraj {{ solanaWalletsLink || link("ekstenziju novčanika") }} koji podržava Web3.', },packages/localizations/src/vi-VN.ts-1374-1379 (1)
1374-1379: Localize the fallback link label in the Solana wallet buttons message. The fallback text "wallet extension" should be translated to Vietnamese to match the localization pattern used elsewhere in the file (e.g., "Chính sách bảo mật", "Điều khoản dịch vụ").Suggested fix:
web3SolanaWalletButtons: { connect: 'Kết nối với {{walletName}}', continue: 'Tiếp tục với {{walletName}}', noneAvailable: - 'Không phát hiện ví Solana Web3 nào. Vui lòng cài đặt {{ solanaWalletsLink || link("wallet extension") }} hỗ trợ Web3.', + 'Không phát hiện ví Solana Web3 nào. Vui lòng cài đặt {{ solanaWalletsLink || link("phần mở rộng ví") }} hỗ trợ Web3.', },packages/localizations/src/mn-MN.ts-1368-1373 (1)
1368-1373: All localization files have an English fallback in the Solana Web3 wallet message. The pattern{{ solanaWalletsLink || link("wallet extension") }}appears identically in all 40+ language files. WhilesolanaWalletsLinkis always provided in the actual implementation (Web3SolanaWalletButtons.tsx passes'https://solana.com/solana-wallets'), the fallback text "wallet extension" would render literally if the parameter were ever missing, creating an English UI text in non-English locales. This should be addressed systematically across all language files, not just mn-MN—for instance, a Mongolian translation like "түрийвчийн өргөтгөл" or "таалай өргөтгөл" would be more appropriate.packages/shared/src/internal/clerk-js/injectedWeb3SolanaProviders.ts-54-60 (1)
54-60: Fallback provider type assertion may not match SolanaWalletAdapterWallet interface.The
window.solanafallback is cast toSolanaWalletAdapterWallet, but the globalwindow.solanaprovider (e.g., Phantom's legacy API) may not conform to the Wallet Standard interface. This could cause runtime errors when accessingfeatures[StandardConnect]orfeatures[SolanaSignMessage]in the calling code.Consider returning a more specific type or documenting that the fallback provider may have a different API:
- if ( - fallbackProvider && - typeof fallbackProvider.connect === 'function' && - typeof fallbackProvider.signMessage === 'function' - ) { - return fallbackProvider as SolanaWalletAdapterWallet; - } + // Note: Legacy providers may not fully implement SolanaWalletAdapterWallet + // The caller should handle potential API differences + if ( + fallbackProvider && + typeof fallbackProvider.connect === 'function' && + typeof fallbackProvider.signMessage === 'function' + ) { + return fallbackProvider as SolanaWalletAdapterWallet; + }packages/shared/src/internal/clerk-js/web3.ts-184-190 (1)
184-190: Potential control flow issue after errorThrower.throw().The
errorThrower.throw()call on line 186 is followed byreturn;on line 187, buterrorThrower.throw()should already throw an exception. IferrorThrower.throw()doesn't actually throw (e.g., in certain build configurations), the function would returnundefinedwhich could cause issues downstream.Consider restructuring to ensure the throw is explicit:
if (provider === 'solana') { if (!walletName || walletName.length === 0) { - errorThrower.throw('Wallet name must be provided to get Solana wallet provider'); - return; + throw errorThrower.throw('Wallet name must be provided to get Solana wallet provider'); } return await getInjectedWeb3SolanaProviders().get(walletName); }Or verify that
errorThrower.throw()always throws and remove the unreachablereturn;.Committable suggestion skipped: line range outside the PR's diff.
🧹 Nitpick comments (20)
packages/localizations/src/zh-TW.ts (2)
937-938: New web3 error strings are clear; consider slightly more user-actionable wording.
Current messages are fine; optional tweak would be adding a hint like “確認錢包已解鎖/已連線” for the signature-generation failure if that matches product tone.
1330-1335: Localize the fallback link label (“wallet extension”) to avoid mixed-language UI.
link("wallet extension")will likely render English in a zh-TW sentence; suggest a zh-TW label (e.g.,link("錢包擴充功能")orlink("錢包擴充套件")) unless there’s a product requirement to keep this specific label in English.packages/ui/src/utils/web3CallbackErrorHandler.ts (1)
6-8: Good hardening with optional chaining; consider removinganyto preserve type-safetyThe optional chaining on
err.errors?.[0](Line 13-14) is a solid robustness improvement (avoids crashes on missing/emptyerrors). Since this is a public exported utility, I’d also tightenerr: anytoerr: unknownsoisClerkAPIResponseError(err)actually provides meaningful narrowing.type Web3CallbackErrorHandler = { - (err: any, setError?: (err: ClerkRuntimeErrorType | ClerkAPIError | string | undefined) => void): void; + (err: unknown, setError?: (err: ClerkRuntimeErrorType | ClerkAPIError | string | undefined) => void): void; };Also applies to: 10-22
packages/localizations/src/fa-IR.ts (3)
761-764: Consider localizing “Solana” consistently with Persian copy (or confirm brand-style choice).
Strings are clear, but mixing Persian with Latin “Solana” can be stylistically inconsistent across fa-IR; consider “سولانا” if that’s the convention elsewhere.
858-861: Keep sign-up wording aligned with sign-in wording (terminology + punctuation).
Same comment as sign-in: if you decide on “Solana” vs “سولانا”, apply consistently across both flows.
1375-1380: Potential template-token + localization issue innoneAvailable(whitespace + English fallback label).
- You use
{{ solanaWalletsLink || link("wallet extension") }}(extra spaces inside{{ ... }}) whereas other strings use{{privacyPolicyLink || link("...")}}; if the templating engine is strict, keep formatting consistent.- The fallback label
"wallet extension"is English in an fa-IR string; consider a Persian label if that’s expected for this locale.Proposed tweak:
- 'هیچ کیف پول Solana Web3 شناسایی نشد. لطفاً یک {{ solanaWalletsLink || link("wallet extension") }} پشتیبانیشده از Web3 نصب کنید.', + 'هیچ کیف پول Solana Web3 شناسایی نشد. لطفاً یک {{solanaWalletsLink || link("افزونهٔ کیف پول")}} پشتیبانیشده از Web3 نصب کنید.',packages/localizations/src/ru-RU.ts (1)
1350-1353: Minor terminology inconsistency.The subtitle uses "аккаунту" while the rest of the file predominantly uses "учетная запись" for "account" (e.g., lines 585, 1017, 1119). Consider aligning for consistency:
web3SelectSolanaWalletScreen: { - subtitle: 'Выберите кошелёк Solana для подключения к вашему аккаунту.', + subtitle: 'Выберите кошелёк Solana для подключения к вашей учетной записи.', title: 'Добавить кошелёк Solana', },packages/clerk-js/rspack.config.js (1)
126-139: Consider maintenance burden of hardcoded Solana dependency list.The explicit exclusion list for Solana packages and their transitive dependencies (
bn.js,borsh,buffer,superstruct,bs58,jayson,rpc-websockets,qrcode) may become stale if Solana wallet adapter dependencies change. Consider:
- Adding a comment explaining why these specific packages are excluded
- Documenting the source of this dependency list (e.g., "transitive deps of @solana/wallet-adapter-* as of v1.x")
This will help future maintainers understand when/if the list needs updating.
packages/shared/src/types/signInCommon.ts (1)
195-198: Add JSDoc + clarifywalletNameexpectations for this new public type.
Since this is a new exported/public surface, please document whatwalletNameshould match (e.g., display name vs adapter name) and any validation expectations.packages/shared/src/types/factors.ts (1)
41-46: Document/guardwalletNameusage (likely Solana-only).
Consider adding a short comment/JSDoc on Line 45 thatwalletNameis used for Solana flows (and ignored otherwise), and ensure downstream code doesn’t treat it as trusted input without validation.packages/shared/src/types/web3Wallet.ts (1)
30-42: Consider a discriminated union to enforce “walletName required for Solana”.
Right nowwalletNameis optional even whenprovideris'solana', which pushes errors to runtime.-export interface GenerateSignatureParams { - identifier: string; - nonce: string; - provider: Web3Provider; - walletName?: string; -} +export type GenerateSignatureParams = + | { + identifier: string; + nonce: string; + provider: 'solana'; + walletName: string; + } + | { + identifier: string; + nonce: string; + provider: Exclude<Web3Provider, 'solana'>; + walletName?: never; + };packages/shared/src/types/signInFuture.ts (1)
7-8: Good doc, but consider encoding “Solana requires walletName” in the type.
The comment on Lines 253-255 is helpful; a discriminated union would prevent invalid calls at compile-time.Also applies to: 243-256
packages/localizations/src/ja-JP.ts (1)
1378-1383: Consider localizing thelink("wallet extension")label to avoid mixed-language UI.
Right now the clickable label will render as “wallet extension” in Japanese.noneAvailable: - 'Solana Web3 ウォレットが検出されませんでした。Web3 に対応した {{ solanaWalletsLink || link("wallet extension") }} をインストールしてください。', + 'Solana Web3 ウォレットが検出されませんでした。Web3 に対応した {{ solanaWalletsLink || link("ウォレット拡張機能") }} をインストールしてください。',packages/shared/src/types/clerk.ts (1)
2302-2309:AuthenticateWithSolanaParamslooks good; consider documenting whatwalletNameshould match (UI label vs provider id).
This helps prevent callers passing display names that don’t map to injected providers.packages/localizations/src/pl-PL.ts (3)
754-757: Polish grammar: consider “przez Solanę” (accusative) instead of “przez Solana”.web3Solana: { subtitle: 'Wybierz poniżej portfel, aby się zalogować', - title: 'Zaloguj się przez Solana', + title: 'Zaloguj się przez Solanę', },
852-855: Polish grammar: consider “przez Solanę” (accusative) instead of “przez Solana”.web3Solana: { subtitle: 'Wybierz poniżej portfel, aby się zarejestrować', - title: 'Zarejestruj się przez Solana', + title: 'Zarejestruj się przez Solanę', },
1376-1381: Consider translating thelink("wallet extension")label to Polish to avoid mixed-language UI.noneAvailable: - 'Nie wykryto portfeli Solana Web3. Zainstaluj {{ solanaWalletsLink || link("wallet extension") }} obsługujący Web3.', + 'Nie wykryto portfeli Solana Web3. Zainstaluj {{ solanaWalletsLink || link("rozszerzenie portfela") }} obsługujące Web3.',packages/localizations/src/en-US.ts (1)
1367-1372: Minor copy nit: consider “Web3-supported” for readability.noneAvailable: - 'No Solana Web3 wallets detected. Please install a Web3 supported {{ solanaWalletsLink || link("wallet extension") }}.', + 'No Solana Web3 wallets detected. Please install a Web3-supported {{ solanaWalletsLink || link("wallet extension") }}.',packages/clerk-js/src/core/resources/SignIn.ts (1)
26-26: Consider using type-only imports for better tree-shaking.The imported
GenerateSignatureandSignInAuthenticateWithSolanaParamsare types and should use theimport typesyntax.As per coding guidelines, use type-only imports for better tree-shaking.
Apply this diff:
EmailLinkFactor, EnterpriseSSOConfig, - GenerateSignature, + type GenerateSignature, PassKeyConfig,ResetPasswordParams, ResetPasswordPhoneCodeFactorConfig, - SignInAuthenticateWithSolanaParams, + type SignInAuthenticateWithSolanaParams, SignInCreateParams,Also applies to: 36-36
packages/clerk-js/src/core/resources/SignUp.ts (1)
19-19: Consider using type-only import for better tree-shaking.The imported
SignUpAuthenticateWithSolanaParamsis a type and should use theimport typesyntax.As per coding guidelines, use type-only imports for better tree-shaking.
Apply this diff:
PreparePhoneNumberVerificationParams, PrepareVerificationParams, PrepareWeb3WalletVerificationParams, - SignUpAuthenticateWithSolanaParams, + type SignUpAuthenticateWithSolanaParams, SignUpAuthenticateWithWeb3Params,
| public authenticateWithSolana = async (params: SignInAuthenticateWithSolanaParams): Promise<SignInResource> => { | ||
| const identifier = await web3().getSolanaIdentifier(params.walletName); | ||
| return this.authenticateWithWeb3({ | ||
| identifier, | ||
| generateSignature: p => web3().generateSignatureWithSolana({ ...p, walletName: params.walletName }), | ||
| strategy: 'web3_solana_signature', | ||
| walletName: params.walletName, | ||
| }); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add JSDoc documentation for the new public API.
The new authenticateWithSolana method is a public API and should include JSDoc comments explaining parameters, return value, and usage.
As per coding guidelines, all public APIs must be documented with JSDoc.
Add documentation like this:
+ /**
+ * Authenticates a user using a Solana Web3 wallet.
+ *
+ * @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 (params: SignInAuthenticateWithSolanaParams): Promise<SignInResource> => {🤖 Prompt for AI Agents
In packages/clerk-js/src/core/resources/SignIn.ts around lines 454 to 462, the
new public method authenticateWithSolana lacks JSDoc; add a JSDoc block
immediately above the method that documents the params
(SignInAuthenticateWithSolanaParams and walletName), the Promise<SignInResource>
return value, a short description of what the method does (authenticates using a
Solana wallet), and a usage example (e.g. await signIn.authenticateWithSolana({
walletName: 'phantom' })); keep tags @param and @returns and format the example
inside a code fence as in project guidelines.
| public authenticateWithSolana = async (params: SignUpAuthenticateWithSolanaParams): Promise<SignUpResource> => { | ||
| const identifier = await web3().getSolanaIdentifier(params.walletName); | ||
| return this.authenticateWithWeb3({ | ||
| identifier, | ||
| generateSignature: p => web3().generateSignatureWithSolana({ ...p, walletName: params.walletName }), | ||
| unsafeMetadata: params?.unsafeMetadata, | ||
| strategy: 'web3_solana_signature', | ||
| legalAccepted: params?.legalAccepted, | ||
| walletName: params.walletName, | ||
| }); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add JSDoc documentation for the new public API.
The new authenticateWithSolana method is a public API and should include JSDoc comments explaining parameters, return value, and usage.
As per coding guidelines, all public APIs must be documented with JSDoc.
Add documentation like this:
+ /**
+ * 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', 'solflare')
+ * @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 (params: SignUpAuthenticateWithSolanaParams): Promise<SignUpResource> => {🤖 Prompt for AI Agents
In packages/clerk-js/src/core/resources/SignUp.ts around lines 361 to 371, the
new public method authenticateWithSolana is missing JSDoc; add a JSDoc block
immediately above the method that describes the method purpose, lists @param
entries for the SignUpAuthenticateWithSolanaParams fields (at least walletName,
legalAccepted, unsafeMetadata), specifies the @returns Promise<SignUpResource>,
and includes a short usage example showing await signUp.authenticateWithSolana({
walletName: 'phantom', legalAccepted: true });; ensure the JSDoc is properly
closed and formatted to satisfy the project's documentation standards.
| web3Solana: { | ||
| subtitle: 'Wähle unten eine Wallet aus, um dich anzumelden', | ||
| title: 'Mit Solana anmelden', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Maintain consistent formal German ("Sie" form) throughout the localization file.
The new web3Solana strings use informal German ("du" form), while the entire file consistently uses formal German ("Sie" form). This creates an inconsistent user experience.
Apply this diff to use formal German:
web3Solana: {
- subtitle: 'Wähle unten eine Wallet aus, um dich anzumelden',
+ subtitle: 'Wählen Sie unten eine Wallet aus, um sich anzumelden',
title: 'Mit Solana anmelden',
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| web3Solana: { | |
| subtitle: 'Wähle unten eine Wallet aus, um dich anzumelden', | |
| title: 'Mit Solana anmelden', | |
| }, | |
| web3Solana: { | |
| subtitle: 'Wählen Sie unten eine Wallet aus, um sich anzumelden', | |
| title: 'Mit Solana anmelden', | |
| }, |
🤖 Prompt for AI Agents
In packages/localizations/src/de-DE.ts around lines 767 to 770, the new
web3Solana strings use informal "du" wording while the file uses formal "Sie";
update the subtitle and title to formal German (use "Sie" and appropriate formal
phrasing), e.g. change "Wähle unten eine Wallet aus, um dich anzumelden" to a
formal variant and "Mit Solana anmelden" to a formal title, ensuring
capitalization and punctuation match existing entries and maintain the same key
names and surrounding structure.
| web3Solana: { | ||
| subtitle: 'Wähle unten eine Wallet aus, um dich zu registrieren', | ||
| title: 'Mit Solana registrieren', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Maintain consistent formal German ("Sie" form).
The web3Solana strings use informal German, creating inconsistency with the rest of the file.
Apply this diff:
web3Solana: {
- subtitle: 'Wähle unten eine Wallet aus, um dich zu registrieren',
+ subtitle: 'Wählen Sie unten eine Wallet aus, um sich zu registrieren',
title: 'Mit Solana registrieren',
},🤖 Prompt for AI Agents
In packages/localizations/src/de-DE.ts around lines 862 to 865, the web3Solana
strings use informal German ("dich" and "Wähle ... aus") which is inconsistent
with the rest of the file that uses the formal "Sie" form; update the subtitle
and title to use formal phrasing (e.g., change "Wähle unten eine Wallet aus, um
dich zu registrieren" to "Wählen Sie unten eine Wallet aus, um sich zu
registrieren" and ensure the title remains formal like "Mit Solana registrieren"
or adjust to "Mit Solana registrieren" if no change needed) so all user-facing
text consistently uses the formal "Sie" form.
| web3_signature_request_rejected: | ||
| 'Du hast die Signaturanfrage abgelehnt. Bitte versuche es erneut, um fortzufahren.', | ||
| web3_solana_signature_generation_failed: | ||
| 'Beim Erstellen der Signatur ist ein Fehler aufgetreten. Bitte versuche es erneut, um fortzufahren.', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Maintain consistent formal German ("Sie" form) in error messages.
The new Solana error messages use informal German, inconsistent with other error messages in the file.
Apply this diff:
web3_signature_request_rejected:
- 'Du hast die Signaturanfrage abgelehnt. Bitte versuche es erneut, um fortzufahren.',
+ 'Sie haben die Signaturanfrage abgelehnt. Bitte versuchen Sie es erneut, um fortzufahren.',
web3_solana_signature_generation_failed:
- 'Beim Erstellen der Signatur ist ein Fehler aufgetreten. Bitte versuche es erneut, um fortzufahren.',
+ 'Beim Erstellen der Signatur ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut, um fortzufahren.',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| web3_signature_request_rejected: | |
| 'Du hast die Signaturanfrage abgelehnt. Bitte versuche es erneut, um fortzufahren.', | |
| web3_solana_signature_generation_failed: | |
| 'Beim Erstellen der Signatur ist ein Fehler aufgetreten. Bitte versuche es erneut, um fortzufahren.', | |
| web3_signature_request_rejected: | |
| 'Sie haben die Signaturanfrage abgelehnt. Bitte versuchen Sie es erneut, um fortzufahren.', | |
| web3_solana_signature_generation_failed: | |
| 'Beim Erstellen der Signatur ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut, um fortzufahren.', |
🤖 Prompt for AI Agents
In packages/localizations/src/de-DE.ts around lines 983 to 986, the two new
Solana error messages use informal "Du" and "versuche"; update them to formal
German to match the rest of the file by replacing the strings so the first
message uses "Sie haben ..." and the second message uses "Bitte versuchen Sie
..." (i.e., change "Du hast die Signaturanfrage abgelehnt. Bitte versuche es
erneut, um fortzufahren." to the formal equivalent and change "Bitte versuche es
erneut, um fortzufahren." in the second message to "Bitte versuchen Sie es
erneut, um fortzufahren.").
| web3SelectSolanaWalletScreen: { | ||
| subtitle: 'Wähle eine Solana-Wallet aus, um sie mit deinem Konto zu verbinden.', | ||
| title: 'Solana-Wallet hinzufügen', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Maintain consistent formal German ("Sie" form) in wallet selection screen.
The web3SelectSolanaWalletScreen strings use informal German, inconsistent with the surrounding web3WalletsSection.
Apply this diff:
web3SelectSolanaWalletScreen: {
- subtitle: 'Wähle eine Solana-Wallet aus, um sie mit deinem Konto zu verbinden.',
+ subtitle: 'Wählen Sie eine Solana-Wallet aus, um sie mit Ihrem Konto zu verbinden.',
title: 'Solana-Wallet hinzufügen',
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| web3SelectSolanaWalletScreen: { | |
| subtitle: 'Wähle eine Solana-Wallet aus, um sie mit deinem Konto zu verbinden.', | |
| title: 'Solana-Wallet hinzufügen', | |
| }, | |
| web3SelectSolanaWalletScreen: { | |
| subtitle: 'Wählen Sie eine Solana-Wallet aus, um sie mit Ihrem Konto zu verbinden.', | |
| title: 'Solana-Wallet hinzufügen', | |
| }, |
🤖 Prompt for AI Agents
In packages/localizations/src/de-DE.ts around lines 1362 to 1365, the
web3SelectSolanaWalletScreen strings use informal German; change the subtitle to
the formal "Sie" form. Replace "Wähle eine Solana-Wallet aus, um sie mit deinem
Konto zu verbinden." with "Wählen Sie eine Solana-Wallet aus, um sie mit Ihrem
Konto zu verbinden." and keep the title as-is to match surrounding
web3WalletsSection formal tone.
| web3SolanaWalletButtons: { | ||
| connect: 'Mit {{walletName}} verbinden', | ||
| continue: 'Weiter mit {{walletName}}', | ||
| noneAvailable: | ||
| 'Keine Solana-Web3-Wallets erkannt. Bitte installiere eine Web3-unterstützte {{ solanaWalletsLink || link("wallet extension") }}.', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Maintain consistent formal German ("Sie" form) in wallet button messages.
The noneAvailable string uses informal German, inconsistent with the rest of the file.
Apply this diff:
web3SolanaWalletButtons: {
connect: 'Mit {{walletName}} verbinden',
continue: 'Weiter mit {{walletName}}',
noneAvailable:
- 'Keine Solana-Web3-Wallets erkannt. Bitte installiere eine Web3-unterstützte {{ solanaWalletsLink || link("wallet extension") }}.',
+ 'Keine Solana-Web3-Wallets erkannt. Bitte installieren Sie eine Web3-unterstützte {{ solanaWalletsLink || link("wallet extension") }}.',
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| web3SolanaWalletButtons: { | |
| connect: 'Mit {{walletName}} verbinden', | |
| continue: 'Weiter mit {{walletName}}', | |
| noneAvailable: | |
| 'Keine Solana-Web3-Wallets erkannt. Bitte installiere eine Web3-unterstützte {{ solanaWalletsLink || link("wallet extension") }}.', | |
| }, | |
| web3SolanaWalletButtons: { | |
| connect: 'Mit {{walletName}} verbinden', | |
| continue: 'Weiter mit {{walletName}}', | |
| noneAvailable: | |
| 'Keine Solana-Web3-Wallets erkannt. Bitte installieren Sie eine Web3-unterstützte {{ solanaWalletsLink || link("wallet extension") }}.', | |
| }, |
🤖 Prompt for AI Agents
In packages/localizations/src/de-DE.ts around lines 1402 to 1407, the
noneAvailable message uses informal German ("installiere") which is inconsistent
with the rest of the file; update the string to formal German by rephrasing to
something like "Es wurden keine Solana-Web3-Wallets erkannt. Bitte installieren
Sie eine Web3-unterstützte {{ solanaWalletsLink || link(\"wallet extension\")
}}." so that it uses "Sie" and matches the tone of the other messages.
| web3SolanaWalletButtons: { | ||
| connect: 'Подключиться через {{walletName}}', | ||
| continue: 'Продолжить через {{walletName}}', | ||
| noneAvailable: | ||
| 'Кошельки Solana Web3 не обнаружены. Установите {{ solanaWalletsLink || link("wallet extension") }} с поддержкой Web3.', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's check the structure of the localization file
fd 'ru-RU.ts' packages/localizations/src/Repository: clerk/javascript
Length of output: 95
🏁 Script executed:
# Look for similar patterns with link() function in other localization files
rg 'link\(' packages/localizations/src/ -A 2 -B 2 | head -50Repository: clerk/javascript
Length of output: 3731
🏁 Script executed:
# Check if there are other instances of fallback patterns in the Russian localization
rg '\|\|' packages/localizations/src/ru-RU.tsRepository: clerk/javascript
Length of output: 555
🏁 Script executed:
# Search for the localization system implementation to understand how template expressions are processed
fd -e ts -e js packages/ -type f | xargs rg 'link\(' | grep -E '(function|const.*link|export)' | head -20Repository: clerk/javascript
Length of output: 230
🏁 Script executed:
# Look for any documentation or comments about the link() function
rg -B 5 -A 5 'link\(' packages/localizations/src/ | grep -E '(//|/\*|\*)' | head -20Repository: clerk/javascript
Length of output: 42
🏁 Script executed:
# Check the English localization file for comparison
cat packages/localizations/src/en-US.ts | grep -A 5 "web3SolanaWalletButtons"Repository: clerk/javascript
Length of output: 329
🏁 Script executed:
# Look for the en-US pattern to understand the original
rg 'wallet extension' packages/localizations/src/Repository: clerk/javascript
Length of output: 8187
🏁 Script executed:
# Check if "wallet extension" appears elsewhere in code (not in localizations)
rg 'wallet extension' packages/ --type-list | grep -v localizations | head -20Repository: clerk/javascript
Length of output: 449
🏁 Script executed:
# Verify this is indeed a systemic issue - check how many files have this pattern
rg 'link\("wallet extension"\)' packages/localizations/src/ | wc -lRepository: clerk/javascript
Length of output: 62
🏁 Script executed:
# Check the total number of localization files to confirm coverage
ls -1 packages/localizations/src/*.ts | grep -v index | wc -lRepository: clerk/javascript
Length of output: 62
Untranslated fallback text in template expression affects all language files.
The noneAvailable message in web3SolanaWalletButtons contains English fallback text "wallet extension" across ALL 49 localization files. This creates a systemic issue where English text displays when solanaWalletsLink is not provided, regardless of the user's language setting.
While other link() fallbacks in ru-RU.ts ARE properly translated (e.g., "Политика конфиденциальности", "Условия обслуживания"), the wallet extension fallback remains untranslated everywhere. This should be translated consistently across all language files:
- 'Кошельки Solana Web3 не обнаружены. Установите {{ solanaWalletsLink || link("wallet extension") }} с поддержкой Web3.',
+ 'Кошельки Solana Web3 не обнаружены. Установите {{ solanaWalletsLink || link("расширение кошелька") }} с поддержкой Web3.',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| web3SolanaWalletButtons: { | |
| connect: 'Подключиться через {{walletName}}', | |
| continue: 'Продолжить через {{walletName}}', | |
| noneAvailable: | |
| 'Кошельки Solana Web3 не обнаружены. Установите {{ solanaWalletsLink || link("wallet extension") }} с поддержкой Web3.', | |
| }, | |
| web3SolanaWalletButtons: { | |
| connect: 'Подключиться через {{walletName}}', | |
| continue: 'Продолжить через {{walletName}}', | |
| noneAvailable: | |
| 'Кошельки Solana Web3 не обнаружены. Установите {{ solanaWalletsLink || link("расширение кошелька") }} с поддержкой Web3.', | |
| }, |
🤖 Prompt for AI Agents
In packages/localizations/src/ru-RU.ts around lines 1389–1394 the template
fallback text link("wallet extension") is left in English; replace that fallback
with the proper Russian translation (e.g., link("расширение кошелька")) while
preserving the template interpolation, spacing and existing keys, and then apply
the same replacement consistently across all other localization files so no
language falls back to the English phrase.
| const Web3SolanaWalletButtonsInner = ({ web3AuthCallback }: Web3WalletButtonsProps) => { | ||
| const card = useCardState(); | ||
| const { wallets } = useWallet(); | ||
| const { t } = useLocalizations(); | ||
|
|
||
| // Filter to only show installed wallets | ||
| const installedWallets = React.useMemo( | ||
| () => | ||
| wallets | ||
| .filter(w => { | ||
| return w.readyState === WalletReadyState.Installed; | ||
| }) | ||
| .map(wallet => { | ||
| return { | ||
| name: wallet.adapter.name, | ||
| icon: wallet.adapter.icon, | ||
| }; | ||
| }), | ||
| [wallets], | ||
| ); | ||
|
|
||
| const startWeb3AuthFlow = (walletName: string) => async () => { | ||
| card.setLoading(walletName); | ||
| try { | ||
| await web3AuthCallback({ walletName }); | ||
| } catch { | ||
| await sleep(1000); | ||
| } finally { | ||
| card.setIdle(); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don’t swallow auth errors; surface them via card.setError (and avoid arbitrary sleep). Right now failures silently “wait 1s” and reset to idle, which is hard to debug and UX-hostile.
- const startWeb3AuthFlow = (walletName: string) => async () => {
+ const startWeb3AuthFlow = (walletName: string) => async () => {
card.setLoading(walletName);
try {
await web3AuthCallback({ walletName });
- } catch {
- await sleep(1000);
+ } catch (err: unknown) {
+ card.setError(err instanceof Error ? err.message : 'Web3 authentication failed');
} finally {
card.setIdle();
}
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const Web3SolanaWalletButtonsInner = ({ web3AuthCallback }: Web3WalletButtonsProps) => { | |
| const card = useCardState(); | |
| const { wallets } = useWallet(); | |
| const { t } = useLocalizations(); | |
| // Filter to only show installed wallets | |
| const installedWallets = React.useMemo( | |
| () => | |
| wallets | |
| .filter(w => { | |
| return w.readyState === WalletReadyState.Installed; | |
| }) | |
| .map(wallet => { | |
| return { | |
| name: wallet.adapter.name, | |
| icon: wallet.adapter.icon, | |
| }; | |
| }), | |
| [wallets], | |
| ); | |
| const startWeb3AuthFlow = (walletName: string) => async () => { | |
| card.setLoading(walletName); | |
| try { | |
| await web3AuthCallback({ walletName }); | |
| } catch { | |
| await sleep(1000); | |
| } finally { | |
| card.setIdle(); | |
| } | |
| }; | |
| const Web3SolanaWalletButtonsInner = ({ web3AuthCallback }: Web3WalletButtonsProps) => { | |
| const card = useCardState(); | |
| const { wallets } = useWallet(); | |
| const { t } = useLocalizations(); | |
| // Filter to only show installed wallets | |
| const installedWallets = React.useMemo( | |
| () => | |
| wallets | |
| .filter(w => { | |
| return w.readyState === WalletReadyState.Installed; | |
| }) | |
| .map(wallet => { | |
| return { | |
| name: wallet.adapter.name, | |
| icon: wallet.adapter.icon, | |
| }; | |
| }), | |
| [wallets], | |
| ); | |
| const startWeb3AuthFlow = (walletName: string) => async () => { | |
| card.setLoading(walletName); | |
| try { | |
| await web3AuthCallback({ walletName }); | |
| } catch (err: unknown) { | |
| card.setError(err instanceof Error ? err.message : 'Web3 authentication failed'); | |
| } finally { | |
| card.setIdle(); | |
| } | |
| }; |
🤖 Prompt for AI Agents
In packages/ui/src/elements/Web3SolanaWalletButtons.tsx around lines 36 to 66,
the startWeb3AuthFlow catch block swallows errors and uses an arbitrary sleep
then resets the card to idle; change it to capture the caught error, call
card.setError with a meaningful message or the error object (e.g.,
card.setError(error.message || error)), remove the sleep call, and only call
card.setIdle on success (move setIdle into the try after await web3AuthCallback)
so errors remain visible; ensure the catch does not rethrow unless caller
expects it and preserve any cleanup needed.
647c5d6 to
571a845
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/clerk-js/package.json (1)
61-80: Remove unused Solana dependencies or implement their integration.The four new Solana dependencies (
@solana/wallet-adapter-base,@solana/wallet-adapter-react,@solana/wallet-standard,@wallet-standard/core) are added topackage.jsonbut are not imported or used anywhere in theclerk-jssource code. Additionally:
- No TypeScript
exportsfield is configured inpackage.jsonto expose types alongside runtime code@clerk/sharedalready contains Web3 type definitions (web3.ts,web3Wallet.ts); clarify whether these dependencies should be added there instead or ifclerk-jsactually needs themEither implement the dependencies with corresponding source code changes or remove them from this PR.
packages/localizations/src/pl-PL.ts (1)
809-811: Stray quote inlabel__onlyTermsOfServicestringThere’s an extra
"at the end of this string:label__onlyTermsOfService: 'Akceptuję {{ termsOfServiceLink || link("Warunki świadczenia usługi") }}"',This will render an unwanted quote character in the UI and is inconsistent with the neighboring strings. Suggest:
- label__onlyTermsOfService: 'Akceptuję {{ termsOfServiceLink || link("Warunki świadczenia usługi") }}"', + label__onlyTermsOfService: 'Akceptuję {{ termsOfServiceLink || link("Warunki świadczenia usługi") }}',
♻️ Duplicate comments (11)
packages/localizations/src/de-DE.ts (1)
767-770: Align new Solana strings with formal German (“Sie”) used elsewhereThe newly added Solana strings mix informal “du/dich/installiere” with a file that otherwise consistently speaks in the formal “Sie” tone. This is the same concern raised in earlier review comments and is still present.
Suggested diff to standardize to formal German while keeping keys and structure unchanged:
@@ signIn: { @@ - web3Solana: { - subtitle: 'Wähle unten eine Wallet aus, um dich anzumelden', - title: 'Mit Solana anmelden', - }, + web3Solana: { + subtitle: 'Wählen Sie unten eine Wallet aus, um sich anzumelden', + title: 'Mit Solana anmelden', + }, @@ signUp: { @@ - web3Solana: { - subtitle: 'Wähle unten eine Wallet aus, um dich zu registrieren', - title: 'Mit Solana registrieren', - }, + web3Solana: { + subtitle: 'Wählen Sie unten eine Wallet aus, um sich zu registrieren', + title: 'Mit Solana registrieren', + }, @@ unstable__errors: { @@ - web3_signature_request_rejected: - 'Du hast die Signaturanfrage abgelehnt. Bitte versuche es erneut, um fortzufahren.', - web3_solana_signature_generation_failed: - 'Beim Erstellen der Signatur ist ein Fehler aufgetreten. Bitte versuche es erneut, um fortzufahren.', + web3_signature_request_rejected: + 'Sie haben die Signaturanfrage abgelehnt. Bitte versuchen Sie es erneut, um fortzufahren.', + web3_solana_signature_generation_failed: + 'Beim Erstellen der Signatur ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut, um fortzufahren.', @@ web3WalletsSection: { @@ - web3SelectSolanaWalletScreen: { - subtitle: 'Wähle eine Solana-Wallet aus, um sie mit deinem Konto zu verbinden.', - title: 'Solana-Wallet hinzufügen', - }, + web3SelectSolanaWalletScreen: { + subtitle: 'Wählen Sie eine Solana-Wallet aus, um sie mit Ihrem Konto zu verbinden.', + title: 'Solana-Wallet hinzufügen', + }, @@ - web3SolanaWalletButtons: { - connect: 'Mit {{walletName}} verbinden', - continue: 'Weiter mit {{walletName}}', - noneAvailable: - 'Keine Solana-Web3-Wallets erkannt. Bitte installiere eine Web3-unterstützte {{ solanaWalletsLink || link("wallet extension") }}.', - }, + web3SolanaWalletButtons: { + connect: 'Mit {{walletName}} verbinden', + continue: 'Weiter mit {{walletName}}', + noneAvailable: + 'Keine Solana-Web3-Wallets erkannt. Bitte installieren Sie eine Web3-unterstützte {{ solanaWalletsLink || link("wallet extension") }}.', + },This keeps the existing meaning while matching the formal tone used across the rest of the locale.
Also applies to: 862-865, 983-986, 1362-1365, 1402-1407
packages/clerk-js/src/core/resources/SignIn.ts (1)
454-462: Add JSDoc forauthenticateWithSolanapublic API.This is a new public method on
SignInand should be documented like the other authentication helpers.+ /** + * Authenticates a user using a Solana Web3 wallet. + * + * @param params - Configuration for Solana authentication. + * @param params.walletName - The name of the Solana wallet to use (for example, 'phantom'). + * @returns A promise that resolves to the updated {@link SignInResource}. + * @throws {ClerkRuntimeError} If the Solana wallet cannot be found or the signature flow fails. + * + * @example + * ```ts + * await signIn.authenticateWithSolana({ walletName: 'phantom' }); + * ``` + */ public authenticateWithSolana = async (params: SignInAuthenticateWithSolanaParams): Promise<SignInResource> => {As per coding guidelines, all public APIs should have JSDoc with params, return type, throws, and an example.
packages/shared/src/internal/clerk-js/injectedWeb3SolanaProviders.ts (1)
6-23: Guard#initializeto prevent repeated listener registration and redundant imports.
get()invokes#initialize()on every call, which re-imports@wallet-standard/coreand re-attaches theregister/unregisterlisteners each time. Over time this will accumulate listeners and do unnecessary work.Consider guarding initialization and sharing a single in‑flight promise:
class InjectedWeb3SolanaProviders { #wallets: readonly Wallet[] | undefined = undefined; static #instance: InjectedWeb3SolanaProviders | null = null; + #initialized = false; + #initializing: Promise<void> | null = null; private constructor() {} async #initialize() { - const wallets = await import('@wallet-standard/core').then(mod => mod.getWallets()); - this.#wallets = wallets.get(); - - wallets.on('register', () => { - this.#wallets = wallets.get(); - }); - wallets.on('unregister', () => { - this.#wallets = wallets.get(); - }); + if (this.#initialized) { + return; + } + if (this.#initializing) { + await this.#initializing; + return; + } + + this.#initializing = (async () => { + const wallets = await import('@wallet-standard/core').then(mod => mod.getWallets()); + this.#wallets = wallets.get(); + + wallets.on('register', () => { + this.#wallets = wallets.get(); + }); + wallets.on('unregister', () => { + this.#wallets = wallets.get(); + }); + + this.#initialized = true; + this.#initializing = null; + })(); + + await this.#initializing; }This keeps listener registration strictly once while still updating
#walletson changes.Also applies to: 39-63
packages/clerk-js/src/core/resources/SignUp.ts (1)
361-371: Add JSDoc forauthenticateWithSolanasign-up API.
authenticateWithSolanais a new public entry point onSignUpand should be documented similarly to the other Web3 helpers, including walletName, legalAccepted, and unsafeMetadata.+ /** + * Authenticates a user during sign-up using a Solana Web3 wallet. + * + * @param params - Configuration for Solana Web3 sign-up. + * @param params.walletName - The Solana wallet to use (for example, 'phantom' or 'solflare'). + * @param params.unsafeMetadata - Optional unsafe metadata to attach to the new user. + * @param params.legalAccepted - Optional flag indicating the user has accepted legal terms. + * @returns A promise that resolves to the updated {@link SignUpResource}. + * @throws {ClerkRuntimeError} If wallet connection or signature generation fails. + * + * @example + * ```ts + * await signUp.authenticateWithSolana({ + * walletName: 'phantom', + * legalAccepted: true, + * }); + * ``` + */ public authenticateWithSolana = async (params: SignUpAuthenticateWithSolanaParams): Promise<SignUpResource> => {As per coding guidelines, all public APIs should carry JSDoc with parameters, return type, throws, and a usage example.
packages/ui/src/elements/Web3SolanaWalletButtons.tsx (3)
57-66: Surface web3 auth errors instead of sleeping and swallowing them.
startWeb3AuthFlowhides failures and just sleeps 1s before idling, which is opaque for users and hard to debug. Usecard.setErrorand remove the artificial delay so callers see a meaningful error.- const startWeb3AuthFlow = (walletName: string) => async () => { - card.setLoading(walletName); - try { - await web3AuthCallback({ walletName }); - } catch { - await sleep(1000); - } finally { - card.setIdle(); - } - }; + const startWeb3AuthFlow = (walletName: string) => async () => { + card.setLoading(walletName); + try { + await web3AuthCallback({ walletName }); + } catch (err: unknown) { + card.setError(err instanceof Error ? err : 'Web3 authentication failed'); + } finally { + card.setIdle(); + } + };Then drop the now-unused
sleepimport at Line 26.
174-193: Add an explicit accessible name for the icon‑onlyWalletButtonIcon.
WalletButtonIconrenders onlyiconas its child, so the underlying<Button>has no explicit name; relying on inner image/initials is brittle for screen readers. Use thelabelprop asaria-labelso SR users consistently hear which wallet they’re activating.const WalletButtonIcon = forwardRef((props: WalletButtonProps, ref: Ref<HTMLButtonElement> | null): JSX.Element => { const { icon, label, id, ...rest } = props; return ( <Button ref={ref} + aria-label={label} textVariant='buttonLarge' variant='outline' colorScheme='neutral' hoverAsFocus sx={t => ({ minHeight: t.sizes.$8, width: '100%', })} {...rest} > {icon} </Button> ); });
265-279:WalletProviderreceives an empty wallets array, so no Solana wallets will ever appear.
wallets = useMemo(() => [], [network])meansuseWallet()inWeb3SolanaWalletButtonsInneralways sees an empty list, soinstalledWalletsis always[]and the component will permanently render the “noneAvailable” alert, regardless of what users have installed.You need to instantiate and pass actual Solana wallet adapters (or a wallet-standard discovery adapter) here—ideally reusing the same adapter factory you use elsewhere / in the Core 2 implementation.
For example (pseudocode; wire up to your real adapter factory):
export const Web3SolanaWalletButtons = (props: Web3WalletButtonsProps) => { const network = MAINNET_ENDPOINT; - const wallets = useMemo(() => [], [network]); + const wallets = useMemo( + () => { + // TODO: replace with your real adapter factory, e.g. from a shared Solana adapters module. + // return createSolanaWalletAdapters({ endpoint: network }); + return []; + }, + [network], + );…and then ensure
createSolanaWalletAdapters(or equivalent) returns the supportedAdapter[]forWalletProvider.#!/bin/bash # Compare Core 2 vs Core 3 wiring for Solana wallet adapters to make sure this matches. rg -n "WalletProvider" packages/ui/src --type tsx -C3 | sed -n '1,120p'packages/ui/src/common/WalletInitialIcon.tsx (1)
39-40: Guard against empty or undefinedvaluewhen computing the initial.
value[0].toUpperCase()will throw ifvalueis an empty string or undefined. Use optional chaining/fallback so the component can safely render with an empty initial.- {value[0].toUpperCase()} + {value[0]?.toUpperCase() ?? ''}Or derive an
initialvariable with the same logic and render that.packages/ui/src/components/UserProfile/Web3SelectSolanaWalletScreen.tsx (2)
26-37: Don’t close the screen on connect errors; surface a visible error instead.Right now errors are just logged and the screen always closes in
finally, which looks like a no-op to the user and blocks retry. Prefer closing only on success and usingcard.setErroron failure.const onClick = async ({ walletName }: { walletName: string }) => { card.setLoading(walletName); try { await onConnect({ strategy: 'web3_solana_signature', walletName }); - card.setIdle(); + card.setIdle(); + close(); } catch (err) { card.setIdle(); - console.error(err); - } finally { - close(); + console.error(err); + card.setError(err as unknown); } };This keeps the screen open on failure and lets the existing card error plumbing show a message.
66-75: Set resetButtontotype="button"to avoid accidental submit.Inside
Form.Root, a Button without an explicittypecan default tosubmitif it renders a native<button>, unintentionally submitting the form.<FormButtonContainer> <Button variant='ghost' + type='button' onClick={() => { close(); }} localizationKey={localizationKeys('userProfile.formButtonReset')} elementDescriptor={descriptors.formButtonReset} /> </FormButtonContainer>packages/ui/src/components/SignIn/SignInFactorOneSolanaWalletsCard.tsx (1)
63-75: AlignsignUpContinueUrlpath with other SignIn combined-flow components.In the combined-flow case you currently use
'../create/continue', but sibling components (e.g.,SignInSocialButtons.tsx) use'create/continue'for the same override. The extra../will change the routing context and likely send users to the wrong step.- signUpContinueUrl: ctx.isCombinedFlow ? '../create/continue' : ctx.signUpContinueUrl, + signUpContinueUrl: ctx.isCombinedFlow ? 'create/continue' : ctx.signUpContinueUrl,This keeps the navigation consistent across SignIn Solana and social flows.
🧹 Nitpick comments (23)
packages/localizations/src/tr-TR.ts (1)
1370-1375: Optional: localize the “wallet extension” fallback labelCurrent
noneAvailablemixes Turkish with the English"wallet extension"label insidelink(...), which is slightly jarring but functional. You could localize the fallback link text to keep the sentence fully Turkish:- noneAvailable: - 'Solana Web3 cüzdanı tespit edilmedi. Lütfen Web3 destekli {{ solanaWalletsLink || link("wallet extension") }} kurun.', + noneAvailable: + 'Solana Web3 cüzdanı tespit edilmedi. Lütfen Web3 destekli {{ solanaWalletsLink || link("cüzdan uzantısını") }} kurun.',This keeps the grammar natural while preserving the link helper pattern.
packages/localizations/src/id-ID.ts (1)
1365-1370: Consider localizing “wallet extension” link labelThe button texts look good, and placeholders are correct. You might optionally localize the inner
"wallet extension"label to Indonesian for consistency with the rest of the file.- 'Tidak ada dompet Solana Web3 yang terdeteksi. Silakan instal {{ solanaWalletsLink || link("wallet extension") }} yang mendukung Web3.', + 'Tidak ada dompet Solana Web3 yang terdeteksi. Silakan instal {{ solanaWalletsLink || link("ekstensi dompet") }} yang mendukung Web3.',packages/localizations/src/ja-JP.ts (1)
1378-1383: Wallet button labels look good; consider localizing link textThe connect/continue strings with
{{walletName}}are correct and consistent.
Minor nit: you might want to localize the inline link label"wallet extension"to Japanese, e.g.link("ウォレット拡張機能"), to match how other links in this file localize their visible text.packages/localizations/src/da-DK.ts (1)
1325-1328: Consider terminology consistency for "wallet" vs "tegnebog".The new Solana-related sections use "wallet" as a loanword (lines 752, 846, 1327, 1368), while existing Web3 wallet sections in this file consistently use the Danish word "tegnebog/tegnebøger" (lines 1321, 1323, 1324, 1339, 1343, 1346).
While "wallet" is commonly understood in crypto contexts, consider using consistent terminology throughout the file for better maintainability.
For example, you could change "Solana-wallet" to "Solana-tegnebog" throughout:
- Line 752: "Vælg en tegnebog nedenfor for at logge ind"
- Line 846: "Vælg en tegnebog nedenfor for at tilmelde dig"
- Line 1327: "Tilføj en Solana-tegnebog"
- Lines 1365-1368: Use "tegnebog" instead of "wallet" (note: {{walletName}} interpolation should remain as-is)
packages/localizations/src/nb-NO.ts (1)
1366-1371: Wallet button labels good; consider localizing inner “wallet extension” textThe
web3SolanaWalletButtonsstrings and placeholders ({{walletName}},{{ solanaWalletsLink || link("wallet extension") }}) look structurally correct. Minor nit: the anchor text"wallet extension"inside the last string is still English; consider translating it (e.g., a Norwegian equivalent for “wallet extension”) if consistency with the rest of this locale is desired.packages/localizations/src/pl-PL.ts (3)
754-757: Solana sign-in copy is fine; optional word-order tweakThe text is clear, but
Wybierz poniżej portfel, aby się zalogowaćis slightly unusual word order in Polish. If you want a more natural phrasing, considerWybierz portfel poniżej, aby się zalogować. Not required if you’re aligning with other locales.
852-855: Sign-up Solana copy matches sign-in; same optional phrasing tweakCopy is consistent with the sign-in variant. As above, you might prefer
Wybierz portfel poniżej, aby się zarejestrowaćfor a slightly more natural word order, but the current text is understandable.
1376-1381: Consider localizing the “wallet extension” link textThe sentence is Polish but the fallback link label is English:
'... Zainstaluj {{ solanaWalletsLink || link("wallet extension") }} obsługujący Web3.'For consistency with other entries that localize the text inside
link(...), you might prefer something like:- 'Nie wykryto portfeli Solana Web3. Zainstaluj {{ solanaWalletsLink || link("wallet extension") }} obsługujący Web3.', + 'Nie wykryto portfeli Solana Web3. Zainstaluj {{ solanaWalletsLink || link("rozszerzenie portfela") }} obsługujące Web3.',Adjust wording as you see fit, but keeping the link label Polish will make the UI feel more consistent.
packages/clerk-js/rspack.config.js (2)
126-139: Consider following the existing pattern of dedicated cache groups.The file already defines dedicated cache groups for
stripeVendor,coinbaseWalletSDKVendor, andbaseAccountSDKVendor(lines 112-117, 107-111, 102-106). For consistency and maintainability, Solana packages and their dependencies could follow the same pattern rather than being excluded fromdefaultVendors.This approach would:
- Align with the existing architecture
- Make the bundling strategy more explicit
- Simplify future updates to the Solana dependency list
- Provide better control over chunk naming and priority
Example refactor:
+ solanaVendor: { + test: /[\\/]node_modules[\\/](@solana|@solana-mobile|@wallet-standard|bn\.js|borsh|buffer|superstruct|bs58|jayson|rpc-websockets|qrcode)[\\/]/, + name: 'solana-vendors', + chunks: 'all', + enforce: true, + }, defaultVendors: { minChunks: 1, - test: module => { - if (!(module instanceof rspack.NormalModule) || !module.resource) { - return false; - } - // Exclude Solana packages and their known transitive dependencies - if ( - /[\\/]node_modules[\\/](@solana|@solana-mobile|@wallet-standard|bn\.js|borsh|buffer|superstruct|bs58|jayson|rpc-websockets|qrcode)[\\/]/.test( - module.resource, - ) - ) { - return false; - } - return /[\\/]node_modules[\\/]/.test(module.resource); - }, + test: /[\\/]node_modules[\\/]/, name: 'vendors', priority: -10, },
130-137: Add documentation explaining the rationale for Solana exclusion.The comment states what is being excluded but not why these packages require special treatment. Adding context would help future maintainers understand the bundling strategy.
Consider expanding the comment:
- // Exclude Solana packages and their known transitive dependencies + // Exclude Solana packages and their known transitive dependencies from the default vendor chunk + // to enable separate chunking or lazy loading due to [size/compatibility/loading strategy reason]packages/localizations/src/he-IL.ts (1)
1343-1348: Root Solana wallet button texts and templating look goodThe
web3SolanaWalletButtonsgroup cleanly exposesconnect,continue, andnoneAvailablestrings, using interpolation ({{walletName}},{{ solanaWalletsLink || link("wallet extension") }}) in a way that matches the project’s templating style. Also, many other keys in this file remainundefined, which is correct given the fallback behavior in Clerk localizations. Based on learnings, this is the expected pattern.packages/localizations/src/es-UY.ts (5)
756-759: Align Solana sign-in strings with es‑UY voseo and existing “cartera” termThe structure and keys look correct, but for es-UY this block currently mixes tú-style (“Selecciona”) and the new “billetera” term, while the rest of the file uses voseo (“Seleccioná”) and “cartera Web3”.
Consider updating for consistency:
totpMfa: { formTitle: 'Código de verificación', subtitle: 'Para continuar, ingresá el código generado por tu aplicación autenticadora', title: 'Verificación en dos pasos', }, - web3Solana: { - subtitle: 'Selecciona una billetera abajo para iniciar sesión', - title: 'Iniciar sesión con Solana', - }, + web3Solana: { + subtitle: 'Seleccioná una cartera abajo para iniciar sesión', + title: 'Iniciar sesión con Solana', + },
854-857: Unify Solana sign-up wording with es‑UY styleSame pattern here: tú-style “Selecciona” + “billetera” vs voseo and “cartera” elsewhere in es-UY.
You could align it like this:
start: { actionLink: 'Iniciar sesión', @@ }, - web3Solana: { - subtitle: 'Selecciona una billetera abajo para registrarte', - title: 'Registrarse con Solana', - }, + web3Solana: { + subtitle: 'Seleccioná una cartera abajo para registrarte', + title: 'Registrarse con Solana', + },
1341-1344: Match Solana wallet-management copy to existing Web3 wallet sectionThis block is structurally correct, but again uses “Selecciona” + “billetera de Solana” while nearby text (e.g.,
subtitle__availableWallets) uses “Seleccioná” + “cartera Web3”.For consistency within this locale:
web3WalletsSection: { destructiveAction: 'Eliminar cartera', detailsAction__nonPrimary: undefined, primaryButton: 'Conectar cartera', title: 'Carteras Web3', - web3SelectSolanaWalletScreen: { - subtitle: 'Selecciona una billetera de Solana para conectarla a tu cuenta.', - title: 'Agregar una billetera de Solana', - }, + web3SelectSolanaWalletScreen: { + subtitle: 'Seleccioná una cartera de Solana para conectarla a tu cuenta.', + title: 'Agregar una cartera de Solana', + },
968-970: Voseo nuance in new Solana error messages (optional)The error keys and messages are correct and clear. If you want to be fully consistent with es-UY voseo (e.g., nearby “Instalá una para continuar.”), you might tweak the phrasing:
- web3_signature_request_rejected: 'Has rechazado la solicitud de firma. Inténtalo de nuevo para continuar.', - web3_solana_signature_generation_failed: - 'Se produjo un error al generar la firma. Inténtalo de nuevo para continuar.', + web3_signature_request_rejected: 'Rechazaste la solicitud de firma. Intentá de nuevo para continuar.', + web3_solana_signature_generation_failed: + 'Ocurrió un error al generar la firma. Intentá de nuevo para continuar.',Purely stylistic; fine to keep as-is if you prefer more neutral wording.
1380-1385: Ensure wallet-availability message matches es‑UY terminology and voseoKeys/placeholders look correct (
walletName,solanaWalletsLink). Same optional consistency suggestion around “billeteras” vs “carteras” and “Instala” vs “Instalá”:- web3SolanaWalletButtons: { - connect: 'Conectar con {{walletName}}', - continue: 'Continuar con {{walletName}}', - noneAvailable: - 'No se detectaron billeteras Web3 de Solana. Instala una {{ solanaWalletsLink || link("wallet extension") }} compatible con Web3.', - }, + web3SolanaWalletButtons: { + connect: 'Conectar con {{walletName}}', + continue: 'Continuar con {{walletName}}', + noneAvailable: + 'No se detectaron carteras Web3 de Solana. Instalá una {{ solanaWalletsLink || link("wallet extension") }} compatible con Web3.', + },(You may also want to localize the inner
"wallet extension"label in a follow-up if other es-* locales do so.)packages/ui/src/components/UserProfile/Web3Form.tsx (1)
16-24: Consider explicit component return type and stricter error typingTo better align with the TS guidelines for public APIs, you could:
- Give
AddWeb3WalletActionMenuan explicit return type (e.g.(): JSX.Element | null).- Change
catch (err: any)tocatch (err: unknown)and narrow via your existinggetFieldError/handleErrorutilities.This would tighten types without changing behavior.
Also applies to: 41-43, 65-73
packages/shared/src/types/signInCommon.ts (1)
196-198: NewSignInAuthenticateWithSolanaParamstype is fine but could be tightened laterDefining a dedicated
SignInAuthenticateWithSolanaParams { walletName: string }cleanly exposes the extra Solana requirement for sign‑in flows. If you later introduce a shared Solana wallet name type (e.g. from aweb3Wallettypes module), consider reusing it here instead of plainstringto keep wallet names consistent across sign‑in and sign‑up.packages/shared/src/types/signUpCommon.ts (1)
114-121: Web3/Solana sign-up param types are coherentMaking
legalAcceptedpart ofSignUpAuthenticateWithWeb3Paramsand layeringSignUpAuthenticateWithSolanaParams = SignUpAuthenticateWithWeb3Params & { walletName: string }gives a clear, reusable shape for Solana without disturbing existing helpers. As with the sign‑in side, you might later narrowwalletNameto a shared wallet-name type, but the current approach is consistent and safe.packages/shared/src/internal/clerk-js/web3.ts (2)
140-193: Tighten Solana walletName guard ingetWeb3Wallet.
errorThrower.throwalready throws and never returns, so thereturn;that follows is effectively dead code and slightly obscures control flow.async function getWeb3Wallet(provider: Web3Provider, walletName?: string) { @@ - if (provider === 'solana') { - if (!walletName || walletName.length === 0) { - errorThrower.throw('Wallet name must be provided to get Solana wallet provider'); - return; - } - return await getInjectedWeb3SolanaProviders().get(walletName); - } + if (provider === 'solana') { + if (!walletName || walletName.length === 0) { + errorThrower.throw('Wallet name must be provided to get Solana wallet provider'); + } + return await getInjectedWeb3SolanaProviders().get(walletName); + }This makes it clearer that the Solana branch either throws or returns a provider. As per coding guidelines, keeping error paths explicit improves maintainability.
68-93: Use error code 4001 instead of message string matching for Solana user rejection detection.The current implementation detects user rejection by checking if the error message includes "User rejected the request.". The Solana Wallet Standard (implemented by Phantom, Solflare, and other wallet adapters) exposes a stable error code
4001for user rejection. Update the error handling to checkerr.code === 4001instead of relying on message text matching:if (err && err.code === 4001) { throw new ClerkRuntimeError('Web3 signature request was rejected by the user.', { code: 'web3_signature_request_rejected', }); }This aligns with the coding guidelines preference for structured error codes over message parsing and makes the error handling robust to wallet adapter or locale changes.
packages/ui/src/elements/Web3SolanaWalletButtons.tsx (2)
116-124: SimplifygridTemplateColumns; currentwallets.length < 1branch is effectively dead.Because you early-return when
installedWallets.length === 0, thewallets.length < 1ternary here never takes the first branch. You can simplify to a singlerepeatexpression based onrow.lengthandrowIndex, which also makes intent clearer:- gridTemplateColumns: - wallets.length < 1 - ? `repeat(1, minmax(0, 1fr))` - : `repeat(${row.length}, ${ - rowIndex === 0 - ? `minmax(0, 1fr)` - : // Calculate the width of each button based on the width of the buttons within the first row. - // t.sizes.$2 is used here to represent the gap defined on the Grid component. - `minmax(0, calc((100% - (${strategyRowOneLength} - 1) * ${t.sizes.$2}) / ${strategyRowOneLength}))` - })`, + gridTemplateColumns: `repeat(${row.length}, ${ + rowIndex === 0 + ? `minmax(0, 1fr)` + : // Calculate the width of each button based on the width of the buttons within the first row. + // t.sizes.$2 is used here to represent the gap defined on the Grid component. + `minmax(0, calc((100% - (${strategyRowOneLength} - 1) * ${t.sizes.$2}) / ${strategyRowOneLength}))` + })`,
195-262:WalletButtonBlocksemantics look good; optional: also setaria-labelfor consistency.This variant already exposes the wallet name as visible text, so it’s accessible. If you want stricter consistency with
WalletButtonIcon, you could also setaria-label={label}onSimpleButton, but that’s optional.
| web3SolanaWalletButtons: { | ||
| connect: 'Poveži se s {{walletName}}', | ||
| continue: 'Nastavi s {{walletName}}', | ||
| noneAvailable: | ||
| 'Nisu otkrivene Solana Web3 novčanike. Instalirajte {{ solanaWalletsLink || link("wallet extension") }} s podrškom za Web3.', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix grammatical error in the noneAvailable message.
Line 1375-1376 contains a grammatical mismatch in Croatian. The feminine plural form "otkrivene" doesn't agree with the masculine noun "novčanike" (which should be in nominative case "novčanici" as the subject).
Apply this diff to correct the grammar:
noneAvailable:
- 'Nisu otkrivene Solana Web3 novčanike. Instalirajte {{ solanaWalletsLink || link("wallet extension") }} s podrškom za Web3.',
+ 'Nisu otkriveni Solana Web3 novčanici. Instalirajte {{ solanaWalletsLink || link("wallet extension") }} s podrškom za Web3.',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| web3SolanaWalletButtons: { | |
| connect: 'Poveži se s {{walletName}}', | |
| continue: 'Nastavi s {{walletName}}', | |
| noneAvailable: | |
| 'Nisu otkrivene Solana Web3 novčanike. Instalirajte {{ solanaWalletsLink || link("wallet extension") }} s podrškom za Web3.', | |
| }, | |
| web3SolanaWalletButtons: { | |
| connect: 'Poveži se s {{walletName}}', | |
| continue: 'Nastavi s {{walletName}}', | |
| noneAvailable: | |
| 'Nisu otkriveni Solana Web3 novčanici. Instalirajte {{ solanaWalletsLink || link("wallet extension") }} s podrškom za Web3.', | |
| }, |
🤖 Prompt for AI Agents
In packages/localizations/src/hr-HR.ts around lines 1372 to 1377, the
noneAvailable Croatian string uses the feminine plural "otkrivene" which
disagrees with the masculine plural noun "novčanike/novčanici"; update the
message to use the correct masculine plural form and case while preserving
placeholders and the link expression. Replace the string with a grammatically
correct sentence such as: "Nisu otkriveni Solana Web3 novčanici. Instalirajte {{
solanaWalletsLink || link(\"wallet extension\") }} s podrškom za Web3." ensuring
escaping of any quotes as required by the file.
| web3Solana: { | ||
| subtitle: 'Selectați un portofel mai jos pentru a vă conecta', | ||
| title: 'Conectare cu Solana', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent register: formal vs. informal Romanian.
The new Solana sign-in strings use the formal register ("Selectați", "vă conecta"), but the rest of the file consistently uses the informal register (e.g., Line 753: "Te rugăm să te autentifici"). This creates an inconsistent user experience.
Apply this diff to align with the informal register used throughout the file:
web3Solana: {
- subtitle: 'Selectați un portofel mai jos pentru a vă conecta',
+ subtitle: 'Selectează un portofel mai jos pentru a te conecta',
title: 'Conectare cu Solana',
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| web3Solana: { | |
| subtitle: 'Selectați un portofel mai jos pentru a vă conecta', | |
| title: 'Conectare cu Solana', | |
| }, | |
| web3Solana: { | |
| subtitle: 'Selectează un portofel mai jos pentru a te conecta', | |
| title: 'Conectare cu Solana', | |
| }, |
🤖 Prompt for AI Agents
In packages/localizations/src/ro-RO.ts around lines 763 to 766, the web3Solana
strings use the formal register ("Selectați", "vă conecta") whereas the file
uses informal Romanian; replace the subtitle with the informal phrasing
"Selectează un portofel mai jos pentru a te conecta" (keep the title "Conectare
cu Solana") so the register matches the rest of the file.
| web3Solana: { | ||
| subtitle: 'Selectați un portofel mai jos pentru a vă înregistra', | ||
| title: 'Înregistrare cu Solana', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same register inconsistency in sign-up strings.
This block also uses the formal register, inconsistent with the rest of the file.
Apply this diff:
web3Solana: {
- subtitle: 'Selectați un portofel mai jos pentru a vă înregistra',
+ subtitle: 'Selectează un portofel mai jos pentru a te înregistra',
title: 'Înregistrare cu Solana',
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| web3Solana: { | |
| subtitle: 'Selectați un portofel mai jos pentru a vă înregistra', | |
| title: 'Înregistrare cu Solana', | |
| }, | |
| web3Solana: { | |
| subtitle: 'Selectează un portofel mai jos pentru a te înregistra', | |
| title: 'Înregistrare cu Solana', | |
| }, |
🤖 Prompt for AI Agents
In packages/localizations/src/ro-RO.ts around lines 860 to 863, the web3Solana
block uses the formal register ("Înregistrare cu Solana", "Selectați un portofel
mai jos pentru a vă înregistra") which is inconsistent with the rest of the
file; change these to the informal forms used elsewhere: set title to
"Înregistrează-te cu Solana" and subtitle to "Selectează un portofel mai jos
pentru a te înregistra". Ensure spacing and punctuation match surrounding
entries.
| web3SelectSolanaWalletScreen: { | ||
| subtitle: 'Selectați un portofel Solana pentru a-l conecta la contul dvs.', | ||
| title: 'Adăugați un portofel Solana', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Formal register used in wallet screen strings.
Inconsistent with the surrounding content (e.g., Line 1362: 'Selectează un portofel web3 pentru a-l conecta la cont.').
Apply this diff:
web3SelectSolanaWalletScreen: {
- subtitle: 'Selectați un portofel Solana pentru a-l conecta la contul dvs.',
- title: 'Adăugați un portofel Solana',
+ subtitle: 'Selectează un portofel Solana pentru a-l conecta la contul tău.',
+ title: 'Adaugă un portofel Solana',
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| web3SelectSolanaWalletScreen: { | |
| subtitle: 'Selectați un portofel Solana pentru a-l conecta la contul dvs.', | |
| title: 'Adăugați un portofel Solana', | |
| }, | |
| web3SelectSolanaWalletScreen: { | |
| subtitle: 'Selectează un portofel Solana pentru a-l conecta la contul tău.', | |
| title: 'Adaugă un portofel Solana', | |
| }, |
🤖 Prompt for AI Agents
In packages/localizations/src/ro-RO.ts around lines 1344 to 1347, the wallet
screen strings use the formal register; change them to the informal register to
match surrounding content. Replace the subtitle with "Selectează un portofel
Solana pentru a-l conecta la cont." and the title with "Adaugă un portofel
Solana".
| web3SolanaWalletButtons: { | ||
| connect: 'Conectează cu {{walletName}}', | ||
| continue: 'Continuă cu {{walletName}}', | ||
| noneAvailable: | ||
| 'Nu s-au detectat portofele Solana Web3. Instalați un {{ solanaWalletsLink || link("wallet extension") }} compatibil cu Web3.', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mixed register and untranslated English text.
Two issues:
noneAvailableuses formal ("Instalați") whileconnect/continueuse informal — inconsistent within the same block.- The fallback text
"wallet extension"is in English and should be translated.
Apply this diff:
web3SolanaWalletButtons: {
connect: 'Conectează cu {{walletName}}',
continue: 'Continuă cu {{walletName}}',
noneAvailable:
- 'Nu s-au detectat portofele Solana Web3. Instalați un {{ solanaWalletsLink || link("wallet extension") }} compatibil cu Web3.',
+ 'Nu s-au detectat portofele Solana Web3. Instalează o {{ solanaWalletsLink || link("extensie de portofel") }} compatibilă cu Web3.',
},🤖 Prompt for AI Agents
In packages/localizations/src/ro-RO.ts around lines 1383 to 1388, the
web3SolanaWalletButtons block mixes formal and informal register and leaves the
fallback link text in English; change "Instalați" to the informal "Instalează"
to match "Conectează" / "Continuă" and translate the fallback "wallet extension"
to Romanian (e.g., "extensie pentru portofel") so the noneAvailable string
becomes informal and fully localized.
| export const Web3SolanaWalletButtons = (props: Web3WalletButtonsProps) => { | ||
| const network = MAINNET_ENDPOINT; | ||
| const wallets = useMemo(() => [], [network]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's find and examine the target file
find . -name "Web3SolanaWalletButtons.tsx" -type fRepository: clerk/javascript
Length of output: 176
🏁 Script executed:
# Check the package.json for Solana dependencies
find . -name "package.json" -type f | head -20 | xargs grep -l "@solana/wallet-standard" 2>/dev/null | head -5Repository: clerk/javascript
Length of output: 176
🏁 Script executed:
# Search for MAINNET_ENDPOINT usage in the codebase
rg "MAINNET_ENDPOINT" --type ts --type tsx -B 2 -A 2Repository: clerk/javascript
Length of output: 176
🏁 Script executed:
# Let's also check how this file imports from @solana packages
rg "@solana" packages/ui/src/elements/Web3SolanaWalletButtons.tsx 2>/dev/nullRepository: clerk/javascript
Length of output: 176
🌐 Web query:
@solana/wallet-standard MAINNET_ENDPOINT constant export
💡 Result:
Short answer: No — the @solana/wallet-standard JavaScript package does not export a MAINNET_ENDPOINT constant. The Wallet Standard uses chain identifiers (e.g. "solana:mainnet"/"solana:devnet") rather than hard-coded RPC endpoint constants; many tooling/docs use the canonical RPC URL https://api.mainnet-beta.solana.com when an RPC is needed. [1][2][3]
Sources:
- @solana/wallet-standard (npm) package info. [1]
- Wallet Standard / Solana docs referencing chain identifier "solana:mainnet". [2]
- Common Solana RPC endpoint (https://api.mainnet-beta.solana.com) used in docs and examples. [3]
🌐 Web query:
@solana/wallet-standard npm package API documentation
💡 Result:
You can find the package and API sources here:
- @solana/wallet-standard npm package (package page + versions). [1]
- Solana Wallet Standard repository (Solana-specific extensions / repo on GitHub). [2]
- Solana docs showing Wallet Standard usage (Wallet Connection / Commerce Kit). [3]
References
- @solana/wallet-standard — npm package page. [npmjs.com/package/@solana/wallet-standard]
- anza-xyz / wallet-standard — GitHub (Solana extensions to the Wallet Standard). [github.com/anza-xyz/wallet-standard]
- Solana docs — Wallet Connection (Wallet Standard usage in Commerce Kit). [launch.solana.com/docs/commerce-kit/quickstart/wallet-connection]
Remove the non-existent MAINNET_ENDPOINT import — this constant does not exist in @solana/wallet-standard.
The @solana/wallet-standard package does not export a MAINNET_ENDPOINT constant. The Wallet Standard instead uses chain identifiers (e.g., "solana:mainnet", "solana:devnet"). If an RPC endpoint is required, use the canonical Solana mainnet endpoint https://api.mainnet-beta.solana.com or make it configurable via props/environment variables to support devnet and testnet environments.
🤖 Prompt for AI Agents
In packages/ui/src/elements/Web3SolanaWalletButtons.tsx around lines 265 to 267,
remove references to the non-existent MAINNET_ENDPOINT import from
@solana/wallet-standard and stop using it directly; instead, provide a concrete
RPC endpoint or make it configurable by accepting an endpoint prop (or reading
from an env/config) and defaulting to the canonical Solana mainnet RPC
"https://api.mainnet-beta.solana.com" (or use chain identifier strings like
"solana:mainnet" if the wallet APIs require that), update useMemo to depend on
the chosen configurable endpoint/chain identifier, and ensure imports and types
are adjusted accordingly.
…ure support (#7293) Signed-off-by: Kenton Duprey <[email protected]> Co-authored-by: Dylan Staley <[email protected]> Signed-off-by: Kenton Duprey <[email protected]>
…a Solana enabled wallet via `<UserProfile />` (#7435) Signed-off-by: Kenton Duprey <[email protected]>
Signed-off-by: Kenton Duprey <[email protected]>
Signed-off-by: Kenton Duprey <[email protected]>
4a6460a to
bca9f40
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (15)
packages/localizations/src/hr-HR.ts (1)
1372-1377: Fix grammatical error in the noneAvailable message.Lines 1375-1376 contain a grammatical mismatch in Croatian. The feminine plural form "otkrivene" doesn't agree with the masculine noun "novčanike" (which should be in nominative case "novčanici" as the subject).
Apply this diff to correct the grammar:
noneAvailable: - 'Nisu otkrivene Solana Web3 novčanike. Instalirajte {{ solanaWalletsLink || link("wallet extension") }} s podrškom za Web3.', + 'Nisu otkriveni Solana Web3 novčanici. Instalirajte {{ solanaWalletsLink || link("wallet extension") }} s podrškom za Web3.',packages/ui/src/components/SignIn/SignInFactorOneSolanaWalletsCard.tsx (1)
70-70: Fix thesignUpContinueUrlpath to match sibling components.The path
'../create/continue'in the combined-flow condition is inconsistent withSignInSocialButtons.tsx, which uses'create/continue'. Both components are siblings in the same routing context, so using'../'navigates to the wrong step.Apply this diff:
- signUpContinueUrl: ctx.isCombinedFlow ? '../create/continue' : ctx.signUpContinueUrl, + signUpContinueUrl: ctx.isCombinedFlow ? 'create/continue' : ctx.signUpContinueUrl,packages/localizations/src/ro-RO.ts (5)
763-766: Align sign-in Solana strings with informal register used elsewhere.Most of this file uses the informal register (e.g., Line 753: “Te rugăm să te autentifici”), but this block uses formal “Selectați” / “vă conecta”, which is inconsistent.
web3Solana: { - subtitle: 'Selectați un portofel mai jos pentru a vă conecta', + subtitle: 'Selectează un portofel mai jos pentru a te conecta', title: 'Conectare cu Solana', },
860-863: Use informal register for sign-up Solana copy.Same inconsistency here: formal “Selectați” / “vă înregistra” and nominal title vs. informal style used elsewhere.
web3Solana: { - subtitle: 'Selectați un portofel mai jos pentru a vă înregistra', - title: 'Înregistrare cu Solana', + subtitle: 'Selectează un portofel mai jos pentru a te înregistra', + title: 'Înregistrează-te cu Solana', },
973-975: Switch Solana error messages to informal register to match surrounding errors.Nearby errors (e.g., Line 972) use informal “Te rugăm…”, but these use formal “Ați” / “Încercați”.
- web3_signature_request_rejected: 'Ați respins solicitarea de semnătură. Încercați din nou pentru a continua.', - web3_solana_signature_generation_failed: - 'A apărut o eroare la generarea semnăturii. Încercați din nou pentru a continua.', + web3_signature_request_rejected: 'Ai respins solicitarea de semnătură. Încearcă din nou pentru a continua.', + web3_solana_signature_generation_failed: + 'A apărut o eroare la generarea semnăturii. Încearcă din nou pentru a continua.',
1344-1347: Update Solana wallet selection screen to informal register.This block uses formal “Selectați”, “contul dvs.”, “Adăugați”, unlike the informal style in
web3WalletPagejust below.web3SelectSolanaWalletScreen: { - subtitle: 'Selectați un portofel Solana pentru a-l conecta la contul dvs.', - title: 'Adăugați un portofel Solana', + subtitle: 'Selectează un portofel Solana pentru a-l conecta la contul tău.', + title: 'Adaugă un portofel Solana', },
1383-1388: Fix mixed register and untranslated “wallet extension” in Solana wallet buttons.
connect/continueare informal, butnoneAvailableuses formal “Instalați” and leaves “wallet extension” in English.web3SolanaWalletButtons: { connect: 'Conectează cu {{walletName}}', continue: 'Continuă cu {{walletName}}', noneAvailable: - 'Nu s-au detectat portofele Solana Web3. Instalați un {{ solanaWalletsLink || link("wallet extension") }} compatibil cu Web3.', + 'Nu s-au detectat portofele Solana Web3. Instalează o {{ solanaWalletsLink || link("extensie de portofel") }} compatibilă cu Web3.', },packages/ui/src/common/WalletInitialIcon.tsx (1)
39-39: Add safety check for emptyvaluestring.Accessing
value[0]without checking if the string is non-empty will cause a runtime error (undefined.toUpperCase()) if an empty string is passed.Apply this diff to add a safety check:
- {value[0].toUpperCase()} + {value[0]?.toUpperCase() ?? ''}packages/localizations/src/kk-KZ.ts (1)
1345-1350: Englishwallet extensionfallback should be localized (same systemic issue as earlier review)
noneAvailablestill falls back to the English phraselink("wallet extension"), so users withoutsolanaWalletsLinksee English text inside an otherwise Kazakh string. Please translate the fallback label while preserving the{{ solanaWalletsLink || link(...) }}pattern, consistent with the rest of this locale and the earlier comment on this issue.packages/localizations/src/ja-JP.ts (1)
1378-1383: Localizewallet extensionfallback inside noneAvailable
noneAvailablecurrently useslink("wallet extension")as an English fallback. This mirrors the systemic issue already noted in a previous review: ifsolanaWalletsLinkis absent, users see English text in a Japanese string. Please replace the fallback label with a Japanese phrase (e.g., a translation of “wallet extension”) while keeping the template structure.packages/localizations/src/fr-FR.ts (1)
1391-1396: Translatewallet extensionfallback in noneAvailableIn
web3SolanaWalletButtons.noneAvailable, the fallbacklink("wallet extension")remains in English. As already raised in a prior review, this yields English text whensolanaWalletsLinkis missing. Please switch that fallback label to French (e.g., an “extension de portefeuille” equivalent) while preserving the interpolation.packages/localizations/src/ru-RU.ts (1)
1389-1394: Englishwallet extensionfallback persists; align with earlier review
web3SolanaWalletButtons.noneAvailablestill useslink("wallet extension")in English. This is the same systemic localization gap already called out in a previous review: whensolanaWalletsLinkis absent, Russian users see an English phrase embedded in the message. Please replace the fallback text with a Russian equivalent while preserving the template.packages/localizations/src/he-IL.ts (1)
1343-1348: Localizewallet extensionfallback in noneAvailable
web3SolanaWalletButtons.noneAvailablestill falls back to the Englishlink("wallet extension"). As previously noted for this PR, that causes English text to appear in localized UI whensolanaWalletsLinkis not provided. Please replace the fallback label with a Hebrew phrase while keeping the interpolation intact.packages/clerk-js/src/core/resources/SignUp.ts (1)
361-371: DocumentauthenticateWithSolanapublic API with JSDoc
authenticateWithSolanais a new public method onSignUpand should be documented per the project’s JSDoc requirement for public APIs. A brief doc similar to the other authentication helpers will make its usage clearer to SDK consumers and keep generated docs accurate.For example:
/** * Authenticates a user during sign-up using a Solana Web3 wallet. * * @param params - Configuration for Solana authentication. * @param params.walletName - The Solana wallet to use (e.g. "phantom", "solflare"). * @param params.unsafeMetadata - Optional metadata to attach to the sign-up. * @param params.legalAccepted - Whether the user has accepted legal terms. * @returns A promise that resolves to the updated SignUp resource. */ public authenticateWithSolana = async (params: SignUpAuthenticateWithSolanaParams): Promise<SignUpResource> => { … };As per coding guidelines, all public APIs must be documented with JSDoc.
packages/clerk-js/src/core/resources/SignIn.ts (1)
454-462: Add JSDoc forauthenticateWithSolanaon SignIn
authenticateWithSolanais a new public entrypoint onSignInand should be documented like the other authentication helpers.Something along these lines would satisfy the guidelines:
/** * Authenticates a user using a Solana Web3 wallet. * * @param params - Configuration for Solana authentication. * @param params.walletName - The Solana wallet to use for authentication. * @returns A promise that resolves to the updated SignIn resource. */ public authenticateWithSolana = async (params: SignInAuthenticateWithSolanaParams): Promise<SignInResource> => { … };As per coding guidelines, all public APIs must be documented with JSDoc.
🧹 Nitpick comments (20)
packages/localizations/src/vi-VN.ts (1)
1374-1379: Wallet button strings are correct; consider localizing “wallet extension”Keys and placeholders (
{{walletName}},{{ solanaWalletsLink || link("…") }}) look correct; messages read well. As an optional polish, you might localize the linked anchor text instead of"wallet extension":- 'Không phát hiện ví Solana Web3 nào. Vui lòng cài đặt {{ solanaWalletsLink || link("wallet extension") }} hỗ trợ Web3.', + 'Không phát hiện ví Solana Web3 nào. Vui lòng cài đặt {{ solanaWalletsLink || link("tiện ích ví") }} hỗ trợ Web3.',packages/localizations/src/nl-NL.ts (1)
752-755: Solana wallet flow translations look good; minor terminology consistency nitThe Solana sign‑in/sign‑up/profile and button texts read well and keep placeholders like
{{walletName}}and{{ solanaWalletsLink || link("wallet extension") }}intact. One tiny nit: you alternate between “wallet”, “Solana‑wallet” and “(web3) portefeuille” elsewhere in this file. If you want maximum consistency, consider standardizing on either “wallet”/“Solana‑wallet” or “(web3) portefeuille” across these new keys, but this is purely cosmetic.Also applies to: 847-850, 1326-1329, 1365-1370
packages/localizations/src/nl-BE.ts (1)
1326-1329: Solana wallet‑selection screen copy is accurate; minor terminology nitTitle/subtitle correctly describe adding a Solana wallet and match other locales. You might optionally align terminology with nearby strings (either consistently “wallet” or “portefeuille”) for a slightly more uniform UX, but it’s not blocking.
packages/localizations/src/hi-IN.ts (1)
1378-1383: Consider translating "wallet extension" for consistency.The
connectandcontinuetranslations are good. However, innoneAvailable, the link text"wallet extension"is kept in English, while:
- Line 808 uses translated Hindi text in similar
link()patterns (e.g.,"गोपनीयता नीति")- Line 965 uses
"वॉलेट एक्सटेंशन"(Hindi transliteration) for the same termFor consistency, consider using the Hindi transliteration:
noneAvailable: - 'कोई Solana Web3 वॉलेट नहीं मिला। कृपया Web3 समर्थित {{ solanaWalletsLink || link("wallet extension") }} इंस्टॉल करें।', + 'कोई Solana Web3 वॉलेट नहीं मिला। कृपया Web3 समर्थित {{ solanaWalletsLink || link("वॉलेट एक्सटेंशन") }} इंस्टॉल करें।',packages/ui/src/components/SignIn/SignInFactorOneSolanaWalletsCard.tsx (2)
21-21: Add explicit return type annotation.The component function lacks an explicit return type. As per coding guidelines, functions should define explicit return types for clarity and type safety.
Apply this diff:
-const SignInFactorOneSolanaWalletsCardInner = () => { +const SignInFactorOneSolanaWalletsCardInner = (): React.JSX.Element => {
92-94: Add JSDoc for the public API.The exported component lacks JSDoc documentation. As per coding guidelines, public APIs should be documented with comprehensive JSDoc comments.
Apply this diff:
+/** + * SignIn card component for authenticating with Solana Web3 wallets. + * Displays wallet selection UI and handles Solana signature-based authentication. + * + * @returns A wrapped component with redirect and card state providers + */ export const SignInFactorOneSolanaWalletsCard = withRedirectToSignInTask( withRedirectToAfterSignIn(withCardStateProvider(SignInFactorOneSolanaWalletsCardInner)), );packages/ui/src/components/SignUp/SignUpStartSolanaWalletsCard.tsx (2)
21-21: Add explicit return type annotation.The component function lacks an explicit return type. As per coding guidelines, functions should define explicit return types for clarity and type safety.
Apply this diff:
-const SignUpStartSolanaWalletsCardInner = () => { +const SignUpStartSolanaWalletsCardInner = (): React.JSX.Element => {
91-93: Add JSDoc for the public API.The exported component lacks JSDoc documentation. As per coding guidelines, public APIs should be documented with comprehensive JSDoc comments.
Apply this diff:
+/** + * SignUp card component for authenticating with Solana Web3 wallets. + * Displays wallet selection UI and handles Solana signature-based authentication during sign-up. + * + * @returns A wrapped component with redirect and card state providers + */ export const SignUpStartSolanaWalletsCard = withRedirectToSignUpTask( withRedirectToAfterSignUp(withCardStateProvider(SignUpStartSolanaWalletsCardInner)), );packages/localizations/src/fi-FI.ts (1)
1368-1373: Consider minor grammatical refinement for "continue" button text.The translations are functional and understandable. However, for improved grammatical consistency with the rest of the file, line 1370 could be refined:
- Current:
'Jatka {{walletName}}'- Suggestion:
'Jatka {{walletName}}:lla'or'Jatka {{walletName}}:n kanssa'This would align better with the pattern used in line 853 (
'Jatka palvelun {{provider|titleize}} avulla'), which includes a preposition/postposition for "with" in Finnish.Apply this diff if you want to improve grammatical consistency:
web3SolanaWalletButtons: { connect: 'Yhdistä {{walletName}}', - continue: 'Jatka {{walletName}}', + continue: 'Jatka {{walletName}}:lla', noneAvailable: 'Solana Web3 -lompakoita ei havaittu. Asenna Web3-yhteensopiva {{ solanaWalletsLink || link("wallet extension") }}.', },Note: This is a minor grammatical preference rather than a critical issue. The current translation is still understandable.
packages/localizations/src/en-GB.ts (1)
1371-1376: Consider tightening “Web3 supported” phrasing for readabilityThe last sentence reads a bit awkwardly as “Web3 supported …”. For slightly smoother wording you could hyphenate “Web3-supported”:
- noneAvailable: - 'No Solana Web3 wallets detected. Please install a Web3 supported {{ solanaWalletsLink || link("wallet extension") }}.', + noneAvailable: + 'No Solana Web3 wallets detected. Please install a Web3-supported {{ solanaWalletsLink || link("wallet extension") }}.',Purely stylistic; no functional impact.
packages/localizations/src/cs-CZ.ts (1)
1380-1385: Consider localizing the fallback “wallet extension” link labelThe
web3SolanaWalletButtons.noneAvailablestring is fine functionally and placeholders look correct, but the fallback link label insidelink("wallet extension")is still English in an otherwise Czech sentence. You may want to switch that to a Czech phrase (similar to how otherlink("…")usages in this file are localized) to keep the UI fully localized.packages/localizations/src/id-ID.ts (1)
1365-1370: Root Solana wallet button labels look good; consider localizing link fallback textThe
web3SolanaWalletButtonslabels are clear and consistent with other provider button texts. One optional improvement: the fallback link label"wallet extension"is still in English; you may want to localize it, e.g.:- 'Tidak ada dompet Solana Web3 yang terdeteksi. Silakan instal {{ solanaWalletsLink || link("wallet extension") }} yang mendukung Web3.', + 'Tidak ada dompet Solana Web3 yang terdeteksi. Silakan instal {{ solanaWalletsLink || link("ekstensi dompet") }} yang mendukung Web3.',packages/localizations/src/th-TH.ts (1)
1358-1363: Root Solana wallet button labels are correct; consider localizing link textThe
web3SolanaWalletButtonsblock is structurally sound and uses{{walletName}}and{{ solanaWalletsLink || link("wallet extension") }}consistently with other locales. One optional improvement: you might want to localize the"wallet extension"label inside the link to Thai (as is done for policy/terms link labels) for a more native experience, unless you intentionally prefer the English term here.packages/localizations/src/be-BY.ts (2)
1337-1340: Solana wallet‑selection screen wiring is consistent; consider terminology tweakThe new
web3SelectSolanaWalletScreenobject underuserProfile.start.web3WalletsSectionis correctly nested and uses clear copy describing adding/connecting a Solana wallet.Minor nit: elsewhere in this file the concept of “account” is often translated as “ўліковы запіс”; here the subtitle uses “акаўнта”. For consistency, you might consider aligning the term with the dominant choice in this locale, if that matches your translator’s preference.
1376-1381: web3SolanaWalletButtons placeholders and syntax look goodThe
web3SolanaWalletButtonsblock is well‑formed, and the interpolation placeholders match existing patterns:
{{walletName}}is used in bothconnectandcontinue.{{ solanaWalletsLink || link("wallet extension") }}mirrors the samelink()helper style used earlier in this file.One optional improvement: the visible link text
"wallet extension"is still in English; if other locales localize that helper text, you may want to do the same here for consistency.packages/ui/src/common/WalletInitialIcon.tsx (1)
5-11: Consider adding JSDoc forvalueprop.The
idprop has JSDoc documentation, butvaluedoes not. For consistency and clarity, consider documenting whatvaluerepresents.type WalletInitialIconProps = PropsOfComponent<typeof Box> & { + /** + * The wallet name to display the initial of + */ value: string; /** * The wallet provider name */ id: string; };packages/shared/src/internal/clerk-js/web3.ts (1)
68-92: Consider making Solana “user rejected” detection more robust (optional)
generateWeb3Signaturerelies onerr.message.includes('User rejected the request.')to classify rejections, which may be brittle across wallet implementations and future library versions. If the Solana adapters expose a stable error code or type for user cancellations, it would be more robust to key off that instead of a hard-coded message fragment.Check the error shape emitted by the Solana wallet adapters you target (e.g. via their docs or a quick console.log in a local build) to see if there is a stable code/field you can branch on instead of the message text.
packages/localizations/src/en-US.ts (1)
846-849: Consider addingnoAvailableWalletsfor sign‑up Solana parity
signUp.web3Solanadefinestitleandsubtitle, but the type also includesnoAvailableWallets. It’s optional (viaDeepPartial), but adding an explicitnoAvailableWalletsstring here would keep the defaulten-USresource self‑contained and symmetric with the type.packages/clerk-js/src/core/resources/SignUp.ts (1)
260-309: Wallet‑name aware Web3 sign‑up flow matches shared Solana types
- Adding
walletNameto theauthenticateWithWeb3params and threading it through togenerateSignaturekeeps the sign‑up Web3 flow aligned with the newGenerateSignaturecontract and Solana support.- The convenience wrappers (
authenticateWithCoinbaseWallet,authenticateWithBase,authenticateWithOKXWallet) now consistently useSignUpAuthenticateWithWeb3Params, which matches the publicSignUpResourcetype.One improvement to consider: for parity with
SignIn.authenticateWithWeb3, you might add a small runtime guard here:const provider = strategy.replace('web3_', '').replace('_signature', '') as Web3Provider; if (!(typeof generateSignature === 'function')) { clerkMissingOptionError('generateSignature'); } + if (provider === 'solana' && !walletName) { + clerkMissingOptionError('walletName'); + }This would give developers a clearer error if they ever call
authenticateWithWeb3directly using the Solana strategy but forget to supplywalletName, even if the type system already discourages that.Also applies to: 326-337, 339-359
packages/clerk-js/src/core/resources/SignIn.ts (1)
368-416: Minor consistency nit: coinbase retry includeswalletNametooIn
authenticateWithWeb3, the Coinbase retry path now also passeswalletName:signature = await generateSignature({ identifier, nonce: message, provider, walletName });This is functionally fine given the new
GenerateSignatureshape and that Coinbase ignores unknown params, but for strict parity with the Future path (which omitswalletNameon retry) you could simplify this to:- signature = await generateSignature({ identifier, nonce: message, provider, walletName }); + signature = await generateSignature({ identifier, nonce: message, provider });Not required, but would keep both code paths visually aligned.
| web3SolanaWalletButtons: { | ||
| connect: 'Połącz z {{walletName}}', | ||
| continue: 'Kontynuuj z {{walletName}}', | ||
| noneAvailable: | ||
| 'Nie wykryto portfeli Solana Web3. Zainstaluj {{ solanaWalletsLink || link("wallet extension") }} obsługujący Web3.', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Translate the fallback link text to Polish.
The fallback text "wallet extension" in line 1380 should be translated to Polish to maintain consistency with other link() usages in this file (see lines 808-809, which translate fallback text).
Apply this diff:
noneAvailable:
- 'Nie wykryto portfeli Solana Web3. Zainstaluj {{ solanaWalletsLink || link("wallet extension") }} obsługujący Web3.',
+ 'Nie wykryto portfeli Solana Web3. Zainstaluj {{ solanaWalletsLink || link("rozszerzenie portfela") }} obsługujący Web3.',Note: "rozszerzenie portfela" = "wallet extension" in Polish.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| web3SolanaWalletButtons: { | |
| connect: 'Połącz z {{walletName}}', | |
| continue: 'Kontynuuj z {{walletName}}', | |
| noneAvailable: | |
| 'Nie wykryto portfeli Solana Web3. Zainstaluj {{ solanaWalletsLink || link("wallet extension") }} obsługujący Web3.', | |
| }, | |
| web3SolanaWalletButtons: { | |
| connect: 'Połącz z {{walletName}}', | |
| continue: 'Kontynuuj z {{walletName}}', | |
| noneAvailable: | |
| 'Nie wykryto portfeli Solana Web3. Zainstaluj {{ solanaWalletsLink || link("rozszerzenie portfela") }} obsługujący Web3.', | |
| }, |
🤖 Prompt for AI Agents
In packages/localizations/src/pl-PL.ts around lines 1376 to 1381, the fallback
text "wallet extension" inside link(...) is still in English; replace it with
the Polish translation "rozszerzenie portfela" so the fallback becomes
link("rozszerzenie portfela") to match other translations and maintain
consistency.
| { "path": "./dist/ui.browser.js", "maxSize": "19.5KB" }, | ||
| { "path": "./dist/framework*.js", "maxSize": "44KB" }, | ||
| { "path": "./dist/vendors*.js", "maxSize": "43KB" }, | ||
| { "path": "./dist/vendors*.js", "maxSize": "143KB" }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Driveby-comment: This seems like an awfully big increase for what I expect will be a rarely used feature? 🤔 Or does this end up in a separate chunk that gets lazy-loaded somehow?
Description
This PR ports over the new Sign in with Solana feature changes currently in Core 2 over to Core 3, allowing for continued support of the new feature.
USER-4212
Checklist
pnpm testruns as expected.pnpm buildruns as expected.Type of change
Summary by CodeRabbit
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.