basic nostr actors
This commit is contained in:
parent
c14de9c3e9
commit
f1e54f2722
13 changed files with 1081 additions and 2 deletions
85
lib/src/nostr_signer_actor.dart
Normal file
85
lib/src/nostr_signer_actor.dart
Normal 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,
|
||||
}));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue