basic nostr actors

This commit is contained in:
randogoth 2026-06-07 16:45:43 +03:00
parent c14de9c3e9
commit f1e54f2722
13 changed files with 1081 additions and 2 deletions

View file

@ -0,0 +1,85 @@
import 'dart:convert';
import 'dart:math';
import 'package:actors/actors.dart';
import 'package:bip340/bip340.dart' as bip340;
import 'package:crypto/crypto.dart';
sealed class SignerMessage {
const SignerMessage();
}
final class SignEvent extends SignerMessage {
final int kind;
final List<List<String>> 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();
}
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);
}
class NostrSignerActor with Handler<SignerMessage, SignerResult> {
final String _privateKey;
final String _publicKey;
NostrSignerActor(String privateKey)
: _privateKey = privateKey,
_publicKey = bip340.getPublicKey(privateKey);
@override
Future<SignerResult> 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)),
};
EventSigned _signEvent(
int kind,
List<List<String>> tags,
String content,
int? createdAt,
) {
final ts = createdAt ?? DateTime.now().millisecondsSinceEpoch ~/ 1000;
final ser = jsonEncode([0, _publicKey, ts, kind, tags, content]);
final idBytes = sha256.convert(utf8.encode(ser)).bytes;
final id = idBytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
final rng = Random.secure();
final auxBytes = List.generate(32, (_) => rng.nextInt(256));
final aux = auxBytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
final sig = bip340.sign(_privateKey, id, aux);
return EventSigned(jsonEncode({
'id': id,
'pubkey': _publicKey,
'created_at': ts,
'kind': kind,
'tags': tags,
'content': content,
'sig': sig,
}));
}
}