> For the complete documentation index, see [llms.txt](https://docs.indicio.tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.indicio.tech/developer/mobile-solutions/mobile-sdk/events.md).

# Events

Events are handled as flows in Kotlin and can be retrieved from the agent.

{% hint style="info" %}
The examples of event flows below do not include the code needed to launch them in a background coroutine scope. You must add that code in your Kotlin code to take the handlers off of the main thread.
{% endhint %}

## Kotlin

{% code title="Kotlin" %}

```kotlin
val didExchangeEvents? = agent.events.getEventBus(DidExchangeEvents::class)
// or
val didExchangeEvents = agent.events.getDidExchangeEvents()?: throw Error("Events not initialized by agent")
```

{% endcode %}

The `getEventBus` function will attempt to retrieve the event bus class passed to it. This exists because custom event flows can be registered and stored in the `agent.events` eventManager object.

There are eight base flows for different actions that the Agent manages. Their functions are:

* `getDidExchangeEvents()`
* `getAgentEvents()`
* `getCredentialEvents`
* `getEventBusEvents()`
* `getMessageEvents()`
* `getProofEvents()`
* `getTrustPingEvents()`
* `getWebsocketEvents()`

All of the listed functions exist on the `events` property of the agent. The event bus events pertain to record updates. The message events pertain to all incoming messages regardless of type. Agent events are emitted to indicate the state (Start, Running, Stop) of the Agent.

Both the named functions and the `getEventBus` may return `null` if, for some reason, the event bus has not yet been registered to the agent's eventManager. The only way the named function would return `null` is if the Agent initializes with errors.

Once you have the events you can perform operations on them to filter for certain IDs or states in order to complete processes or inform the user when things are occurring.

{% hint style="warning" %}
Performing certain actions that wait for completion of a protocol inside of an event handler can cause a deadlock situation. It is not advised to wait for protocol completion inside a continuous event handler.
{% endhint %}

Example of what NOT to do:

{% code title="BAD example (Kotlin)" %}

```kotlin
// Example of what NOT to do
val didExchangeEvents = agent.events.getDidExchangeEvents()?: throw Error("Events not initialized by agent")

didExchangeEvents.events.onEach{
    // Causes deadlock because requestConnection will not return until the response message is processed
    // This can be avoided by calling this function in a separate thread 
    agent.didExchange.requestConnection(it.didExchangeRecord.id, it.outOfBandRecord.id)
}.collect()

// Auto accept should be used instead of trying to do this. This is an intentionally BAD example
```

{% endcode %}

If you need to wait for the agent to complete an action, you should wait for a specific event/state instead:

{% code title="Kotlin" %}

```kotlin
val didExchangeEvents = agent.events.getDidExchangeEvents()?: throw Error("Events not initialized by agent")
// Waits for the first didExchangeStateChangedEvent to be emitted that is in the completed state
didExchangeEvents.events.first{
   it.didExchangeRecord.state == DidExchangeState.Completed
}
// Additional attributes (such as ID) on the record can be used to wait for a specific record to reach a certain state
```

{% endcode %}

In Kotlin the events use flows; this allows the use of the Flow API on all events.

{% tabs %}
{% tab title="Swift (KMPNativeCoroutines)" %}
Swift uses KMPNativeCoroutines (<https://github.com/rickclephas/KMP-NativeCoroutines>) (1.0.0-ALPHA-23) as a dependency that allows the Kotlin flows to be turned into native Swift observables, AsyncSequence, and potentially more.

{% code title="Swift" %}

```swift
// Turns the didExchangeEvents into a swift asyncSequence
let credentialEvents = asyncSequence(for: agent.events.getCredentialEvents()!.events)
```

{% endcode %}
{% endtab %}

{% tab title="Swift / Objective-C (no KMPNativeCoroutines)" %}
Events are also wrapped with convenience methods so you can easily listen to events without a third party library or when using Objective-C:

* onDidExchangeStateChanged
* onCredentialStateChanged
* onTrustPingEvent
* onAgentEvent
* onRecordEvent
* onProofEvent
* onWebsocketEvent

Objective-C example:

{% code title="Objective-C" %}

```objectivec
void (^removeListener)(ProvenmobileKotlinCancellationException * _Nullable) =  
   [agent.events onDidExchangeStateChangedCallback:^(
      ProvenmobileDidExchangeStateChangedEvent *_Nonnull event
   ) {
      // Handle DidExchangeStateChangedEvent here
   }

// Remove listener when no longer needed
removeListener(nil);
```

{% endcode %}

Swift example:

{% code title="Swift" %}

```swift
let removeListener = agent.events.onDidExchangeStateChanged { event in
   // Handle DidExchangeStateChangedEvent here
}
// Remove listener when no longer needed
removeListener(nil)
```

{% endcode %}
{% endtab %}

{% tab title="React Native" %}
Events in React Native are handled differently than in Kotlin and Swift. The format of events on the Agent is similar but is done in a simpler manner.

Instead of getting an events object, you register a handler function that will be called on all events of the specified type the handler is registered to.

{% code title="TypeScript" %}

```typescript
// Registers a handler that is called on all Did Exchange events
const didExchangeRemove = agent.events.registerDidExchangeHandler(
    event => {
      if (event.didExchangeRecord.state === DidExchangeState.COMPLETED) {
        console.log(
          'didExchange completed',
          event.didExchangeRecord.theirLabel,
        )
      }
    })

// Unregister the handler when no longer needed
didExchangeRemove()
```

{% endcode %}

The return of registering a handler is a function that will remove or unregister the handler. Calling the removal function will stop the given handler from being called on any future events.

Note: Registered events will not persist after the app has been closed.
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.indicio.tech/developer/mobile-solutions/mobile-sdk/events.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
