Skip to content

Commit 3d0d459

Browse files
tarrencevgithub-actions[bot]kronosapiens
authored
docs: Update documentation for controller PR #2400 (#202)
Updates documentation to reflect changes made in: Add headless username lookup and auto-signup connect Related controller PR: cartridge-gg/controller#2400 Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Daniel Kronovet <kronovet@gmail.com>
1 parent a7db734 commit 3d0d459

File tree

1 file changed

+126
-1
lines changed

1 file changed

+126
-1
lines changed

src/pages/controller/examples/react.md

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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
431554
import { StarknetProvider } from './context/StarknetProvider'
432555
import { ConnectWallet } from './components/ConnectWallet'
433556
import { TransferEth } from './components/TransferEth'
557+
import { UsernameLookup } from './components/UsernameLookup'
434558
435559
function App() {
436560
return (
437561
<StarknetProvider>
438562
<ConnectWallet />
563+
<UsernameLookup />
439564
<TransferEth />
440565
</StarknetProvider>
441566
)

0 commit comments

Comments
 (0)