nostr 0.5.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.adr-dir +1 -0
  3. data/.rubocop.yml +3 -1
  4. data/.rubocop_todo.yml +1 -1
  5. data/.tool-versions +2 -2
  6. data/CHANGELOG.md +63 -1
  7. data/README.md +6 -2
  8. data/adr/0001-record-architecture-decisions.md +19 -0
  9. data/adr/0002-introduction-of-signature-class.md +27 -0
  10. data/adr/0003-logging-methods-vs-logger-class.md +122 -0
  11. data/adr/0004-default-logging-activation.md +66 -0
  12. data/adr/0005-logger-types.md +32 -0
  13. data/docs/.vitepress/config.mjs +3 -0
  14. data/docs/bun.lockb +0 -0
  15. data/docs/common-use-cases/logging-and-debugging.md +60 -0
  16. data/docs/common-use-cases/signing-and-verifying-events.md +50 -0
  17. data/docs/common-use-cases/signing-and-verifying-messages.md +43 -0
  18. data/docs/core/client.md +1 -1
  19. data/docs/getting-started/overview.md +5 -1
  20. data/docs/index.md +0 -2
  21. data/docs/package.json +3 -3
  22. data/lib/nostr/client/color_logger.rb +69 -0
  23. data/lib/nostr/client/logger.rb +85 -0
  24. data/lib/nostr/client/plain_logger.rb +69 -0
  25. data/lib/nostr/client.rb +32 -6
  26. data/lib/nostr/crypto.rb +82 -6
  27. data/lib/nostr/errors/invalid_key_format_error.rb +1 -1
  28. data/lib/nostr/errors/invalid_key_length_error.rb +1 -1
  29. data/lib/nostr/errors/invalid_key_type_error.rb +1 -1
  30. data/lib/nostr/errors/invalid_signature_format_error.rb +18 -0
  31. data/lib/nostr/errors/invalid_signature_length_error.rb +18 -0
  32. data/lib/nostr/errors/invalid_signature_type_error.rb +16 -0
  33. data/lib/nostr/errors/signature_validation_error.rb +6 -0
  34. data/lib/nostr/errors.rb +4 -0
  35. data/lib/nostr/event.rb +36 -9
  36. data/lib/nostr/event_kind.rb +1 -0
  37. data/lib/nostr/events/encrypted_direct_message.rb +4 -4
  38. data/lib/nostr/filter.rb +10 -7
  39. data/lib/nostr/key.rb +2 -2
  40. data/lib/nostr/key_pair.rb +26 -2
  41. data/lib/nostr/keygen.rb +1 -1
  42. data/lib/nostr/signature.rb +67 -0
  43. data/lib/nostr/version.rb +1 -1
  44. data/lib/nostr.rb +3 -0
  45. data/nostr.gemspec +10 -10
  46. data/sig/nostr/client/color_logger.rbs +6 -0
  47. data/sig/nostr/client/logger.rbs +12 -0
  48. data/sig/nostr/client/plain_logger.rbs +6 -0
  49. data/sig/nostr/client.rbs +2 -0
  50. data/sig/nostr/crypto.rbs +3 -0
  51. data/sig/nostr/errors/invalid_signature_format_error.rbs +5 -0
  52. data/sig/nostr/errors/invalid_signature_length_error.rbs +5 -0
  53. data/sig/nostr/errors/invalid_signature_type_error.rbs +5 -0
  54. data/sig/nostr/errors/signature_validation_error.rbs +4 -0
  55. data/sig/nostr/event.rbs +7 -6
  56. data/sig/nostr/key_pair.rbs +1 -0
  57. data/sig/nostr/signature.rbs +14 -0
  58. data/sig/vendor/event_emitter.rbs +8 -10
  59. data/sig/vendor/schnorr/signature.rbs +16 -0
  60. data/sig/vendor/schnorr.rbs +3 -1
  61. metadata +48 -22
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nostr
4
+ class Client
5
+ # Logs connection events, messages sent and received, errors, and connection closures in color.
6
+ class ColorLogger < Logger
7
+ # Logs connection to a relay
8
+ #
9
+ # @api private
10
+ #
11
+ # @param [Nostr::Relay] relay The relay the client connected to.
12
+ #
13
+ # @return [void]
14
+ #
15
+ def on_connect(relay)
16
+ puts "\u001b[32m\u001b[1mConnected to the relay\u001b[22m #{relay.name} (#{relay.url})\u001b[0m"
17
+ end
18
+
19
+ # Logs a message received from the relay
20
+ #
21
+ # @api private
22
+ #
23
+ # @param [String] message The message received.
24
+ #
25
+ # @return [void]
26
+ #
27
+ def on_message(message)
28
+ puts "\u001b[32m\u001b[1m◄-\u001b[0m #{message}"
29
+ end
30
+
31
+ # Logs a message sent to the relay
32
+ #
33
+ # @api private
34
+ #
35
+ # @param [String] message The message sent.
36
+ #
37
+ # @return [void]
38
+ #
39
+ def on_send(message)
40
+ puts "\u001b[32m\u001b[1m-►\u001b[0m #{message}"
41
+ end
42
+
43
+ # Logs an error message
44
+ #
45
+ # @api private
46
+ #
47
+ # @param [String] message The error message.
48
+ #
49
+ # @return [void]
50
+ #
51
+ def on_error(message)
52
+ puts "\u001b[31m\u001b[1mError: \u001b[22m#{message}\u001b[0m"
53
+ end
54
+
55
+ # Logs a closure of connection with a relay
56
+ #
57
+ # @api private
58
+ #
59
+ # @param [String] code The closure code.
60
+ # @param [String] reason The reason for the closure.
61
+ #
62
+ # @return [void]
63
+ #
64
+ def on_close(code, reason)
65
+ puts "\u001b[31m\u001b[1mConnection closed: \u001b[22m#{reason} (##{code})\u001b[0m"
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nostr
4
+ class Client
5
+ # Logs connection events, messages sent and received, errors, and connection closures.
6
+ class Logger
7
+ # Attaches event handlers to the specified Nostr client for logging purposes
8
+ #
9
+ # @api public
10
+ #
11
+ # @example Attaching the logger to a client
12
+ # client = Nostr::Client.new
13
+ # logger = Nostr::Client::Logger.new
14
+ # logger.attach_to(client)
15
+ #
16
+ # # Now, actions like connecting, sending messages, receiving messages,
17
+ # # errors, and closing the connection will be logged to the console.
18
+ #
19
+ # @param [Nostr::Client] client The client to attach logging functionality to.
20
+ #
21
+ # @return [void]
22
+ #
23
+ def attach_to(client)
24
+ logger_instance = self
25
+
26
+ client.on(:connect) { |relay| logger_instance.on_connect(relay) }
27
+ client.on(:message) { |message| logger_instance.on_message(message) }
28
+ client.on(:send) { |message| logger_instance.on_send(message) }
29
+ client.on(:error) { |message| logger_instance.on_error(message) }
30
+ client.on(:close) { |code, reason| logger_instance.on_close(code, reason) }
31
+ end
32
+
33
+ # Logs connection to a relay
34
+ #
35
+ # @api private
36
+ #
37
+ # @param [Nostr::Relay] relay The relay the client connected to.
38
+ #
39
+ # @return [void]
40
+ #
41
+ def on_connect(relay); end
42
+
43
+ # Logs a message received from the relay
44
+ #
45
+ # @api private
46
+ #
47
+ # @param [String] message The message received.
48
+ #
49
+ # @return [void]
50
+ #
51
+ def on_message(message); end
52
+
53
+ # Logs a message sent to the relay
54
+ #
55
+ # @api private
56
+ #
57
+ # @param [String] message The message sent.
58
+ #
59
+ # @return [void]
60
+ #
61
+ def on_send(message); end
62
+
63
+ # Logs an error message
64
+ #
65
+ # @api private
66
+ #
67
+ # @param [String] message The error message.
68
+ #
69
+ # @return [void]
70
+ #
71
+ def on_error(message); end
72
+
73
+ # Logs a closure of connection with a relay
74
+ #
75
+ # @api private
76
+ #
77
+ # @param [String] code The closure code.
78
+ # @param [String] reason The reason for the closure.
79
+ #
80
+ # @return [void]
81
+ #
82
+ def on_close(code, reason); end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nostr
4
+ class Client
5
+ # Logs connection events, messages sent and received, errors, and connection closures.
6
+ class PlainLogger < Logger
7
+ # Logs connection to a relay
8
+ #
9
+ # @api private
10
+ #
11
+ # @param [Nostr::Relay] relay The relay the client connected to.
12
+ #
13
+ # @return [void]
14
+ #
15
+ def on_connect(relay)
16
+ puts "Connected to the relay #{relay.name} (#{relay.url})"
17
+ end
18
+
19
+ # Logs a message received from the relay
20
+ #
21
+ # @api private
22
+ #
23
+ # @param [String] message The message received.
24
+ #
25
+ # @return [void]
26
+ #
27
+ def on_message(message)
28
+ puts "◄- #{message}"
29
+ end
30
+
31
+ # Logs a message sent to the relay
32
+ #
33
+ # @api private
34
+ #
35
+ # @param [String] message The message sent.
36
+ #
37
+ # @return [void]
38
+ #
39
+ def on_send(message)
40
+ puts "-► #{message}"
41
+ end
42
+
43
+ # Logs an error message
44
+ #
45
+ # @api private
46
+ #
47
+ # @param [String] message The error message.
48
+ #
49
+ # @return [void]
50
+ #
51
+ def on_error(message)
52
+ puts "Error: #{message}"
53
+ end
54
+
55
+ # Logs a closure of connection with a relay
56
+ #
57
+ # @api private
58
+ #
59
+ # @param [String] code The closure code.
60
+ # @param [String] reason The reason for the closure.
61
+ #
62
+ # @return [void]
63
+ #
64
+ def on_close(code, reason)
65
+ puts "Connection closed: #{reason} (##{code})"
66
+ end
67
+ end
68
+ end
69
+ end
data/lib/nostr/client.rb CHANGED
@@ -18,11 +18,19 @@ module Nostr
18
18
  # @api public
19
19
  #
20
20
  # @example Instantiating a client that logs all the events it sends and receives
21
- # client = Nostr::Client.new(debug: true)
21
+ # client = Nostr::Client.new
22
22
  #
23
- def initialize
23
+ # @example Instantiating a client with no logging
24
+ # client = Nostr::Client.new(logger: nil)
25
+ #
26
+ # @example Instantiating a client with your own logger
27
+ # client = Nostr::Client.new(logger: YourLogger.new)
28
+ #
29
+ def initialize(logger: ColorLogger.new)
24
30
  @subscriptions = {}
31
+ @logger = logger
25
32
 
33
+ logger&.attach_to(self)
26
34
  initialize_channels
27
35
  end
28
36
 
@@ -40,11 +48,11 @@ module Nostr
40
48
  #
41
49
  def connect(relay)
42
50
  execute_within_an_em_thread do
43
- client = Faye::WebSocket::Client.new(relay.url, [], { tls: { verify_peer: false } })
44
- parent_to_child_channel.subscribe { |msg| client.send(msg) }
51
+ client = build_websocket_client(relay.url)
52
+ parent_to_child_channel.subscribe { |msg| client.send(msg) && emit(:send, msg) }
45
53
 
46
54
  client.on :open do
47
- child_to_parent_channel.push(type: :open)
55
+ child_to_parent_channel.push(type: :open, relay:)
48
56
  end
49
57
 
50
58
  client.on :message do |event|
@@ -122,6 +130,14 @@ module Nostr
122
130
 
123
131
  private
124
132
 
133
+ # The logger that prints all the events that the client sends and receives
134
+ #
135
+ # @api private
136
+ #
137
+ # @return [ClientLogger]
138
+ #
139
+ attr_reader :logger
140
+
125
141
  # The subscriptions that the client has created
126
142
  #
127
143
  # @api private
@@ -167,11 +183,21 @@ module Nostr
167
183
  @child_to_parent_channel = EventMachine::Channel.new
168
184
 
169
185
  child_to_parent_channel.subscribe do |msg|
170
- emit :connect if msg[:type] == :open
186
+ emit :connect, msg[:relay] if msg[:type] == :open
171
187
  emit :message, msg[:data] if msg[:type] == :message
172
188
  emit :error, msg[:message] if msg[:type] == :error
173
189
  emit :close, msg[:code], msg[:reason] if msg[:type] == :close
174
190
  end
175
191
  end
192
+
193
+ # Builds a websocket client
194
+ #
195
+ # @api private
196
+ #
197
+ # @return [Faye::WebSocket::Client]
198
+ #
199
+ def build_websocket_client(relay_url)
200
+ Faye::WebSocket::Client.new(relay_url, [], { tls: { verify_peer: false } })
201
+ end
176
202
  end
177
203
  end
data/lib/nostr/crypto.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nostr
4
- # Performs cryptographic operations on a +Nostr::Event+.
4
+ # Performs cryptographic operations.
5
5
  class Crypto
6
6
  # Numeric base of the OpenSSL big number used in an event content's encryption.
7
7
  #
@@ -90,17 +90,93 @@ module Nostr
90
90
  #
91
91
  def sign_event(event, private_key)
92
92
  event_digest = hash_event(event)
93
-
94
- hex_private_key = Array(private_key).pack('H*')
95
- hex_message = Array(event_digest).pack('H*')
96
- event_signature = Schnorr.sign(hex_message, hex_private_key).encode.unpack1('H*')
93
+ signature = sign_message(event_digest, private_key)
97
94
 
98
95
  event.id = event_digest
99
- event.sig = event_signature
96
+ event.sig = signature
100
97
 
101
98
  event
102
99
  end
103
100
 
101
+ # Signs a message using the Schnorr signature algorithm
102
+ #
103
+ # @api public
104
+ #
105
+ # @example Signing a message
106
+ # crypto = Nostr::Crypto.new
107
+ # message = 'Viva la libertad carajo'
108
+ # private_key = Nostr::PrivateKey.new('7d1e4219a5e7d8342654c675085bfbdee143f0eb0f0921f5541ef1705a2b407d')
109
+ # signature = crypto.sign_message(message, private_key)
110
+ # signature # => 'b2115694a576f5bdcebf8c0951a3c7adcfbdb17b11cb9e6d6b7017691138bc6' \
111
+ # '38fee642a7bd26f71b313a7057181294198900a9770d1435e43f182acf3d34c26'
112
+ #
113
+ # @param [String] message The message to be signed
114
+ # @param [PrivateKey] private_key The private key used for signing
115
+ #
116
+ # @return [Signature] A signature object containing the signature as a 64-byte hexadecimal string.
117
+ #
118
+ def sign_message(message, private_key)
119
+ hex_private_key = Array(private_key).pack('H*')
120
+ hex_message = Array(message).pack('H*')
121
+ hex_signature = Schnorr.sign(hex_message, hex_private_key).encode.unpack1('H*')
122
+
123
+ Signature.new(hex_signature.to_s)
124
+ end
125
+
126
+ # Verifies the given {Signature} and returns true if it is valid
127
+ #
128
+ # @api public
129
+ #
130
+ # @example Checking a signature
131
+ # public_key = Nostr::PublicKey.new('15678d8fbc126fa326fac536acd5a6dcb5ef64b3d939abe31d6830cba6cd26d6')
132
+ # private_key = Nostr::PrivateKey.new('7d1e4219a5e7d8342654c675085bfbdee143f0eb0f0921f5541ef1705a2b407d')
133
+ # message = 'Viva la libertad carajo'
134
+ # crypto = Nostr::Crypto.new
135
+ # signature = crypto.sign_message(message, private_key)
136
+ # valid = crypto.valid_sig?(message, public_key, signature)
137
+ # valid # => true
138
+ #
139
+ # @see #check_sig!
140
+ #
141
+ # @param [String] message A message to be signed with binary format.
142
+ # @param [PublicKey] public_key The public key with binary format.
143
+ # @param [Signature] signature The signature with binary format.
144
+ #
145
+ # @return [Boolean] whether signature is valid.
146
+ #
147
+ def valid_sig?(message, public_key, signature)
148
+ signature = Schnorr::Signature.decode([signature].pack('H*'))
149
+ Schnorr.valid_sig?([message].pack('H*'), [public_key].pack('H*'), signature.encode)
150
+ end
151
+
152
+ # Verifies the given {Signature} and raises an +Schnorr::InvalidSignatureError+ if it is invalid
153
+ #
154
+ # @api public
155
+ #
156
+ # @example Checking a signature
157
+ # public_key = Nostr::PublicKey.new('15678d8fbc126fa326fac536acd5a6dcb5ef64b3d939abe31d6830cba6cd26d6')
158
+ # private_key = Nostr::PrivateKey.new('7d1e4219a5e7d8342654c675085bfbdee143f0eb0f0921f5541ef1705a2b407d')
159
+ # message = 'Viva la libertad carajo'
160
+ # crypto = Nostr::Crypto.new
161
+ # signature = crypto.sign_message(message, private_key)
162
+ # valid = crypto.valid_sig?(message, public_key, signature)
163
+ # valid # => true
164
+ #
165
+ # @see #valid_sig?
166
+ #
167
+ # @param [String] message A message to be signed with binary format.
168
+ # @param [PublicKey] public_key The public key with binary format.
169
+ # @param [Signature] signature The signature with binary format.
170
+ #
171
+ # @raise [Schnorr::InvalidSignatureError] if the signature is invalid.
172
+ #
173
+ # @return [Boolean] whether signature is valid.
174
+ #
175
+ def check_sig!(message, public_key, signature)
176
+ signature = Schnorr::Signature.decode([signature].pack('H*'))
177
+ Schnorr.check_sig!([message].pack('H*'), [public_key].pack('H*'), signature.encode)
178
+ end
179
+
104
180
  private
105
181
 
106
182
  # Finds a shared key between two keys
@@ -9,7 +9,7 @@ module Nostr
9
9
  # Initializes the error
10
10
  #
11
11
  # @example
12
- # InvalidKeyFormatError.new('private'')
12
+ # InvalidKeyFormatError.new('private')
13
13
  #
14
14
  # @param [String] key_kind The kind of key that is invalid (public or private)
15
15
  #
@@ -9,7 +9,7 @@ module Nostr
9
9
  # Initializes the error
10
10
  #
11
11
  # @example
12
- # InvalidKeyLengthError.new('private'')
12
+ # InvalidKeyLengthError.new('private')
13
13
  #
14
14
  # @param [String] key_kind The kind of key that is invalid (public or private)
15
15
  #
@@ -9,7 +9,7 @@ module Nostr
9
9
  # Initializes the error
10
10
  #
11
11
  # @example
12
- # InvalidKeyTypeError.new('private'')
12
+ # InvalidKeyTypeError.new('private')
13
13
  #
14
14
  # @param [String] key_kind The kind of key that is invalid (public or private)
15
15
  #
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nostr
4
+ # Raised when the signature is in an invalid format
5
+ #
6
+ # @api public
7
+ #
8
+ class InvalidSignatureFormatError < SignatureValidationError
9
+ # Initializes the error
10
+ #
11
+ # @example
12
+ # InvalidSignatureFormatError.new
13
+ #
14
+ def initialize
15
+ super('Only lowercase hexadecimal characters are allowed in signatures.')
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nostr
4
+ # Raised when the signature's length is not 128 characters
5
+ #
6
+ # @api public
7
+ #
8
+ class InvalidSignatureLengthError < SignatureValidationError
9
+ # Initializes the error
10
+ #
11
+ # @example
12
+ # InvalidSignatureLengthError.new
13
+ #
14
+ def initialize
15
+ super('Invalid signature length. It should have 128 characters.')
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nostr
4
+ # Raised when the signature is not a string
5
+ #
6
+ # @api public
7
+ #
8
+ class InvalidSignatureTypeError < SignatureValidationError
9
+ # Initializes the error
10
+ #
11
+ # @example
12
+ # InvalidSignatureTypeError.new
13
+ #
14
+ def initialize = super('Invalid signature type. It must be a string with lowercase hexadecimal characters.')
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nostr
4
+ # Base class for all signature validation errors
5
+ class SignatureValidationError < Error; end
6
+ end
data/lib/nostr/errors.rb CHANGED
@@ -6,3 +6,7 @@ require_relative 'errors/invalid_hrp_error'
6
6
  require_relative 'errors/invalid_key_type_error'
7
7
  require_relative 'errors/invalid_key_length_error'
8
8
  require_relative 'errors/invalid_key_format_error'
9
+ require_relative 'errors/signature_validation_error'
10
+ require_relative 'errors/invalid_signature_type_error'
11
+ require_relative 'errors/invalid_signature_length_error'
12
+ require_relative 'errors/invalid_signature_format_error'
data/lib/nostr/event.rb CHANGED
@@ -100,15 +100,15 @@ module Nostr
100
100
  #
101
101
  # @example Instantiating a new event
102
102
  # Nostr::Event.new(
103
- # id: 'ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460',
104
- # pubkey: '48df4af6e240ac5f7c5de89bf5941b249880be0e87d03685b178ccb1a315f52e',
105
- # created_at: 1230981305,
106
- # kind: 1,
107
- # tags: [],
108
- # content: 'Your feedback is appreciated, now pay $8',
109
- # sig: '123ac2923b792ce730b3da34f16155470ab13c8f97f9c53eaeb334f1fb3a5dc9a7f643
110
- # 937c6d6e9855477638f5655c5d89c9aa5501ea9b578a66aced4f1cd7b3'
111
- # )
103
+ # id: 'ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460',
104
+ # pubkey: '48df4af6e240ac5f7c5de89bf5941b249880be0e87d03685b178ccb1a315f52e',
105
+ # created_at: 1230981305,
106
+ # kind: 1,
107
+ # tags: [],
108
+ # content: 'Your feedback is appreciated, now pay $8',
109
+ # sig: '123ac2923b792ce730b3da34f16155470ab13c8f97f9c53eaeb334f1fb3a5dc9a7f643
110
+ # 937c6d6e9855477638f5655c5d89c9aa5501ea9b578a66aced4f1cd7b3'
111
+ # )
112
112
  #
113
113
  # @param id [String|nil] 32-bytes sha256 of the the serialized event data.
114
114
  # @param sig [String|nil] 64-bytes signature of the sha256 hash of the serialized event data, which is
@@ -181,6 +181,33 @@ module Nostr
181
181
  crypto.sign_event(self, private_key)
182
182
  end
183
183
 
184
+ # Verifies if the signature of the event is valid. A valid signature means that the event was signed by the owner
185
+ #
186
+ # @api public
187
+ #
188
+ # @example Verifying the signature of an event
189
+ # event = Nostr::Event.new(
190
+ # id: '90b75b78daf883ae57fbcc414d43faa028560b3211ee58e4ea82bf395bb82042',
191
+ # pubkey: Nostr::PublicKey.new('2d7661527d573cc8e84f665fa971dd969ba51e2526df00c149ff8e40a58f9558'),
192
+ # created_at: 1667422587,
193
+ # kind: Nostr::EventKind::TEXT_NOTE,
194
+ # content: 'Your feedback is appreciated, now pay $8',
195
+ # sig: '32f18adebe942e19b171c1c7d2fb27ce794dfea4155e289dca7952b43ed1ec39' \
196
+ # '1d3dc198ba2761bc6d40c737a6eaf4edcc8963acabd3bfcebd04f16637025bdc'
197
+ # )
198
+ #
199
+ # event.verify_signature # => true
200
+ #
201
+ # @return [Boolean] Whether the signature is valid or not.
202
+ #
203
+ def verify_signature
204
+ crypto = Crypto.new
205
+
206
+ return false if id.nil? || pubkey.nil? || sig.nil?
207
+
208
+ crypto.valid_sig?(id, pubkey, sig)
209
+ end
210
+
184
211
  # Serializes the event, to obtain a SHA256 digest of it
185
212
  #
186
213
  # @api public
@@ -21,6 +21,7 @@ module Nostr
21
21
  # The content is set to the URL (e.g., wss://somerelay.com) of a relay the event creator wants to
22
22
  # recommend to its followers.
23
23
  #
24
+ # @deprecated This event kind was removed in https://github.com/nostr-protocol/nips/pull/703/files#diff-39307f1617417657ee9874be314f13aabdc74401b124d0afe8217f2919c9c7d8L105
24
25
  # @return [Integer]
25
26
  #
26
27
  RECOMMEND_SERVER = 2
@@ -11,19 +11,19 @@ module Nostr
11
11
  # @api public
12
12
  #
13
13
  # @example Instantiating a new encrypted direct message
14
- # Nostr::Events::EncryptedDirectMessage.new(
14
+ # Nostr::Events::EncryptedDirectMessage.new(
15
15
  # sender_private_key: 'ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460',
16
16
  # recipient_public_key: '48df4af6e240ac5f7c5de89bf5941b249880be0e87d03685b178ccb1a315f52e',
17
17
  # plain_text: 'Your feedback is appreciated, now pay $8',
18
- # )
18
+ # )
19
19
  #
20
20
  # @example Instantiating a new encrypted direct message that references a previous direct message
21
- # Nostr::Events::EncryptedDirectMessage.new(
21
+ # Nostr::Events::EncryptedDirectMessage.new(
22
22
  # sender_private_key: 'ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460',
23
23
  # recipient_public_key: '48df4af6e240ac5f7c5de89bf5941b249880be0e87d03685b178ccb1a315f52e',
24
24
  # plain_text: 'Your feedback is appreciated, now pay $8',
25
25
  # previous_direct_message: 'ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460'
26
- # )
26
+ # )
27
27
  #
28
28
  # @param plain_text [String] The +content+ of the encrypted message.
29
29
  # @param sender_private_key [PrivateKey] 32-bytes hex-encoded private key of the message's author.
data/lib/nostr/filter.rb CHANGED
@@ -133,13 +133,16 @@ module Nostr
133
133
  # @api public
134
134
  #
135
135
  # @example
136
- # filter.to_h # => {:ids=>["c24881c305c5cfb7c1168be7e9b0e150"],
137
- # :authors=>["000000001c5c45196786e79f83d21fe801549fdc98e2c26f96dcef068a5dbcd7"],
138
- # :kinds=>[0, 1, 2],
139
- # :"#e"=>["7bdb422f254194ae4bb86d354c0bd5a888fce233ffc77dceb3e844ceec1fcfb2"],
140
- # :"#p"=>["000000001c5c45196786e79f83d21fe801549fdc98e2c26f96dcef068a5dbcd7"],
141
- # :since=>1230981305,
142
- # :until=>1292190341}
136
+ # filter.to_h # =>
137
+ # {
138
+ # ids: ['c24881c305c5cfb7c1168be7e9b0e150'],
139
+ # authors: ['000000001c5c45196786e79f83d21fe801549fdc98e2c26f96dcef068a5dbcd7'],
140
+ # kinds: [0, 1, 2],
141
+ # '#e': ['7bdb422f254194ae4bb86d354c0bd5a888fce233ffc77dceb3e844ceec1fcfb2'],
142
+ # '#p': ['000000001c5c45196786e79f83d21fe801549fdc98e2c26f96dcef068a5dbcd7'],
143
+ # since: 1230981305,
144
+ # until: 1292190341
145
+ # }
143
146
  #
144
147
  # @return [Hash] The filter as a hash.
145
148
  #
data/lib/nostr/key.rb CHANGED
@@ -18,14 +18,14 @@ module Nostr
18
18
  #
19
19
  LENGTH = 64
20
20
 
21
- # Instantiates a new key. Can't be used directly because this is an abstract class. Raises a +ValidationError+
21
+ # Instantiates a new key. Can't be used directly because this is an abstract class. Raises a +KeyValidationError+
22
22
  #
23
23
  # @see Nostr::PrivateKey
24
24
  # @see Nostr::PublicKey
25
25
  #
26
26
  # @param [String] hex_value Hex-encoded value of the key
27
27
  #
28
- # @raise [ValidationError]
28
+ # @raise [KeyValidationError]
29
29
  #
30
30
  def initialize(hex_value)
31
31
  validate_hex_value(hex_value)