# Usage

### Setting Up

The `Discv5Protocol` class exposes functions for interacting with the Node Discovery Protocol V5. Start by creating an instance of `Discv5Protocol`:

```csharp
using Lantern.Discv5.WireProtocol;

string[] bootstrapEnrs = new[]
{
  "enr:-Ku4QImhMc1z8yCiNJ1TyUxdcfNucje3BGwEHzodEZUan8PherEo4sF7pPHPSIB1NNuSg5fZy7qFsjmUKs2ea1Whi0EBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQOVphkDqal4QzPMksc5wnpuC3gvSC8AfbFOnZY_On34wIN1ZHCCIyg",
  "enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA"
}; 

Discv5Protocol discv5 = Discv5Builder.CreateDefault(bootstrapEnrs);
```

The `CreateDefault` method of `Discv5Builder` is used to instantiate the Discv5 protocol with a list of bootstrap ENR nodes.&#x20;

If more granular control is needed over the protocol's configuration, you can create an instance of `Discv5Protocol` using the builder pattern provided by `Discv5Builder`:

```csharp
Discv5Protocol discv5 = new Discv5Builder()
             .WithConnectionOptions(connectionOptions)
             .WithSessionOptions(sessionOptions)
             .WithTableOptions(tableOptions)
             .WithBootstrapEnrs(bootstrapEnrs)
             .WithEnrBuilder(enrBuilder)
             .WithEnrEntryRegistry(enrEntryRegistry)
             .WithLoggerFactory(loggerFactory)
             .Build();
```

### How To Use

Once `Discv5Protocol` has been instantiated, the protocol is ready to be interacted by using the following functionalities:

<details>

<summary>Start</summary>

A method to start the discovery protocol.

```csharp
await discv5.StartProtocolAsync()
```

</details>

<details>

<summary>Stop</summary>

A method that can be used to stop the discovery protocol when it's no longer needed.

```csharp
await discv5.StopProtocolAsync();
```

</details>

<details>

<summary>Self Enr</summary>

Returns the Ethereum Node Record (ENR) for the local node.

```csharp
Enr selfRecord = discv5.SelfEnr;
```

</details>

<details>

<summary>Nodes Count</summary>

Returns the total number of nodes that are stored in the routing table.

```csharp
int totalNodes = discv5.NodesCount;
```

</details>

<details>

<summary>Peer Count</summary>

Returns the total number of nodes that have `Live` status in the routing table.

```csharp
int activePeers = discv5.PeerCount;
```

</details>

<details>

<summary>Active Session Count</summary>

Returns the total number of active sessions maintained by the local node.

```csharp
int activeSession = discv5.ActiveSessionCount;
```

</details>

<details>

<summary>Get Node From Id</summary>

Returns the corrresponding `NodeTableEntry` stored in the routing table based on the provided `nodeId`.&#x20;

```csharp
NodeTableEntry node = discv5.GetNodeFromId(nodeId);
```

</details>

<details>

<summary>Get All Nodes</summary>

Returns all the nodes stored in the routing table as an array of `NodeTableEntry` objects.

```csharp
NodeTableEntry[] nodes = discv5.GetAllNodes();
```

</details>

<details>

<summary>Perform Lookup </summary>

To query the network for nodes closest to a given `targetNodeId`, you can use the `PerformLookupAsync` method. It will perform a recursive lookup to find nodes that are closest to the `targetNodeId`.&#x20;

{% code overflow="wrap" %}

```csharp
List<NodeTableEntry>? closestNodes = await discv5.PerformLookupAsync(targetNodeId);
```

{% endcode %}

This method will return list of `NodeTableEntry` objects, or `null` if no nodes were found or an error occurred.

</details>

<details>

<summary>Send PING message</summary>

A `PING` message can be sent to a connected node by supplying its `Enr` using the following method.

```csharp
Task<bool> request = await discv5.SendPingAsync(destinationNode);
```

Returns a `Task<bool>` object, indicating if the request was successfully sent or not.&#x20;

</details>

<details>

<summary>Send FINDNODE message</summary>

A `FINDNODE` request can be sent to a connected node to update the routing table with newer nodes.

{% code overflow="wrap" %}

```csharp
Task<bool> request = discv5.SendFindNodeAsync(destinationNode, targetNodeId);
```

{% endcode %}

Returns a `Task<bool>` object, indicating if the request was successful or not.&#x20;

</details>

<details>

<summary>Send TALKREQ message</summary>

To send an application-level request, this method can be used by providing the destination node's `Enr`, the supported `protocol`, and the `request`.

{% code overflow="wrap" %}

```csharp
Task<bool> request = await discv5.SendTalkReqAsync(destinationEnrRecord, protocol, request);
```

{% endcode %}

Returns a `Task<bool>` object, indicating if the request was successful or not.&#x20;

</details>


---

# Agent Instructions: 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://piertwo.gitbook.io/lantern.discv5/usage.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.
