@@ -425,17 +425,142 @@ export const TransferEth = () => {
425425}
426426` ` `
427427
428- ### 4. Add Components to Your App
428+ ### 4. Username Lookup
429+
430+ The Controller provides a ` lookupUsername ` method that allows you to check if a username exists and see what authentication options are available for existing accounts . This is particularly useful for headless flows where you want to determine login vs signup flows :
431+
432+ ` ` ` typescript
433+ import { useState, useCallback } from 'react'
434+ import { useConnect } from '@starknet-react/core'
435+ import { ControllerConnector } from '@cartridge/connector'
436+
437+ export function UsernameLookup() {
438+ const { connectors } = useConnect()
439+ const controller = connectors[0] as ControllerConnector
440+ const [username, setUsername] = useState<string>('')
441+ const [lookupResult, setLookupResult] = useState<any>(null)
442+ const [isLoading, setIsLoading] = useState<boolean>(false)
443+
444+ const handleLookup = useCallback(async () => {
445+ if (!username.trim()) return
446+
447+ setIsLoading(true)
448+ try {
449+ const result = await controller.lookupUsername(username.trim())
450+ setLookupResult(result)
451+ } catch (error) {
452+ console.error('Lookup failed:', error)
453+ setLookupResult(null)
454+ } finally {
455+ setIsLoading(false)
456+ }
457+ }, [controller, username])
458+
459+ const handleHeadlessConnect = useCallback(async (signer: string) => {
460+ try {
461+ await controller.connect({
462+ username: username.trim(),
463+ signer: signer as any,
464+ })
465+ } catch (error) {
466+ console.error('Connection failed:', error)
467+ }
468+ }, [controller, username])
469+
470+ return (
471+ <div className="space-y-4">
472+ <div>
473+ <input
474+ type="text"
475+ placeholder="Enter username"
476+ value={username}
477+ onChange={(e) => setUsername(e.target.value)}
478+ className="border p-2 rounded"
479+ />
480+ <button
481+ onClick={handleLookup}
482+ disabled={isLoading || !username.trim()}
483+ className="ml-2 px-4 py-2 bg-blue-500 text-white rounded disabled:opacity-50"
484+ >
485+ {isLoading ? 'Looking up...' : 'Lookup Username'}
486+ </button>
487+ </div>
488+
489+ {lookupResult && (
490+ <div className="border p-4 rounded">
491+ <h3 className="font-semibold">Username: {lookupResult.username}</h3>
492+ <p>Exists: {lookupResult.exists ? 'Yes' : 'No'}</p>
493+
494+ {lookupResult.exists && lookupResult.signers.length > 0 && (
495+ <div className="mt-2">
496+ <p>Available authentication methods:</p>
497+ <div className="flex flex-wrap gap-2 mt-2">
498+ {lookupResult.signers.map((signer: string) => (
499+ <button
500+ key={signer}
501+ onClick={() => handleHeadlessConnect(signer)}
502+ className="px-3 py-1 bg-green-500 text-white rounded text-sm"
503+ >
504+ Login with {signer}
505+ </button>
506+ ))}
507+ </div>
508+ </div>
509+ )}
510+
511+ {!lookupResult.exists && (
512+ <div className="mt-2">
513+ <p className="text-gray-600">Username is available for signup</p>
514+ <button
515+ onClick={() => handleHeadlessConnect('webauthn')}
516+ className="mt-2 px-3 py-1 bg-blue-500 text-white rounded text-sm"
517+ >
518+ Sign up with WebAuthn
519+ </button>
520+ </div>
521+ )}
522+ </div>
523+ )}
524+ </div>
525+ )
526+ }
527+ ` ` `
528+
529+ #### Lookup Response Format
530+
531+ The ` lookupUsername ` method returns an object with the following structure :
532+
533+ ` ` ` typescript
534+ interface HeadlessUsernameLookupResult {
535+ username: string; // The username that was looked up
536+ exists: boolean; // Whether the username exists
537+ signers: AuthOption[]; // Available authentication methods, e.g. ["webauthn", "google", "password"]
538+ }
539+ ` ` `
540+
541+ Available ` AuthOption ` values include :
542+ - ` "webauthn" ` - Passkey / WebAuthn authentication
543+ - ` "password" ` - Password - based authentication
544+ - ` "google" ` - Google OAuth
545+ - ` "discord" ` - Discord OAuth
546+ - ` "walletconnect" ` - WalletConnect
547+ - ` "metamask" ` - MetaMask wallet
548+ - ` "rabby" ` - Rabby wallet
549+ - ` "phantom-evm" ` - Phantom wallet (EVM )
550+
551+ ### 5. Add Components to Your App
429552
430553` ` ` typescript
431554import { StarknetProvider } from './context/StarknetProvider'
432555import { ConnectWallet } from './components/ConnectWallet'
433556import { TransferEth } from './components/TransferEth'
557+ import { UsernameLookup } from './components/UsernameLookup'
434558
435559function App() {
436560 return (
437561 <StarknetProvider>
438562 <ConnectWallet />
563+ <UsernameLookup />
439564 <TransferEth />
440565 </StarknetProvider>
441566 )
0 commit comments