Openfort SDK Events
The Openfort SDK provides a comprehensive event system that allows you to monitor and respond to various authentication, wallet, and UI lifecycle events in your application.
Event System Overview
The SDK uses a typed event emitter that you can access via the openfortEvents
export. All events are strongly typed and provide detailed payload information.
import { openfortEvents, OpenfortEvents } from '@openfort/openfort-js'
// Subscribe to an event
openfortEvents.on(OpenfortEvents.ON_AUTH_SUCCESS, (authResponse) => {
console.log('User authenticated:', authResponse.player.id)
})
// Remove a specific listener
const handler = (authResponse) => console.log('Auth success')
openfortEvents.on(OpenfortEvents.ON_AUTH_SUCCESS, handler)
openfortEvents.off(OpenfortEvents.ON_AUTH_SUCCESS, handler)
// Remove all listeners for an event
openfortEvents.removeAllListeners(OpenfortEvents.ON_AUTH_SUCCESS)
Authentication Events
ON_AUTH_INIT
Called when an authentication process begins, before the user completes authentication.
Payload:type AuthInitPayload = {
method: 'email' | 'oauth' | 'siwe' | 'idToken' | 'guest'
provider?: string // OAuth provider name (e.g., 'google', 'discord')
}
openfortEvents.on(OpenfortEvents.ON_AUTH_INIT, (payload) => {
console.log(`Authentication started with ${payload.method}`)
if (payload.provider) {
console.log(`Using provider: ${payload.provider}`)
}
// Show loading indicator, track analytics, etc.
})
- Display loading states
- Track authentication attempts in analytics
- Log authentication method usage
ON_AUTH_SUCCESS
Called after the user successfully authenticates and receives access tokens.
Payload:type AuthResponse = {
player: AuthPlayerResponse
token: string
refreshToken: string
}
type AuthPlayerResponse = {
id: string
object: 'player'
createdAt: number
linkedAccounts: LinkedAccountResponse[]
player?: {
id: string
name: string
description?: string
metadata?: Record<string, any>
accounts?: Array<{
id: string
address: string
chainId: number
// ... more account fields
}>
}
}
openfortEvents.on(OpenfortEvents.ON_AUTH_SUCCESS, (authResponse) => {
console.log('User authenticated successfully!')
console.log('Player ID:', authResponse.player.id)
console.log('Linked accounts:', authResponse.player.linkedAccounts)
// Navigate to dashboard, update UI, etc.
router.push('/dashboard')
})
- Navigate user to authenticated area
- Store user preferences
- Initialize user-specific features
- Track successful authentication in analytics
ON_AUTH_FAILURE
Called when authentication fails due to an error.
Payload:Error // Standard JavaScript Error object
openfortEvents.on(OpenfortEvents.ON_AUTH_FAILURE, (error) => {
console.error('Authentication failed:', error.message)
// Show error message to user
toast.error(`Failed to authenticate: ${error.message}`)
// Track error in monitoring
Sentry.captureException(error)
})
- Display error messages to users
- Log authentication errors
- Retry authentication logic
- Error tracking and monitoring
ON_LOGOUT
Called after the user successfully logs out.
Payload: None
Example:openfortEvents.on(OpenfortEvents.ON_LOGOUT, () => {
console.log('User logged out')
// Clear local state, navigate to login, etc.
localStorage.clear()
router.push('/login')
})
- Clear local application state
- Navigate to login page
- Reset UI components
- Clear sensitive data from memory
Wallet Events
ON_EMBEDDED_WALLET_CREATED
Called after a new embedded wallet is created for the user.
Payload:type EmbeddedAccount = {
id: string
user: string
address: string
chainId?: number
chainType: 'EVM' | 'SVM'
accountType: 'Externally Owned Account' | 'Smart Account'
ownerAddress?: string
implementationType?: string
factoryAddress?: string
salt?: string
createdAt?: number
recoveryMethod?: 'password' | 'automatic' | 'passkey'
recoveryMethodDetails?: {
passkeyId?: string
passkeyEnv?: {
name?: string
os?: string
osVersion?: string
device?: string
}
}
}
openfortEvents.on(OpenfortEvents.ON_EMBEDDED_WALLET_CREATED, (wallet) => {
console.log('New wallet created!')
console.log('Address:', wallet.address)
console.log('Chain ID:', wallet.chainId)
console.log('Account type:', wallet.accountType)
console.log('Recovery method:', wallet.recoveryMethod)
// Display wallet address to user
setWalletAddress(wallet.address)
// Track wallet creation
analytics.track('wallet_created', {
chainType: wallet.chainType,
accountType: wallet.accountType,
})
})
- Display new wallet information
- Store wallet address in UI state
- Track wallet creation metrics
- Initialize wallet-dependent features
ON_EMBEDDED_WALLET_RECOVERED
Called when an existing embedded wallet is recovered.
Payload:type EmbeddedAccount = {
// Same structure as ON_EMBEDDED_WALLET_CREATED
}
openfortEvents.on(OpenfortEvents.ON_EMBEDDED_WALLET_RECOVERED, (wallet) => {
console.log('Wallet recovered!')
console.log('Address:', wallet.address)
console.log('Recovery method used:', wallet.recoveryMethod)
// Update UI with recovered wallet
setWalletAddress(wallet.address)
// Track recovery
analytics.track('wallet_recovered', {
recoveryMethod: wallet.recoveryMethod,
})
})
- Display recovered wallet information
- Track successful wallet recovery
- Verify recovery method
- Resume wallet operations
ON_SWITCH_ACCOUNT
Called when switching between different accounts or chains.
Payload:string // The new account address
openfortEvents.on(OpenfortEvents.ON_SWITCH_ACCOUNT, (address) => {
console.log('Switched to account:', address)
// Update UI with new account
setCurrentAccount(address)
// Refresh account balance
fetchBalance(address)
// Update chain-specific components
updateChainInfo()
})
- Update UI when user switches accounts
- Refresh account-specific data
- Update balance displays
- Sync with blockchain state
ON_SIGNED_MESSAGE
Called whenever the wallet signs a message. This includes:
- Personal message signing (
signMessage
) - Typed data signing (
signTypedData
/ EIP-712) - Transaction signatures
- Session key signatures
- Internal signing operations
type SignedMessagePayload = {
message: string | Uint8Array // The message that was signed
signature: string // The resulting signature (hex string)
}
openfortEvents.on(OpenfortEvents.ON_SIGNED_MESSAGE, (payload) => {
console.log('Message signed!')
console.log('Message:', payload.message)
console.log('Signature:', payload.signature)
// Track signing activity
analytics.track('message_signed', {
messageLength: typeof payload.message === 'string'
? payload.message.length
: payload.message.length,
})
// Store signature for later use
saveSignature(payload.signature)
// Show success notification
toast.success('Message signed successfully!')
})
- Track all signing operations
- Audit trail for signatures
- Display signing confirmations
- Monitor transaction signing
- Debug signing issues
- Implement custom signing workflows
Note: This event is emitted for ALL signing operations, including:
- Manual
openfort.signMessage()
calls - EIP-712 typed data signing
- Smart account user operation signatures
- EOA transaction signatures
- Session key registration/revocation signatures
TypeScript Types
All events are fully typed. Import the types you need:
import type {
OpenfortEvents,
OpenfortEventMap,
AuthInitPayload,
AuthResponse,
EmbeddedAccount,
SignedMessagePayload,
} from '@openfort/openfort-js'
The OpenfortEventMap
provides the complete type mapping:
interface OpenfortEventMap {
[OpenfortEvents.ON_AUTH_INIT]: [AuthInitPayload]
[OpenfortEvents.ON_AUTH_SUCCESS]: [AuthResponse]
[OpenfortEvents.ON_AUTH_FAILURE]: [Error]
[OpenfortEvents.ON_LOGOUT]: []
[OpenfortEvents.ON_SWITCH_ACCOUNT]: [string]
[OpenfortEvents.ON_SIGNED_MESSAGE]: [SignedMessagePayload]
[OpenfortEvents.ON_EMBEDDED_WALLET_CREATED]: [EmbeddedAccount]
[OpenfortEvents.ON_EMBEDDED_WALLET_RECOVERED]: [EmbeddedAccount]
}
Best Practices
1. Always Clean Up Listeners
Remove event listeners when components unmount to prevent memory leaks:
useEffect(() => {
const handler = (data) => console.log(data)
openfortEvents.on(OpenfortEvents.ON_AUTH_SUCCESS, handler)
return () => {
openfortEvents.off(OpenfortEvents.ON_AUTH_SUCCESS, handler)
}
}, [])
2. Handle Errors Gracefully
Always handle the ON_AUTH_FAILURE
event to provide user feedback:
openfortEvents.on(OpenfortEvents.ON_AUTH_FAILURE, (error) => {
// Show user-friendly error message
toast.error(getUserFriendlyError(error))
// Log for debugging
console.error('Auth error:', error)
// Track in error monitoring
Sentry.captureException(error)
})
3. Use Events for Analytics
Events are perfect for tracking user behavior:
openfortEvents.on(OpenfortEvents.ON_AUTH_SUCCESS, (auth) => {
analytics.track('user_authenticated', {
player_id: auth.player.id,
linked_accounts: auth.player.linkedAccounts.length,
})
})
openfortEvents.on(OpenfortEvents.ON_SIGNED_MESSAGE, () => {
analytics.track('message_signed')
})
4. Avoid Heavy Operations in Event Handlers
Keep event handlers lightweight and asynchronous when needed:
openfortEvents.on(OpenfortEvents.ON_AUTH_SUCCESS, async (auth) => {
// Good: Non-blocking UI update
setUser(auth.player)
// Good: Async heavy operation doesn't block
fetchUserData(auth.player.id).catch(console.error)
})
5. Type Your Event Handlers
Use proper TypeScript types for type safety:
import type { AuthResponse, EmbeddedAccount } from '@openfort/openfort-js'
const handleAuthSuccess = (auth: AuthResponse) => {
console.log(auth.player.id) // Fully typed!
}
const handleWalletCreated = (wallet: EmbeddedAccount) => {
console.log(wallet.address) // Fully typed!
}
openfortEvents.on(OpenfortEvents.ON_AUTH_SUCCESS, handleAuthSuccess)
openfortEvents.on(OpenfortEvents.ON_EMBEDDED_WALLET_CREATED, handleWalletCreated)
Troubleshooting
Events Not Firing
- Check listener registration: Ensure listeners are registered before triggering actions
- Verify imports: Make sure you're importing from
@openfort/openfort-js
- Check cleanup: Ensure you're not removing listeners prematurely
Memory Leaks
If you notice memory issues:
- Always clean up listeners in useEffect cleanup or componentWillUnmount
- Use
removeAllListeners
for the specific event, not globally - Consider using weak references for long-lived listeners