Nostr.Client
2.0.0
dotnet add package Nostr.Client --version 2.0.0
NuGet\Install-Package Nostr.Client -Version 2.0.0
<PackageReference Include="Nostr.Client" Version="2.0.0" />
paket add Nostr.Client --version 2.0.0
#r "nuget: Nostr.Client, 2.0.0"
// Install Nostr.Client as a Cake Addin #addin nuget:?package=Nostr.Client&version=2.0.0 // Install Nostr.Client as a Cake Tool #tool nuget:?package=Nostr.Client&version=2.0.0
Nostr client
This is a C# implementation of the Nostr protocol found here:
https://github.com/nostr-protocol/nips
Nostr protocol is based on websocket communication. This library keeps a reliable connection to get real-time data and fast execution of your commands.
License:
Apache License 2.0
Features
- installation via NuGet (Nostr.Client)
- targeting .NET 6.0 and higher (.NET Core, Linux/MacOS compatible)
- reactive extensions (Rx.NET)
Usage
Receiving events
var url = new Uri("wss://relay.damus.io");
using var communicator = new NostrWebsocketCommunicator(url);
using var client = new NostrWebsocketClient(communicator, null);
client.Streams.EventStream.Subscribe(response =>
{
var ev = response.Event;
Log.Information("{kind}: {content}", ev?.Kind, ev?.Content)
if(ev is NostrMetadataEvent evm) {
Log.Information("Name: {name}, about: {about}", evm.Metadata?.Name, evm.Metadata?.About);
}
});
await communicator.Start();
Sending event
var ev = new NostrEvent
{
Kind = NostrKind.ShortTextNote,
CreatedAt = DateTime.UtcNow,
Content = "Test message from C# client"
};
var key = NostrPrivateKey.FromBech32("nsec1xxx");
var signed = ev.Sign(key);
client.Send(new NostrEventRequest(signed));
Sending encrypted direct message (NIP-04)
var sender = NostrPrivateKey.FromBech32("nsec1l0a7m5dlg4h9wurhnmgsq5nv9cqyvdwsutk4yf3w4fzzaqw7n80ssdfzkg");
var receiver = NostrPublicKey.FromBech32("npub1dd668dyr9un9nzf9fjjkpdcqmge584c86gceu7j97nsp4lj2pscs0xk075");
var ev = new NostrEvent
{
CreatedAt = DateTime.UtcNow,
Content = $"Test private message from C# client"
};
var encrypted = ev.EncryptDirect(sender, receiver);
var signed = encrypted.Sign(sender);
client.Send(new NostrEventRequest(signed));
Multi relays support
var relays = new[]
{
new NostrWebsocketCommunicator(new Uri("wss://relay.snort.social")),
new NostrWebsocketCommunicator(new Uri("wss://relay.damus.io")),
new NostrWebsocketCommunicator(new Uri("wss://nos.lol"))
};
var client = new NostrMultiWebsocketClient(NullLogger<NostrWebsocketClient>.Instance, relays);
client.Streams.EventStream.Subscribe(HandleEvent);
relays.ToList().ForEach(relay => relay.Start());
More usage examples:
NIP's coverage
- NIP-01: Basic protocol flow description
- NIP-02: Contact List and Petnames (No petname support)
- NIP-03: OpenTimestamps Attestations for Events
- NIP-04: Encrypted Direct Message
- NIP-05: Mapping Nostr keys to DNS-based internet identifiers
- NIP-06: Basic key derivation from mnemonic seed phrase
- NIP-07:
window.nostr
capability for web browsers - NIP-08: Handling Mentions
- NIP-09: Event Deletion
- NIP-10: Conventions for clients' use of
e
andp
tags in text events - NIP-11: Relay Information Document
- NIP-12: Generic Tag Queries
- NIP-13: Proof of Work
- NIP-14: Subject tag in text events
- NIP-15: End of Stored Events Notice
- NIP-19: bech32-encoded entities
- NIP-20: Command Results
- NIP-21:
nostr:
Protocol handler (web+nostr
) - NIP-25: Reactions
- NIP-26: Delegated Event Signing (Display delegated signings only)
- NIP-28: Public Chat
- NIP-36: Sensitive Content
- NIP-40: Expiration Timestamp
- NIP-42: Authentication of clients to relays
- NIP-50: Search
- NIP-51: Lists
- NIP-65: Relay List Metadata
Pull Requests are welcome!
Reconnecting
A built-in reconnection invokes after 1 minute (default) of not receiving any messages from the server.
It is possible to configure that timeout via communicator.ReconnectTimeout
.
Also, a stream ReconnectionHappened
sends information about a type of reconnection.
However, if you are subscribed to low-rate channels, you will likely encounter that timeout - higher it to a few minutes or implement ping-pong
interaction on your own every few seconds.
In the case of Nostr relay outage, there is a built-in functionality that slows down reconnection requests
(could be configured via client.ErrorReconnectTimeout
, the default is 1 minute).
Beware that you need to resubscribe to channels after reconnection happens. You should subscribe to ReconnectionHappened
stream and send subscription requests.
Testing
The library is prepared for replay testing. The dependency between Client
and Communicator
is via abstraction INostrCommunicator
. There are two communicator implementations:
NostrWebsocketCommunicator
- real-time communication with Nostr relay.NostrFileCommunicator
- a simulated communication, raw data are loaded from files and streamed.
Feel free to implement INostrCommunicator
on your own, for example, load raw data from database, cache, etc.
Usage:
var communicator = new NostrFileCommunicator();
communicator.FileNames = new[]
{
"data/nostr-data.txt"
};
communicator.Delimiter = "\n";
var client = new NostrWebsocketClient(communicator);
client.Streams.EventStream.Subscribe(trade =>
{
// do something with an event
});
await communicator.Start();
Multi-threading and other considerations
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- BTCPayServer.Lightning.Common (>= 1.3.21)
- Microsoft.Extensions.Logging.Abstractions (>= 7.0.1)
- NBitcoin.Secp256k1 (>= 3.1.1)
- Newtonsoft.Json (>= 13.0.3)
- System.Reactive (>= 6.0.0)
- Websocket.Client (>= 4.6.1)
-
net7.0
- BTCPayServer.Lightning.Common (>= 1.3.21)
- Microsoft.Extensions.Logging.Abstractions (>= 7.0.1)
- NBitcoin.Secp256k1 (>= 3.1.1)
- Newtonsoft.Json (>= 13.0.3)
- System.Reactive (>= 6.0.0)
- Websocket.Client (>= 4.6.1)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Nostr.Client:
Package | Downloads |
---|---|
NostrServices.Client
Client wrapper for https://nostr.api.v0l.io |
|
PlangLibrary
Plang language core |
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on Nostr.Client:
Repository | Stars |
---|---|
v0l/void.cat
Free file hosting website
|
Version | Downloads | Last updated |
---|---|---|
2.0.0 | 3,025 | 11/16/2023 |
1.4.3 | 2,033 | 8/1/2023 |
1.4.2 | 605 | 6/25/2023 |
1.4.1 | 475 | 6/21/2023 |
1.4.0 | 538 | 4/28/2023 |
1.3.1 | 586 | 4/20/2023 |
1.3.0 | 529 | 4/19/2023 |
1.2.4 | 535 | 4/17/2023 |
1.2.3 | 566 | 4/4/2023 |
1.2.2 | 579 | 3/10/2023 |
1.2.1 | 547 | 3/7/2023 |
1.2.0 | 578 | 3/3/2023 |
1.1.2 | 564 | 2/23/2023 |
1.1.1 | 589 | 2/23/2023 |
1.1.0 | 565 | 2/23/2023 |
1.0.4 | 565 | 2/21/2023 |
1.0.3 | 607 | 2/18/2023 |
1.0.2 | 564 | 2/18/2023 |
1.0.1 | 594 | 2/18/2023 |
1.0.0 | 594 | 2/18/2023 |
Enhancements