nostr 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)