import 'package:actors/actors.dart'; import 'package:bip340/bip340.dart' as bip340; import 'nip44.dart'; import 'nostr_event.dart'; sealed class SignerMessage { const SignerMessage(); } final class SignEvent extends SignerMessage { final int kind; final List> tags; final String content; final int? createdAt; const SignEvent({ required this.kind, this.tags = const [], required this.content, this.createdAt, }); } final class GetPublicKey extends SignerMessage { const GetPublicKey(); } /// NIP-44 v2 encrypt-to-self: encrypts [plaintext] with this signer's own key /// (conversation key derived from its private key and public key). final class Nip44Encrypt extends SignerMessage { final String plaintext; const Nip44Encrypt(this.plaintext); } /// NIP-44 v2 decrypt-from-self: inverse of [Nip44Encrypt]. Throws on a version /// mismatch or HMAC failure (e.g. a payload sealed with a different key). final class Nip44Decrypt extends SignerMessage { final String payload; const Nip44Decrypt(this.payload); } sealed class SignerResult { const SignerResult(); } final class EventSigned extends SignerResult { final String event; const EventSigned(this.event); } final class PublicKeyResult extends SignerResult { final String publicKey; const PublicKeyResult(this.publicKey); } /// Result of a [Nip44Encrypt] (base64 payload) or [Nip44Decrypt] (plaintext). final class Nip44Text extends SignerResult { final String value; const Nip44Text(this.value); } class NostrSignerActor with Handler { final String _privateKey; final String _publicKey; NostrSignerActor(String privateKey) : _privateKey = privateKey, _publicKey = bip340.getPublicKey(privateKey); @override Future handle(SignerMessage message) => switch (message) { SignEvent(:final kind, :final tags, :final content, :final createdAt) => Future.value(_signEvent(kind, tags, content, createdAt)), GetPublicKey() => Future.value(PublicKeyResult(_publicKey)), Nip44Encrypt(:final plaintext) => Future.value( Nip44Text(nip44Encrypt(plaintext, _privateKey, _publicKey)), ), Nip44Decrypt(:final payload) => Future.value( Nip44Text(nip44Decrypt(payload, _privateKey, _publicKey)), ), }; EventSigned _signEvent( int kind, List> tags, String content, int? createdAt, ) => EventSigned(signNostrEvent( privateKey: _privateKey, publicKey: _publicKey, kind: kind, tags: tags, content: content, createdAt: createdAt, )); }