Accounts

high level

Example

KeyPair key1 = Bip340.generatePrivateKey();

// login using private key
ndk.accounts.loginPrivateKey(
  privkey: key1.privateKey!,
  pubkey: key1.publicKey,
);

// broadcast a new event using the logged in account with it's signer to sign
NdkBroadcastResponse response = ndk.broadcast.broadcast(
  nostrEvent: Nip01Event(
    pubKey: key1.publicKey,
    kind: Nip01Event.kTextNodeKind,
    tags: [],
    content: "test",
  ),
  specificRelays: DEFAULT_BOOTSTRAP_RELAYS,
);
await response.broadcastDoneFuture;

External Signer (web)

// ignore_for_file: avoid_print

import 'package:ndk_flutter/ndk_flutter.dart';

void main() async {
  final signer = Nip07EventSigner();
  if (!signer.canSign()) {
    return;
  }

  final pubkey = await signer.getPublicKeyAsync();
  print(pubkey);
}

External Signer (nip-46 bunker)

Pass the same Nip46ClientMetadata to both flows. A bunker:// URL does not identify your app, so this metadata is the only way for the remote signer to label the connection.

client metadata
const clientMetadata = Nip46ClientMetadata(
    name: "My app",
    url: "https://myapp.example",
    perms: ["sign_event:1", "nip44_encrypt"],
);
login with bunker url
final bunkerConnection = await ndk.accounts.loginWithBunkerUrl(
    bunkerUrl: "bunker://xxx",
    bunkers: ndk.bunkers,
    clientMetadata: clientMetadata,
    authCallback: (challenge) {},
);
login with nostr connect
final nostrConnect = NostrConnect(
    relays: ["wss://relay.example.com"],
    clientMetadata: clientMetadata,
);
final bunkerConnection = await ndk.accounts.loginWithNostrConnect(
    nostrConnect: nostrConnect,
    bunkers: ndk.bunkers,
    authCallback: (challenge) {},
);
login with bunker connection
final bunkerConnection = BunkerConnection(
    privateKey: "privateKey",
    remotePubkey: "remotePubkey",
    relays: ["wss://relay.example.com"]
);
await ndk.accounts.loginWithBunkerConnection(
    connection: bunkerConnection,
    bunkers: ndk.bunkers,
    authCallback: (challenge) {},
);

Reacting to changes

watch the logged in account
ndk.accounts.authStateChanges.listen((account) {
    // account is null when logged out
});
watch the list of accounts
ndk.accounts.accountsStream.listen((accounts) {
    // pubkey -> Account, emitted on every add and remove
});

accountsStream emits the current accounts on subscription, then an unmodifiable snapshot each time an account is added or removed. switchAccount changes the logged in account but not the list, so it only fires authStateChanges.

The ndk.accounts.accounts map is a read-only view of the same data, for when you need a synchronous read instead of a stream.

When to use

Use it to log in an account. You can use several types of accounts:

  • loginPrivateKey
  • loginPublicKey (read-only)
  • loginExternalSigner (capabilities will be managed by external signer)

An account logged in is needed in order to use broadcast, and only if the signer used is able to sign.

You can switch between several logged in accounts with switchAccount(pubkey:...)