Skip to content

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')
}
Example:
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.
})
Use Cases:
  • 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
    }>
  }
}
Example:
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')
})
Use Cases:
  • 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
Example:
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)
})
Use Cases:
  • 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')
})
Use Cases:
  • 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
    }
  }
}
Example:
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,
  })
})
Use Cases:
  • 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
}
Example:
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,
  })
})
Use Cases:
  • 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
Example:
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()
})
Use Cases:
  • 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
Payload:
type SignedMessagePayload = {
  message: string | Uint8Array  // The message that was signed
  signature: string              // The resulting signature (hex string)
}
Example:
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!')
})
Use Cases:
  • 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

  1. Check listener registration: Ensure listeners are registered before triggering actions
  2. Verify imports: Make sure you're importing from @openfort/openfort-js
  3. Check cleanup: Ensure you're not removing listeners prematurely

Memory Leaks

If you notice memory issues:

  1. Always clean up listeners in useEffect cleanup or componentWillUnmount
  2. Use removeAllListeners for the specific event, not globally
  3. Consider using weak references for long-lived listeners