# 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>
