#
Lists
high level
#
Example
final myset = await ndk.lists.getSetByName(
name: "myset",
kind: Nip51List.kRelaySet,
customSigner: mySigner,
);
if (myset == null) {
print("set not found");
return;
}
print("received a set with ${myset.elements.length} elements");
#
How to use
We distinguish between lists and sets:
- Lists: Single lists identified by kind (e.g., bookmarks, mute list)
- Sets: Named collections identified by kind + name/d-tag (e.g., relay sets, follow sets)
Both can have public and private (encrypted) elements.
#
Lists Methods
#
getSingleNip51List
Retrieves a NIP-51 list by kind.
/// Returns a NIP-51 list by the given kind.
///
/// Retrieves the most recent list event for the specified kind.
/// First checks cache unless [forceRefresh] is true, then queries relays.
///
/// [kind] the kind of NIP-51 list to retrieve \
/// [forceRefresh] if true, bypass cache and query relays directly \
/// [timeout] maximum duration to wait for relay responses
///
/// Returns the list if found, null otherwise.
Future<Nip51List?> getSingleNip51List(
int kind, {
bool forceRefresh = false,
Duration timeout = const Duration(seconds: 5),
}) async {
if (_eventSigner == null) {
throw Exception("cannot get nip51 list without a signer");
#
addElementToList
Adds an element to a list. Creates the list if it doesn't exist.
}
/// Adds an element to a NIP-51 list.
///
/// If the list doesn't exist, it will be created. The updated list is
/// then broadcast to relays and cached locally.
///
/// [kind] the kind of NIP-51 list \
/// [tag] the tag type for the element (e.g., 'p' for pubkey, 'e' for event) \
/// [value] the value to add to the list \
/// [broadcastRelays] optional specific relays to broadcast to \
/// [private] if true, encrypt the element in the list content
///
/// Returns the updated list.\
/// Throws an exception if no event signer is available.
Future<Nip51List> addElementToList({
required int kind,
required String tag,
required String value,
Iterable<String>? broadcastRelays,
#
removeElementFromList
Removes an element from a list.
/// Removes an element from a NIP-51 list.
///
/// Updates the list by removing the specified element, then broadcasts
/// the updated list to relays and updates the cache.
///
/// [kind] the kind of NIP-51 list \
/// [tag] the tag type of the element to remove \
/// [value] the value to remove from the list \
/// [broadcastRelays] optional specific relays to broadcast to
///
/// Returns the updated list, or null if the list doesn't exist.\
/// Throws an exception if no event signer is available.
Future<Nip51List?> removeElementFromList({
required int kind,
required String tag,
required String value,
Iterable<String>? broadcastRelays,
#
Sets Methods
#
getSetByName
Gets a specific set by name (d-tag) and kind.
/// Gets a NIP-51 set by name identifier (d tag).
///
/// Retrieves a specific set for the logged-in user or a custom signer.
/// The set is identified by its name (d tag) and kind.
///
/// [name] name of the set (d tag identifier) \
/// [kind] kind of the set, see Nip51List class for constants \
/// [customSigner] optional signer, defaults to logged-in account \
/// [forceRefresh] if true, skip cache and query relays directly
///
/// Returns the set if found, null otherwise. \
/// Throws an exception if no account is logged in and no custom signer is provided.
Future<Nip51Set?> getSetByName({
required String name,
required int kind,
bool forceRefresh = false,
}) async {
final EventSigner signer;
#
getPublicSets
Returns a stream of all public sets for a given public key and kind.
/// [kind] the kind of sets to retrieve \
/// [publicKey] the public key of the user whose sets to retrieve, default logged in pubkey \
/// [forceRefresh] if true, skip cache and query relays directly
///
/// Returns a stream that emits collections of sets as they are discovered.
Stream<Iterable<Nip51Set>?> getPublicSets({
required int kind,
String? publicKey,
bool forceRefresh = false,
}) {
final EventSigner mySigner;
if (publicKey == null) {
if (_eventSigner == null) {
throw Exception("getPublicSets() no account");
}
#
addElementToSet
Adds an element to a named set. Creates the set if it doesn't exist.
return _getSets(kind, mySigner, forceRefresh: forceRefresh);
}
/// Adds an element to a NIP-51 set.
///
/// If the set doesn't exist, it will be created. The updated set is
/// then broadcast to relays and cached locally.
///
/// [name] name of the set (d tag identifier) \
/// [tag] the tag type for the element (e.g., 'relay', 'p', 'e') \
/// [value] the value to add to the set \
/// [kind] kind of the set \
/// [private] if true, encrypt the element in the set content \
/// [specificRelays] optional specific relays to broadcast to
///
/// Returns the updated set.
Future<Nip51Set?> addElementToSet({
required String name,
required String tag,
required String value,
#
removeElementFromSet
Removes an element from a named set.
await _cacheManager.saveEvent(event);
return set;
}
/// Removes an element from a NIP-51 set.
///
/// Updates the set by removing the specified element, then broadcasts
/// the updated set to relays and updates the cache.
///
/// [name] name of the set (d tag identifier) \
/// [value] the value to remove from the set \
/// [tag] the tag type of the element to remove \
/// [kind] kind of the set \
/// [private] if true, the element was encrypted \
/// [specificRelays] optional specific relays to broadcast to
///
/// Returns the updated set.
/// Throws an exception if no event signer is available.
Future<Nip51Set?> removeElementFromSet({
required String name,
required String value,
required String tag,
#
setCompleteSet
Overwrites or creates a complete set. Warning: This replaces the entire set.
return mySet;
}
/// Overwrites or creates a complete NIP-51 set.
///
/// **Warning:** This replaces the entire set. Consider using
/// [addElementToSet] or [removeElementFromSet] for incremental updates.
///
/// [set] the complete set to broadcast \
/// [kind] kind of the set \
/// [specificRelays] optional specific relays to broadcast to
///
/// Returns the set after broadcasting.
Future<Nip51Set> setCompleteSet({
required Nip51Set set,
#
deleteSet
Deletes a set by name and broadcasts a deletion event.
/// Deletes a NIP-51 set by name.
///
/// Broadcasts a deletion event for the set and removes it from the cache.
/// Uses the logged-in account's signer.
///
/// [name] name of the set (d tag identifier) \
/// [kind] kind of the set \
/// [specificRelays] optional specific relays to broadcast the deletion to
///
/// Throws an exception if no event signer is available.
Future deleteSet({
required String name,
required int kind,
Iterable<String>? specificRelays,
#
Common Use Cases
#
Relay Sets
// Add relay to a set
await ndk.lists.addElementToSet(
name: "my-relays",
tag: "relay",
value: "wss://relay.example.com",
kind: Nip51List.kRelaySet,
);
// Get a relay set
final relaySet = await ndk.lists.getSetByName(
name: "my-relays",
kind: Nip51List.kRelaySet,
);
#
Bookmarks
// Add bookmark
await ndk.lists.addElementToList(
kind: Nip51List.kBookmarks,
tag: "e",
value: eventId,
);
// Get bookmarks
final bookmarks = await ndk.lists.getSingleNip51List(
Nip51List.kBookmarks,
mySigner,
);
#
Follow Sets
// Add to follow set
await ndk.lists.addElementToSet(
name: "close-friends",
tag: "p",
value: pubkey,
kind: Nip51List.kFollowSet,
);
// Stream all public follow sets
ndk.lists.getPublicSets(
kind: Nip51List.kFollowSet,
publicKey: somePubkey,
).listen((sets) {
print("Found ${sets?.length ?? 0} follow sets");
});