Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #14

Merged
merged 3 commits into from
Jan 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,10 @@

## 1.3.1

- fix: Inconsitency in events is breaking tags
- fix: Inconsitency in events is breaking tags

## 1.3.2

- refactor: Event with optional verification
- remove tests with encoding problem
- improve coverage
80 changes: 50 additions & 30 deletions lib/src/event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,32 @@ class Event {
this.kind,
this.tags,
this.content,
this.sig,
) {
this.sig, {
this.subscriptionId,
bool verify = true,
}) {
assert(createdAt.toString().length == 10);
assert(createdAt <= currentUnixTimestampSeconds());
pubkey = pubkey.toLowerCase();
String id = getEventId();
assert(this.id == id);
assert(bip340.verify(pubkey, id, sig));

/// This option adds event checks such as id, signature, non-futuristic event: default=True
/// Performances could be a reason to disable event checks
if (verify == true) {
assert(createdAt <= currentUnixTimestampSeconds());
String verifyId = getEventId();
assert(id == verifyId);
assert(bip340.verify(pubkey, id, sig));
}
}

/// Instanciate Event object from the minimum available data
Event.from(
{this.createdAt = 0,
required this.kind,
required this.tags,
required this.content,
required String privkey,
this.subscriptionId}) {
Event.from({
this.createdAt = 0,
required this.kind,
required this.tags,
required this.content,
required String privkey,
this.subscriptionId,
}) {
if (createdAt == 0) {
createdAt = currentUnixTimestampSeconds();
}
Expand All @@ -82,16 +90,20 @@ class Event {
}

/// Deserialize an event from a JSON
Event.fromJson(Map<String, dynamic> json, {this.subscriptionId}) {
id = json['id'];
pubkey = json['pubkey'];
createdAt = json['created_at'];
kind = json['kind'];
tags = (json['tags'] as List<dynamic>)
factory Event.fromJson(Map<String, dynamic> json, {bool verify = true}) {
var tags = (json['tags'] as List<dynamic>)
.map((e) => (e as List<dynamic>).map((e) => e as String).toList())
.toList();
content = json['content'];
sig = json['sig'];
return Event(
json['id'],
json['pubkey'],
json['created_at'],
json['kind'],
tags,
json['content'],
json['sig'],
verify: verify,
);
}

/// Serialize an event in JSON
Expand Down Expand Up @@ -119,25 +131,33 @@ class Event {
/// Deserialize a nostr event message
/// - ["EVENT", event JSON as defined above]
/// - ["EVENT", subscription_id, event JSON as defined above]
Event.deserialize(input) {
factory Event.deserialize(input, {bool verify = true}) {
Map<String, dynamic> json = {};
String? subscriptionId;
if (input.length == 2) {
json = input[1] as Map<String, dynamic>;
} else if (input.length == 3) {
json = input[2] as Map<String, dynamic>;
subscriptionId = input[1];
subscriptionId = input[1] as String;
} else {
throw Exception('invalid input');
}
id = json['id'];
pubkey = json['pubkey'];
createdAt = json['created_at'];
kind = json['kind'];
tags = (json['tags'] as List<dynamic>)

var tags = (json['tags'] as List<dynamic>)
.map((e) => (e as List<dynamic>).map((e) => e as String).toList())
.toList();
content = json['content'];
sig = json['sig'];

return Event(
json['id'],
json['pubkey'],
json['created_at'],
json['kind'],
tags,
json['content'],
json['sig'],
subscriptionId: subscriptionId,
verify: verify,
);
}

/// To obtain the event.id, we sha256 the serialized event.
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: nostr
description: A library for nostr protocol implemented in dart for flutter
version: 1.3.1
version: 1.3.2
homepage: https://github.com/ethicnology/dart-nostr

environment:
Expand Down
63 changes: 22 additions & 41 deletions test/event_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -103,31 +103,8 @@ void main() {
});

test('Constructor.toJson', () {
Map<String, dynamic> json = {
"pubkey":
"9be7376ef6c0d493235ddf9018ff675a04bfcaf34dc1f97a1d270470f28c0ae0",
"content": "How does this work? 👀",
"id":
"883334badc17315fc61f0a13eec84c8c87df9d504ce0788f5eeab4a3527ddc97",
"created_at": 1672477967,
"sig":
"3ce34915e90505f9760a463eb8f9e8b1748fd4c10c4cfddc09a2930ecce249ce8dd499eeffd6e24a215bb2f8265b68085f7104eb7d506f8d9b76a7c5312b09fd",
"kind": 1,
"tags": [
[
"e",
"68ae015bf4833a6ff0ed86564c5afaa65c31791d35e8432755535d02eafc4375"
],
[
"e",
"de2d85a00a52ceb25f3cfc41e22d927f6166250f210f928e2552b97c0bd66dcf"
],
[
"p",
"052acd328f1c1d48e86fff3e34ada4bfc60578116f4f68f296602530529656a2"
]
]
};
Map<String, dynamic> json = jsonDecode(
'{"id":"f9b8c5b7a8692b0f5b8ca9f2c29ff84d6baa5a60d14cbf1c54bd2bb77ee8b41f","kind":1,"pubkey":"891b945271cd3c65dc22cb9e77ba08f5cd165ad8d9fba370b740f7db95f98b10","created_at":1675015139,"content":"Authorize just this time...I have commitment issues.","tags":[["e","343ed9c6ca7a0a8f33f8cfed04b6cea4a4dda50a649daffaf85d6410507c5c7c","wss://relay.damus.io","reply"],["p","7b6461d02c6f0be1cacdcf968c4246105a2db51c7770993bf8bb25e59cedffa7"]],"sig":"bd63b762379bd06e536ccb943f909f075bd512315fbf2407be19f03ee9d3ef5b4a70205aa7a8e68cb8c2d250f56ef8f5074339abd741d32dbd18d16641a339ef"}');
Event event = Event.fromJson(json);
Map<String, dynamic> toJson = event.toJson();
expect(toJson, json);
Expand Down Expand Up @@ -180,31 +157,29 @@ void main() {
test('Constructor.deserialize', () {
var serialized = [
"EVENT",
"7971516031312706",
"0954524188078879",
{
"id":
"883334badc17315fc61f0a13eec84c8c87df9d504ce0788f5eeab4a3527ddc97",
"pubkey":
"9be7376ef6c0d493235ddf9018ff675a04bfcaf34dc1f97a1d270470f28c0ae0",
"created_at": 1672477967,
"f9b8c5b7a8692b0f5b8ca9f2c29ff84d6baa5a60d14cbf1c54bd2bb77ee8b41f",
"kind": 1,
"pubkey":
"891b945271cd3c65dc22cb9e77ba08f5cd165ad8d9fba370b740f7db95f98b10",
"created_at": 1675015139,
"content": "Authorize just this time...I have commitment issues.",
"tags": [
[
"e",
"68ae015bf4833a6ff0ed86564c5afaa65c31791d35e8432755535d02eafc4375"
],
[
"e",
"de2d85a00a52ceb25f3cfc41e22d927f6166250f210f928e2552b97c0bd66dcf"
"343ed9c6ca7a0a8f33f8cfed04b6cea4a4dda50a649daffaf85d6410507c5c7c",
"wss://relay.damus.io",
"reply"
],
[
"p",
"052acd328f1c1d48e86fff3e34ada4bfc60578116f4f68f296602530529656a2"
"7b6461d02c6f0be1cacdcf968c4246105a2db51c7770993bf8bb25e59cedffa7"
]
],
"content": "How does this work? 👀",
"sig":
"3ce34915e90505f9760a463eb8f9e8b1748fd4c10c4cfddc09a2930ecce249ce8dd499eeffd6e24a215bb2f8265b68085f7104eb7d506f8d9b76a7c5312b09fd",
"bd63b762379bd06e536ccb943f909f075bd512315fbf2407be19f03ee9d3ef5b4a70205aa7a8e68cb8c2d250f56ef8f5074339abd741d32dbd18d16641a339ef"
}
];
Event event = Event.deserialize(serialized);
Expand Down Expand Up @@ -239,9 +214,15 @@ void main() {
expect(eventWithoutSubscriptionId.subscriptionId, null);
});

test('Generated from decoded json', () {
Event event = Event.fromJson(jsonDecode(
'{"kind": 1, "pubkey":"0ba0206887bd61579bf65ec09d7806bea32c64be1cf2c978cf031a811cd238db","content": "dart-nostr","tags": [["p","052acd328f1c1d48e86fff3e34ada4bfc60578116f4f68f296602530529656a2",""]],"created_at": 1672477962,"sig":"246970954e7b74e7fe381a4c818fed739ee59444cb536dadf45fbbce33bd7455ae7cd678c347c4a0c6e0a4483d18c7e26b7abe76f4cc73234f774e0e0d65204b","id": "047663d895d56aefa3f528935c7ce7dc8939eb721a0ec76ef2e558a8257955d2"}'));
test('Fake event (verify=false) with empty tag', () {
var json = jsonDecode(
'{"kind": 1, "pubkey":"0ba0206887bd61579bf65ec09d7806bea32c64be1cf2c978cf031a811cd238db","content": "dart-nostr","tags": [["p","052acd328f1c1d48e86fff3e34ada4bfc60578116f4f68f296602530529656a2",""]],"created_at": 1672477962,"sig":"246970954e7b74e7fe381a4c818fed739ee59444cb536dadf45fbbce33bd7455ae7cd678c347c4a0c6e0a4483d18c7e26b7abe76f4cc73234f774e0e0d65204b","id": "047663d895d56aefa3f528935c7ce7dc8939eb721a0ec76ef2e558a8257955d2"}',
);
Event event = Event.fromJson(json, verify: false);
expect(event.tags[0][2], equals(""));
});

test('Event.deserialize throw', () {
expect(() => Event.deserialize([]), throwsException);
});
}
4 changes: 2 additions & 2 deletions test/message_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ void main() {
group('Message', () {
test('EVENT', () {
String payload =
'["EVENT","3979053091133091",{"id":"a60679692533b308f1d862c2a5ca5c08a304e5157b1df5cde0ff0454b9920605","pubkey":"7c579328cf9028a4548d5117afa4f8448fb510ca9023f576b7bc90fc5be6ce7e","created_at":1674405882,"kind":1,"tags":[],"content":"GM gm gm! Currently bathing my brain in coffee ☕️ hahaha. How many other nostrinos love coffee? 🤪🤙","sig":"10262aa6a83e0b744cda2097f06f7354357512b82846f6ef23ef7d997136b64815c343b613a0635a27da7e628c96ac2475f66dd72513c1fb8ce6560824eb25b8"}]';
'["EVENT","0954524188078879",{"id":"da5107e5aa00978e0dd9bb3c09b2303af414fe4c10600b3c61bb938675d191af","kind":1,"pubkey":"da0cc82154bdf4ce8bf417eaa2d2fa99aa65c96c77867d6656fccdbf8e781b18","created_at":1675015235,"content":"#[0] test","tags":[["p","939ddb0c77d18ccd1ebb44c7a32b9cdc29b489e710c54db7cf1383ee86674a24"]],"sig":"f2b507e1039084d07477ccd2876ee0eb9e80f214be80e4e2ab28ad60dc5858297bbd9bf177be230b571c0015deb05c12eb02b659586fd3573cfa84c9292400b5"}]';
var msg = Message.deserialize(payload);
expect(msg.type, "EVENT");
expect(msg.message.id,
"a60679692533b308f1d862c2a5ca5c08a304e5157b1df5cde0ff0454b9920605");
"da5107e5aa00978e0dd9bb3c09b2303af414fe4c10600b3c61bb938675d191af");
});
test('REQ', () {
String payload =
Expand Down