Tools A Dart package that makes it easy to work with the nostr protocol and develop nostr clients

A Dart package that makes it easy to work with the nostr protocol and develop nostr clients.

Usage

To use this package, add nostr_tools as a dependency in your pubspec.yaml file.

Generating a private key and a public key

import 'package:nostr_tools/nostr_tools.dart';

void main() {
  final keyGenerator = KeyApi();

  final privateKey = keyGenerator.generatePrivateKey();
  print('[+] privateKey: $privateKey');
  // [+] privateKey: b2352adb186508e7f617105a6dc070df531f53b56cf8744816fdb838891dc9b7

  final publicKey = keyGenerator.getPublicKey(privateKey);
  print('[+] publicKey: $publicKey');
  // [+] publicKey: 9d088c4377b9866fad945d949de8f626784b1639f93bf090c1cea6727f17dd51
}

Creating, signing and verifying events

import 'package:nostr_tools/nostr_tools.dart';

void main() {
  final keyApi = KeyApi();
  final eventApi = EventApi();

  final privateKey = keyApi.generatePrivateKey();
  final publicKey = keyApi.getPublicKey(privateKey);

  final event = Event(
    kind: 1,
    tags: [],
    content: 'content',
    created_at: DateTime.now().millisecondsSinceEpoch ~/ 1000,
    pubkey: publicKey,
  );

  event.id = eventApi.getEventHash(event);
  event.sig = eventApi.signEvent(event, privateKey);

  if (eventApi.verifySignature(event)) print('[+] sig is valid');
}

Interacting with a relay

void main() async {
  final relay = RelayApi(relayUrl: 'wss://relay.damus.io');

  final stream = await relay.connect();

  relay.on((event) {
    if (event == RelayEvent.connect) {
      print('[+] connected to ${relay.relayUrl}');
    } else if (event == RelayEvent.error) {
      print('[!] failed to connect to ${relay.relayUrl}');
    }
  });

  relay.sub([
    Filter(
      kinds: [1],
      limit: 10,
      since: DateTime.now().millisecondsSinceEpoch ~/ 1000,
    )
  ]);

  stream.listen((Message message) {
    if (message.type == 'EVENT') {
      Event event = message.message;
      print('[+] Received event: ${event.content}');
    } else if (message.type == 'OK') {
      print('[+] Event Published: ${message.message}');
    }
  });

  // let's publish a new event while simultaneously monitoring the relay for it
  final privateKey =
      'b2352adb186508e7f617105a6dc070df531f53b56cf8744816fdb838891dc9b7';

  final event = EventApi().finishEvent(
    Event(
      kind: 1,
      tags: [],
      content: 'hello world',
      created_at: DateTime.now().millisecondsSinceEpoch ~/ 1000,
    ),
    privateKey,
  );

  relay.publish(event);
}

Interacting with multiple relays

void main() async {
  final relaysList = [
    'wss://relay.damus.io',
    'wss://relay.nostr.info',
    'wss://eden.nostr.land',
    'wss://nostr-pub.wellorder.net',
    'wss://nos.lol'
  ];
  final relayPool = RelayPoolApi(relaysList: relaysList);

  final stream = await relayPool.connect();

  relayPool.on((event) {
    if (event == RelayEvent.connect) {
      print('[+] connected to: ${relayPool.connectedRelays}');
    } else if (event == RelayEvent.error) {
      print('[!] failed to connect to: ${relayPool.failedRelays}');
    }
  });

  relayPool.sub([
    Filter(
      kinds: [1],
      limit: 10,
      since: DateTime.now().millisecondsSinceEpoch ~/ 1000,
    )
  ]);

  stream.listen((Message message) {
    if (message.type == 'EVENT') {
      Event event = message.message;
      print('[+] Received event: ${event.content}');
    }
  });

  final privateKey =
      'ccbe92bd853e3661bace63df5b8338dcbaa2c766e2dbb0b90d45b2dd58efaae4';

  final event = EventApi().finishEvent(
    Event(
      kind: 1,
      tags: [],
      content: 'hello world',
      created_at: DateTime.now().millisecondsSinceEpoch ~/ 1000,
    ),
    privateKey,
  );

  relayPool.publish(event);
}

Querying profile data from a NIP-05 address

void main() async {
  var nip05 = Nip05();
  var profile = await nip05.queryProfile('anipy@aniketambore.github.io');
  print('[+] Pubkey: ${profile?.pubkey}');
  // [+] Pubkey: c7c187ba76532d55723490af88e76dd570fe551a2461ca9ab542b503bbb25045

  print('[+] Relays: ${profile?.relays}');
  // [+] Relays: [wss://relay.damus.io, wss://nos.lol, wss://relay.snort.social]
}

Encoding and decoding NIP-19 codes

void main() {
  final keyGenerator = KeyApi();
  final nip19 = Nip19();

  final sk = keyGenerator.generatePrivateKey();
  final nsec = nip19.nsecEncode(sk);
  final nsecDecoded = nip19.decode(nsec);
  assert(nsecDecoded['type'] == 'nsec');
  assert(nsecDecoded['data'] == sk);

  final pk = keyGenerator.getPublicKey(sk);
  final npub = nip19.npubEncode(pk);
  final npubDecoded = nip19.decode(npub);
  assert(npubDecoded['type'] == 'npub');
  assert(npubDecoded['data'] == pk);

  final relays = [
    'wss://relay.nostr.example.mydomain.example.com',
    'wss://nostr.banana.com'
  ];
  final nprofile =
      nip19.nprofileEncode(ProfilePointer(pubkey: pk, relays: relays));
  final nprofileDecode = nip19.decode(nprofile);
  assert(nprofileDecode['type'] == 'nprofile');
  assert(nprofileDecode['data']['pubkey'] == pk);
  assert(nprofileDecode['data']['relays'].length == 2);
}

Encrypting and decrypting direct messages

void main() {
  final keyGenerator = KeyApi();
  final nip04 = Nip04();

  final aliceSK = keyGenerator.generatePrivateKey();
  final alicePK = keyGenerator.getPublicKey(aliceSK);
  final bobSK = keyGenerator.generatePrivateKey();
  final bobPK = keyGenerator.getPublicKey(bobSK);

  var aliceMessageToBob = 'Hello Bob!';
  var cipherText = nip04.encrypt(aliceSK, bobPK, aliceMessageToBob);
  print('[+] cipherText: $cipherText');

  var bobDecodingMessage = nip04.decrypt(bobSK, alicePK, cipherText);
  print('[+] plainText: $bobDecodingMessage');
}

Take a look at the example project for developing a simple basic nostr client in flutter.

Reference

GitHub

View Github

Related Posts

Recent Posts

ഇടുക്കിയിലെ മലയോര മേഖലകളിൽ രാത്രിയാത്ര നിരോധിച്ചു. രാത്രി ഏഴു മുതൽ രാവിലെ ആറു വരെയാണ് നിരോധനം

ഏന്തയാർ ഈസ്റ്റിൽ പ്രളയത്തിൽ തകർന്ന പാലത്തിന് പകരം പുതിയ പാലം നിർമ്മിക്കുവാൻ താത്ക്കാലിക പാലം പൊളിച്ച് നീക്കി

Explore the Investment Opportunities: A Comprehensive Guide to Different Types of Mutual Funds

Title: Understanding Mutual Funds: A Beginner's Guide to Investing

തീവ്രമഴ മുന്നറിയിപ്പിന്റെ പശ്ചാതലത്തിൽ സംസ്ഥാനം ജാഗ്രതയിൽ

250,000 അപേക്ഷകൾ വർദ്ധിച്ചതിനാൽ ട്രാൻസ്‌പോർട്ട് കമ്മീഷണർ പരിശോധന പുനരാരംഭിക്കും

ഏലക്കയിൽ കീടനാശിനി സാന്നിധ്യം; ആറര ലക്ഷത്തിലധികം ടിൻ അരവണ നശിപ്പിക്കാൻ ടെൻഡർ ക്ഷണിച്ച് ദേവസ്വം ബോർഡ്‌

ഭീമൻ പാറക്കഷണങ്ങൾ അടർന്ന് ദേശീയ പാതയിലേക്ക് വീഴുന്നത് പതിവാകുന്നു. കുട്ടിക്കാനത്തിനും മുണ്ടക്കയത്തിനുമിടയിൽ നിലനിൽക്കുന്നത് വൻ അപകട ഭീഷണി

ചക്രവാതച്ചുഴി:അതിശക്തമായ മഴ വരുന്നു

പ്ലസ് വൺ പ്രവേശനം. അക്ഷയയിൽ തിക്കി തിരക്കേണ്ട, നെറ്റിവിറ്റി/ജാതി തെളിയിക്കാൻ പത്താംതരം സർട്ടിഫിക്കറ്റ് മതി