> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ditto.live/llms.txt
> Use this file to discover all available pages before exploring further.

# Using Mesh Presence

> Presence is the representation of all devices present in the Ditto mesh. You can read more about presence in the [Mesh Networking](/key-concepts/mesh-networking#presence-graph) section.

To get realtime updates about changes to presence data, use the Presence API. This article includes instructions on how to implement Ditto's Presence APIs to enable the following end-user functionality for network monitoring and management within your app:

* Setting and updating peer-specific information, such as name, role, and location.
* Viewing information about other peers currently connected in the mesh.

# Accessing Presence APIs

To access API methods for mesh presence functionality, call the the `presence` namespace on the root `Ditto` object:

<CodeGroup>
  ```swift Swift theme={null}

  ditto.presence
  ```

  ```kotlin Kotlin theme={null}
  ditto.presence
  ```

  ```javascript JS theme={null}
  ditto.presence
  ```

  ```typescript TS theme={null}
  import { Ditto, Presence } from '@dittolive/ditto'

  const presence: Presence = ditto.presence
  ```

  ```java Java theme={null}
  ditto.getPresence();
  ```

  ```csharp C# theme={null}
  Ditto.Presence
  ```

  ```cpp C++ theme={null}
  ditto.get_presence()
  ```

  ```rust Rust theme={null}
  ditto.presence()
  ```

  ```dart Dart theme={null}
  ditto.presence
  ```

  ```go Go theme={null}
  dit.Presence()
  ```
</CodeGroup>

# Presence Graph

Once discovered in the mesh, peers automatically establish a *presence graph* by advertising their device presence within the mesh and forming network connections with other connected peers.

The presence graph is a data structure representing the current state of the mesh from a specific peer's point of view.

You can integrate the presence graph into your app to enable end-user functionality like network monitoring, management, and transport optimization. For example, once implemented, end users can input personal information, such as their name, and inspect remote peers connected within the mesh. For more information, see <a href="https://github.com/getditto/DittoSwiftTools" target="_blank">DittoSwiftTools</a> on GitHub.

## Accessing Presence Graphs

To view your current presence graph:

<CodeGroup>
  ```swift Swift theme={null}

  let presenceGraph = ditto.presence.graph
  ```

  ```kotlin Kotlin theme={null}
  val presenceGraph = ditto.presence.graph
  ```

  ```javascript JS theme={null}
  const presenceGraph = ditto.presence.graph
  ```

  ```typescript TS theme={null}
  import { Ditto, PresenceGraph } from '@dittolive/ditto'

  const presenceGraph: PresenceGraph = ditto.presence.graph
  ```

  ```java Java theme={null}
  DittoPresenceGraph graph = ditto.getPresence().getGraph();
  ```

  ```csharp C# theme={null}
  var PresenceGraph = Ditto.Presence.Graph
  ```

  ```cpp C++ theme={null}
  auto presenceGraph = ditto.get_presence().graph()
  ```

  ```rust Rust theme={null}
  let presenceGraph = ditto.presence().graph()
  ```

  ```dart Dart theme={null}
  final presenceGraph = ditto.presence.graph;
  ```

  ```go Go theme={null}
  presenceGraph := dit.Presence().Graph()
  ```
</CodeGroup>

Once invoked, Ditto returns the following object, allowing you to perform actions like displaying the status of connected peers and managing network resources:

<CodeGroup>
  ```json theme={null}
  {
    localPeer: Peer;
    remotePeers: Peer[];
  }
  ```
</CodeGroup>

The `localPeer` is the metadata set by the end user within your app. The `remotePeers` property provides an `array` of the other client devices connected to the mesh. (See [End-User Defined Metadata](#end-user-defined-peer-metadata) for more information.)

## Observing Presence Graph Modifications

To monitor and handle changes observed to the presence graph, call the change handler with the updated graph object as follows:

<Warning>
  Make sure the observer response object remains in memory during runtime; otherwise, Ditto removes it during the periodic garbage collection process running in the background, resulting in the change handler no longer being triggered.
</Warning>

<CodeGroup>
  ```swift Swift theme={null}

  let presenceObserver = ditto.presence.observe { presenceGraph in
      // observe changes to the presence graph
  }
  ```

  ```kotlin Kotlin theme={null}
  val presenceObserver = ditto.presence.observe { graph ->
      // observe changes to the presence graph
  }
  ```

  ```javascript JS theme={null}
  const presenceObserver = ditto.presence.observe((presenceGraph) => {
      // observe changes to the presence graph
  })
  ```

  ```typescript TS theme={null}
  import { Ditto, PresenceGraph, PresenceObserver } from '@dittolive/ditto'

  const presenceObserver: PresenceObserver = ditto.presence.observe((presenceGraph: PresenceGraph) => {
    // observe changes to the presence graph
  })
  ```

  ```java Java theme={null}
  DittoPresenceObserver presenceObserver = ditto.getPresence().observe(graph -> {
      // observe changes to the presence graph
  });
  ```

  ```csharp C# theme={null}
  var presenceObserver = Ditto.Presence.Observe((DittoPresenceGraph graph) =>
  {
      // Observe changes to the presence graph
  });
  ```

  ```cpp C++ theme={null}
  auto presenceObserver = ditto.get_presence().observe([&](PresenceGraph graph) {
      // observe changes to the presence graph
  });
  ```

  ```rust Rust theme={null}
  let presence_observer = ditto.presence().register_observer(move |_graph| {
      // observe changes to the presence graph
  })?;
  ```

  ```dart Dart theme={null}
  final presenceObserver = ditto.presence.observe((graph) {
    // observe changes to the presence graph
  });
  ```

  ```go Go theme={null}
  presenceObserver := dit.Presence().Observe(func(graph *ditto.PresenceGraph) {
      // observe changes to the presence graph
  })
  ```
</CodeGroup>

# Peer Key Identifier

Once discovered in the mesh, each peer device running Ditto is automatically assigned a *peer key*.

## Reading Peer Keys

View your local device's peer key or the peer key identifying a specific remote device:

* To retrieve the peer key for the current peer:

<CodeGroup>
  ```swift Swift theme={null}

  ditto.presence.graph.localPeer.peerKeyString
  ```

  ```kotlin Kotlin theme={null}
  ditto.presence.graph.localPeer.peerKeyString
  ```

  ```javascript JS theme={null}
  ditto.presence.graph.localPeer.peerKeyString
  ```

  ```typescript TS theme={null}
  import { Ditto } from '@dittolive/ditto'

  const peerKeyString: string = ditto.presence.graph.localPeer.peerKeyString
  ```

  ```java Java theme={null}
  ditto.getPresence().getGraph().getLocalPeer().getPeerKey()
  ```

  ```csharp C# theme={null}
  Ditto.Presence.Graph.LocalPeer.PeerKeyString
  ```

  ```cpp C++ theme={null}
  ditto.get_presence().graph().local_peer.peer_key_string
  ```

  ```rust Rust theme={null}
  ditto.presence().graph().local_peer.peer_key
  ```

  ```dart Dart theme={null}
  ditto.presence.graph.localPeer.peerKeyString
  ```

  ```go Go theme={null}
  dit.Presence().Graph().LocalPeer.PeerKeyString
  ```
</CodeGroup>

* To retrieve the peer key for a remote peer:

<CodeGroup>
  ```swift Swift theme={null}

  let remotePeers = presenceGraph.remotePeers
  let firstPeer = remotePeers.first!

  let peerkeyString = firstPeer.peerKeyString
  ```

  ```kotlin Kotlin theme={null}
  val remotePeers = ditto.presence.graph.remotePeers
  val firstPeer = remotePeers.first()

  val peerKeyString = firstPeer.peerKeyString
  ```

  ```javascript JS theme={null}
  const remotePeers = ditto.presence.graph.remotePeers
  const firstPeer = remotePeers[0]

  const peerkeyString = firstPeer.peerKeyString
  ```

  ```typescript TS theme={null}
  import { Ditto, Peer } from '@dittolive/ditto'

  const remotePeers: Peer[] = ditto.presence.graph.remotePeers
  const firstPeer: Peer = remotePeers[0]

  const peerKeyString: string = firstPeer.peerKeyString
  ```

  ```java Java theme={null}
  List<DittoPeer> remotePeers = ditto.getPresence().getGraph().getRemotePeers();
  DittoPeer firstPeer = remotePeers.get(0);

  String peerKey = firstPeer.getPeerKey();
  ```

  ```csharp C# theme={null}
  DittoPeer remotePeers = ditto.presence.graph.remotePeers
  const firstPeer = remotePeers[0]

  const peerkeyString = firstPeer.peerKeyString
  ```

  ```cpp C++ theme={null}
  auto remotePeers = ditto.get_presence().graph().remote_peers;
  auto firstPeer = remotePeers[0];

  auto peerkeyString = firstPeer.peer_key_string;
  ```

  ```rust Rust theme={null}
  let remote_peers = ditto.presence().graph().remote_peers;
  let first_peer = &remote_peers[0];

  let peer_key = &first_peer.peer_key;
  ```

  ```dart Dart theme={null}
  final remotePeers = ditto.presence.graph.remotePeers;
  final firstPeer = remotePeers[0];
  final peerKeyString = firstPeer.peerKeyString;
  ```

  ```go Go theme={null}
  remotePeers := dit.Presence().Graph().RemotePeers
  firstPeer := remotePeers[0]
  peerKeyString := firstPeer.PeerKeyString
  ```
</CodeGroup>

# End-User Defined Peer Metadata

Using the peer-metadata property, you can provide each peer connected within the mesh the ability to set and view information about themselves or read information defined by other peers within the mesh.

<Warning>
  Data added to the peer metadata object is shared during the connection handshake. Large data payloads may impact performance on low-bandwidth connections, such as BLE.
</Warning>

The following table provides an overview of key considerations to know before setting peer metadata, as well as Ditto's recommended best practices to ensure optimal mesh performance and avoid potential issues:

| **Consideration**                                                                                                                                                                                                                     | **Best Practice**                                                                                                                                                                                                                                            |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Peer metadata syncs across the mesh with each new connection. Therefore, sharing large data over low-bandwidth transports, such as Bluetooth Low Energy (LE), and low-quality connections may slow or disrupt the connection process. | Keep the size of peer metadata to a minimum, especially when syncing over Bluetooth LE or similar low-bandwidth transports. This is because peer metadata exceeding 128 KB, the maximum limit, results in the operation failing and Ditto throwing an error. |
| Peer metadata is visible to all peers connected in the mesh.                                                                                                                                                                          | Include only non-sensitive information in peer metadata.                                                                                                                                                                                                     |

## Setting Local Peer Metadata

To implement functionality providing end users the ability to define metadata, call the `setPeerMetadata` API method as follows:

<CodeGroup>
  ```swift Swift theme={null}

  // Setting via Object
  try ditto.presence.setPeerMetadata(["location": "inside"])

  // Setting via JSON String
  let jsonData = "{location:\"inside\"}".data(using: .utf8)!
  try ditto.presence.setPeerMetadataJSONData(jsonData)
  ```

  ```kotlin Kotlin theme={null}
  // Setting via Object
  ditto.presence.peerMetadata = mapOf("number" to 1)

  // Setting via JSON String
  ditto.presence.peerMetadataJsonString =
      """
      {"location":"inside"}
      """.trimIndent()
  ```

  ```javascript JS theme={null}
  // Setting via Object
  await ditto.presence.setPeerMetadata({ location: "inside" })

  // Setting via JSON String
  await ditto.presence.setPeerMetadataJSONString("{location:\"inside\"}")
  ```

  ```typescript TS theme={null}
  import { Ditto } from '@dittolive/ditto'

  interface PeerMetadata {
    location: string
  }

  // Setting via Object
  const metadata: PeerMetadata = { location: "inside" }
  await ditto.presence.setPeerMetadata(metadata)

  // Setting via JSON String
  await ditto.presence.setPeerMetadataJSONString('{"location":"inside"}')
  ```

  ```java Java theme={null}
  import static com.ditto.java.serialization.DittoCborSerializable.buildDictionary;

  // Setting via DittoCborSerializable.Dictionary
  ditto.getPresence().setPeerMetadata(
      buildDictionary().put("number", 1).build()
  );

  // Setting via JSON String
  ditto.getPresence().setPeerMetadataJsonString("{\"location\":\"inside\"}");
  ```

  ```csharp C# theme={null}
  Ditto.Presence.SetPeerMetadata(new Dictionary<string, object>()  { { "location", "inside" } });
  ```

  ```cpp C++ theme={null}
  nlohmann::json metadata = {
      {"location", "inside"}
  };

  ditto.get_presence().set_peer_metadata(metadata);
  ```

  ```rust Rust theme={null}
  let metadata = json!({
      "location": "inside",
  });
  ditto.presence().set_peer_metadata(&metadata)?;
  ```

  ```dart Dart theme={null}
  // Setting via Object
  ditto.presence.peerMetadata = {"location": "inside"};

  // Setting via JSON String
  ditto.presence.peerMetadataJsonString = '{"location": "inside"}';
  ```

  ```go Go theme={null}
  // Setting via object
  var metadata map[string]any
  metadata["location"] = "inside"
  dit.Presence().SetPeerMetadata(metadata)

  // Setting via JSON string
  dit.Presence().SetPeerMetadataJSONData([]byte("{\"location\": \"inside\"}"))
  ```
</CodeGroup>

## Reading Local Peer Metadata

Once set, inspect the metadata:

<CodeGroup>
  ```swift Swift theme={null}

  // Reading from the presence namespace
  ditto.presence.peerMetadata

  // Reading from the presence graph
  ditto.presence.graph.localPeer.peerMetadata
  ```

  ```kotlin Kotlin theme={null}
  // Reading from the presence namespace
  ditto.presence.peerMetadata

  // Reading from the presence graph
  ditto.presence.graph.localPeer.peerMetadata
  ```

  ```javascript JS theme={null}
  // Reading from the presence namespace
  ditto.presence.peerMetadata

  // Reading from the presence graph
  ditto.presence.graph.localPeer.peerMetadata
  ```

  ```typescript TS theme={null}
  import { Ditto } from '@dittolive/ditto'

  // Reading from the presence namespace
  const metadata: Record<string, unknown> = ditto.presence.peerMetadata

  // Reading from the presence graph
  const localPeerMetadata: Record<string, unknown> = ditto.presence.graph.localPeer.peerMetadata
  ```

  ```java Java theme={null}
  import com.ditto.java.serialization.DittoCborSerializable;

  // Reading from the presence namespace
  DittoCborSerializable.Dictionary metadata = ditto.getPresence().getPeerMetadata();

  // Reading from the presence graph
  DittoCborSerializable.Dictionary metadata2 = ditto.getPresence().getGraph().getLocalPeer().getPeerMetadata();
  ```

  ```csharp C# theme={null}
  // Reading from the presence namespace
  Ditto.Presence.PeerMetadata;

  // Reading from the presence graph
  Ditto.Presence.Graph.LocalPeer.PeerMetadata;
  ```

  ```cpp C++ theme={null}
  // Reading from the presence namespace
  ditto.get_presence().peer_metadata()

  // Reading from the presence graph
  ditto.get_presence().graph().local_peer.peer_metadata
  ```

  ```rust Rust theme={null}
  // Reading from the presence namespace
  ditto.presence().peer_metadata()

  // Reading from the presence graph
  ditto.presence().graph().local_peer.peer_metadata
  ```

  ```dart Dart theme={null}
  // Reading from the presence namespace
  ditto.presence.peerMetadata

  // Reading from the presence graph
  ditto.presence.graph.localPeer.peerMetadata
  ```

  ```go Go theme={null}
  // Reading from the presence namespace
  dit.Presence().GetPeerMetadata()

  // Reading from the presence graph
  dit.Presence().Graph().LocalPeer.PeerMetadata
  ```
</CodeGroup>

## Reading Remote Peer Metadata

To inspect the metadata set by all other peers in the mesh:

<CodeGroup>
  ```swift Swift theme={null}

  let remotePeers = ditto.presence.graph.remotePeers
  let firstPeer = remotePeers.first!

  let peerMetadata = firstPeer.peerMetadata
  ```

  ```kotlin Kotlin theme={null}
  val remotePeers = ditto.presence.graph.remotePeers
  val firstPeer = remotePeers.first()

  val peerMetadata = firstPeer.peerMetadata
  ```

  ```javascript JS theme={null}
  const remotePeers = ditto.presence.graph.remotePeers
  const firstPeer = remotePeers[0]

  const peerMetadata = firstPeer.peerMetadata
  ```

  ```typescript TS theme={null}
  import { Ditto, Peer } from '@dittolive/ditto'

  const remotePeers: Peer[] = ditto.presence.graph.remotePeers
  const firstPeer: Peer = remotePeers[0]

  const peerMetadata: Record<string, unknown> = firstPeer.peerMetadata
  ```

  ```java Java theme={null}
  import com.ditto.java.serialization.DittoCborSerializable;

  List<DittoPeer> remotePeers = ditto.getPresence().getGraph().getRemotePeers();
  DittoPeer firstPeer = remotePeers.get(0);

  DittoCborSerializable.Dictionary metadata = firstPeer.getPeerMetadata();
  ```

  ```csharp C# theme={null}
  var RemotePeers = Ditto.Presence.Graph.RemotePeers.PeerMetadata;
  var FirstPeer = RemotePeers[0];

  var PeerMetadata = FirstPeer.PeerMetadata;
  ```

  ```cpp C++ theme={null}
  auto remotePeers = ditto.get_presence().graph().remote_peers;
  auto firstPeer = remotePeers[0];

  auto peerMetadata = firstPeer.peer_metadata();
  ```

  ```rust Rust theme={null}
  let remote_peers = ditto.presence().graph().remote_peers;
  let first_peer = &remote_peers[0];

  let peer_metadata = &first_peer.peer_metadata;
  ```

  ```dart Dart theme={null}
  final remotePeers = ditto.presence.graph.remotePeers;
  final firstPeer = remotePeers[0];
  final metadata = firstPeer.peerMetadata;
  ```

  ```go Go theme={null}
  remotePeers := dit.Presence().Graph().RemotePeers
  firstPeer := remotePeers[0]
  metadata := firstPeer.PeerMetadata
  ```
</CodeGroup>

## Identity Server Metadata

Identity server metadata is application information that is set when the user is authenticating. As part of the authentication process the application developer can provide information about the peer that is added to the user's peer object and shared with other peers in the mesh.

The identity server metadata is signed by the identity server and validated by all peers reading to prevent spoofing of the information.

### Setting Identity Server Metadata

The identity server metadata is set during the See [End-User Access>Setting Identity Server User Metadata](../auth-and-authorization/data-authorization) for specifics.

### Reading Local Peer Identity Server Metadata

To inspect the identity server metadata of the local peer doing the following:

<CodeGroup>
  ```swift Swift theme={null}

  // Reading from the presence namespace
  ditto.presence.identityServiceMetadata

  // Reading from the presence graph
  ditto.presence.graph.localPeer.identityServiceMetadata
  ```

  ```kotlin Kotlin theme={null}
  // Reading from the presence namespace
  ditto.presence.identityServiceMetadata

  // Reading from the presence graph
  ditto.presence.graph.localPeer.identityServiceMetadata
  ```

  ```javascript JS theme={null}
  // Reading from the presence namespace
  ditto.presence.identityServiceMetadata

  // Reading from the presence graph
  ditto.presence.graph.localPeer.identityServiceMetadata
  ```

  ```typescript TS theme={null}
  import { Ditto } from '@dittolive/ditto'

  // Reading from the presence namespace
  const identityMetadata: Record<string, unknown> = ditto.presence.identityServiceMetadata

  // Reading from the presence graph
  const localIdentityMetadata: Record<string, unknown> = ditto.presence.graph.localPeer.identityServiceMetadata
  ```

  ```java Java theme={null}
  import com.ditto.java.serialization.DittoCborSerializable;

  // Reading from the presence namespace
  DittoCborSerializable.Dictionary metadata = ditto.getPresence().getIdentityServiceMetadata();

  // Reading from the presence graph
  DittoCborSerializable.Dictionary metadata2 = ditto.getPresence().getGraph().getLocalPeer().getIdentityServiceMetadata();
  ```

  ```csharp C# theme={null}
  // Reading from the presence namespace
  Ditto.Presence.IdentityServiceMetadata;

  // Reading from the presence graph
  Ditto.Presence.Graph.LocalPeer.IdentityServiceMetadata;
  ```

  ```cpp C++ theme={null}
  // Reading from the presence namespace
  ditto.get_presence().identity_service_metadata()

  // Reading from the presence graph
  ditto.get_presence().graph().local_peer.identity_service_metadata
  ```

  ```rust Rust theme={null}
  // Reading from the presence namespace
  ditto.presence().identity_service_metadata()

  // Reading from the presence graph
  ditto.presence().graph().local_peer.identity_service_metadata
  ```

  ```dart Dart theme={null}
  ditto.presence.graph.localPeer.identityServiceMetadata
  // Coming Soon
  ```

  ```go Go theme={null}
  dit.Presence().Graph().LocalPeer.IdentityServiceMetadata
  ```
</CodeGroup>

## Reading Remote Peer Identity Server Metadata

To inspect the identity server metadata set by other peers connected within the mesh:

<CodeGroup>
  ```swift Swift theme={null}

  let remotePeers = ditto.presence.graph.remotePeers
  let firstPeer = remotePeers.first!

  let peerMetadata = firstPeer.identityServiceMetadata
  ```

  ```kotlin Kotlin theme={null}
  val remotePeers = ditto.presence.graph.remotePeers
  val firstPeer = remotePeers.first()

  val peerMetadata = firstPeer.identityServiceMetadata
  ```

  ```javascript JS theme={null}
  const remotePeers = ditto.presence.graph.remotePeers
  const firstPeer = remotePeers[0]

  const peerMetadata = firstPeer.identityServiceMetadata
  ```

  ```typescript TS theme={null}
  import { Ditto, Peer } from '@dittolive/ditto'

  const remotePeers: Peer[] = ditto.presence.graph.remotePeers
  const firstPeer: Peer = remotePeers[0]

  const identityServiceMetadata: Record<string, unknown> = firstPeer.identityServiceMetadata
  ```

  ```java Java theme={null}
  import com.ditto.java.serialization.DittoCborSerializable;

  List<DittoPeer> remotePeers = ditto.getPresence().getGraph().getRemotePeers();
  DittoPeer firstPeer = remotePeers.get(0);

  DittoCborSerializable.Dictionary metadata = firstPeer.getIdentityServiceMetadata();
  ```

  ```csharp C# theme={null}
  var RemotePeers = Ditto.Presence.Graph.RemotePeers.PeerMetadata;
  var FirstPeer = RemotePeers[0];

  var PeerMetadata = FirstPeer.IdentityServiceMetadata;
  ```

  ```cpp C++ theme={null}
  auto remotePeers = ditto.get_presence().graph().remote_peers;
  auto firstPeer = remotePeers[0];

  auto peerMetadata = firstPeer.identity_service_metadata();
  ```

  ```rust Rust theme={null}
  let remote_peers = ditto.presence().graph().remote_peers;
  let first_peer = &remote_peers[0];

  let peer_metadata = &first_peer.identity_service_metadata;
  ```

  ```dart Dart theme={null}
  final remotePeers = ditto.presence.graph.remotePeers;
  final firstPeer = remotePeers[0];

  final peerMetadata = firstPeer.identityServiceMetadata;
  ```

  ```go Go theme={null}
  remotePeers := dit.Presence().Graph().RemotePeers
  firstPeer := remotePeers[0]
  peerMetadata := firstPeer.IdentityServiceMetadata
  ```
</CodeGroup>

***
