nostr 0.2.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nostr
4
+ # Classes of event kinds.
5
+ module Events
6
+ # An event whose +content+ is encrypted. It can only be decrypted by the owner of the private key that pairs
7
+ # the event's +pubkey+.
8
+ class EncryptedDirectMessage < Event
9
+ # Instantiates a new encrypted direct message
10
+ #
11
+ # @api public
12
+ #
13
+ # @example Instantiating a new encrypted direct message
14
+ # Nostr::Events::EncryptedDirectMessage.new(
15
+ # sender_private_key: 'ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460',
16
+ # recipient_public_key: '48df4af6e240ac5f7c5de89bf5941b249880be0e87d03685b178ccb1a315f52e',
17
+ # plain_text: 'Your feedback is appreciated, now pay $8',
18
+ # )
19
+ #
20
+ # @example Instantiating a new encrypted direct message that references a previous direct message
21
+ # Nostr::Events::EncryptedDirectMessage.new(
22
+ # sender_private_key: 'ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460',
23
+ # recipient_public_key: '48df4af6e240ac5f7c5de89bf5941b249880be0e87d03685b178ccb1a315f52e',
24
+ # plain_text: 'Your feedback is appreciated, now pay $8',
25
+ # previous_direct_message: 'ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460'
26
+ # )
27
+ #
28
+ # @param plain_text [String] The +content+ of the encrypted message.
29
+ # @param sender_private_key [String] 32-bytes hex-encoded private key of the message's author.
30
+ # @param recipient_public_key [String] 32-bytes hex-encoded public key of the recipient of the encrypted message.
31
+ # @param previous_direct_message [String] 32-bytes hex-encoded id identifying the previous message in a
32
+ # conversation or a message we are explicitly replying to (such that contextual, more organized conversations
33
+ # may happen
34
+ #
35
+ def initialize(plain_text:, sender_private_key:, recipient_public_key:, previous_direct_message: nil)
36
+ crypto = Crypto.new
37
+ keygen = Keygen.new
38
+
39
+ encrypted_content = crypto.encrypt_text(sender_private_key, recipient_public_key, plain_text)
40
+ sender_public_key = keygen.extract_public_key(sender_private_key)
41
+
42
+ super(
43
+ pubkey: sender_public_key,
44
+ kind: Nostr::EventKind::ENCRYPTED_DIRECT_MESSAGE,
45
+ content: encrypted_content,
46
+ )
47
+
48
+ add_pubkey_reference(recipient_public_key)
49
+ add_event_reference(previous_direct_message) if previous_direct_message
50
+ end
51
+ end
52
+ end
53
+ end
data/lib/nostr/keygen.rb CHANGED
@@ -62,7 +62,7 @@ module Nostr
62
62
  # @return [String] A 32-bytes hex-encoded public key.
63
63
  #
64
64
  def extract_public_key(private_key)
65
- group.generator.multiply_by_scalar(private_key.to_i(16)).x.to_s(16)
65
+ group.generator.multiply_by_scalar(private_key.to_i(16)).x.to_s(16).rjust(64, '0')
66
66
  end
67
67
 
68
68
  private
data/lib/nostr/user.rb CHANGED
@@ -50,43 +50,15 @@ module Nostr
50
50
  # @param event_attributes [Hash]
51
51
  # @option event_attributes [String] :pubkey 32-bytes hex-encoded public key of the event creator.
52
52
  # @option event_attributes [Integer] :created_at Date of the creation of the vent. A UNIX timestamp, in seconds.
53
- # @option event_attributes [Integer] :kind The kind of the event. An integer from 0 to 2.
53
+ # @option event_attributes [Integer] :kind The kind of the event. An integer from 0 to 3.
54
54
  # @option event_attributes [Array<Array>] :tags An array of tags. Each tag is an array of strings.
55
55
  # @option event_attributes [String] :content Arbitrary string.
56
56
  #
57
57
  # @return [Event]
58
58
  #
59
59
  def create_event(event_attributes)
60
- event_fragment = EventFragment.new(**event_attributes.merge(pubkey: keypair.public_key))
61
- event_sha256 = Digest::SHA256.hexdigest(JSON.dump(event_fragment.serialize))
62
-
63
- signature = sign(event_sha256)
64
-
65
- Event.new(
66
- id: event_sha256,
67
- pubkey: event_fragment.pubkey,
68
- created_at: event_fragment.created_at,
69
- kind: event_fragment.kind,
70
- tags: event_fragment.tags,
71
- content: event_fragment.content,
72
- sig: signature
73
- )
74
- end
75
-
76
- private
77
-
78
- # Signs an event with the user's private key
79
- #
80
- # @api private
81
- #
82
- # @param event_sha256 [String] The SHA256 hash of the event.
83
- #
84
- # @return [String] The signature of the event.
85
- #
86
- def sign(event_sha256)
87
- hex_private_key = Array(keypair.private_key).pack('H*')
88
- hex_message = Array(event_sha256).pack('H*')
89
- Schnorr.sign(hex_message, hex_private_key).encode.unpack1('H*')
60
+ event = Event.new(**event_attributes.merge(pubkey: keypair.public_key))
61
+ event.sign(keypair.private_key)
90
62
  end
91
63
  end
92
64
  end
data/lib/nostr/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Nostr
4
4
  # The version of the gem
5
- VERSION = '0.2.0'
5
+ VERSION = '0.4.0'
6
6
  end
data/lib/nostr.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'nostr/crypto'
3
4
  require_relative 'nostr/version'
4
5
  require_relative 'nostr/keygen'
5
6
  require_relative 'nostr/client_message_type'
@@ -8,8 +9,8 @@ require_relative 'nostr/subscription'
8
9
  require_relative 'nostr/relay'
9
10
  require_relative 'nostr/key_pair'
10
11
  require_relative 'nostr/event_kind'
11
- require_relative 'nostr/event_fragment'
12
12
  require_relative 'nostr/event'
13
+ require_relative 'nostr/events/encrypted_direct_message'
13
14
  require_relative 'nostr/client'
14
15
  require_relative 'nostr/user'
15
16
 
data/nostr.gemspec CHANGED
@@ -50,12 +50,15 @@ Gem::Specification.new do |spec|
50
50
  spec.add_development_dependency 'puma', '~> 5.6'
51
51
  spec.add_development_dependency 'rack', '~> 3.0'
52
52
  spec.add_development_dependency 'rake', '~> 13.0'
53
+ spec.add_development_dependency 'rbs', '~> 2.8'
53
54
  spec.add_development_dependency 'rspec', '~> 3.12'
54
55
  spec.add_development_dependency 'rubocop', '~> 1.42'
55
56
  spec.add_development_dependency 'rubocop-rake', '~> 0.6'
56
57
  spec.add_development_dependency 'rubocop-rspec', '2.16'
57
58
  spec.add_development_dependency 'simplecov', '= 0.17'
58
59
  spec.add_development_dependency 'simplecov-console', '~> 0.9'
60
+ spec.add_development_dependency 'steep', '~> 1.3'
61
+ spec.add_development_dependency 'typeprof', '~> 0.21'
59
62
  spec.add_development_dependency 'yard', '~> 0.9'
60
63
  spec.add_development_dependency 'yard-junk', '~> 0.0.9'
61
64
  spec.add_development_dependency 'yardstick', '~> 0.9'
@@ -0,0 +1,20 @@
1
+ module Nostr
2
+ class Client
3
+ include EventEmitter
4
+
5
+ def initialize: -> void
6
+ def connect: (Relay relay) -> Thread
7
+ def subscribe: (?subscription_id: String, ?filter: Filter) -> Subscription
8
+ def unsubscribe: (String subscription_id) -> untyped
9
+ def publish: (Event event) -> untyped
10
+
11
+ private
12
+
13
+ attr_reader subscriptions: Hash[String, Subscription]
14
+ attr_reader parent_to_child_channel: untyped
15
+ attr_reader child_to_parent_channel: untyped
16
+
17
+ def execute_within_an_em_thread: { -> untyped } -> Thread
18
+ def initialize_channels: -> untyped
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ module Nostr
2
+ module ClientMessageType
3
+ EVENT: String
4
+ REQ: String
5
+ CLOSE: String
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ module Nostr
2
+ class Crypto
3
+ BN_BASE: Integer
4
+ CIPHER_CURVE: String
5
+ CIPHER_ALGORITHM: String
6
+
7
+ def encrypt_text: (String, String, String) -> String
8
+ def decrypt_text: (String, String, String) -> String
9
+ def sign_event: (Event, String) -> Event
10
+
11
+ private
12
+
13
+ def compute_shared_key: (String, String) -> String
14
+ def hash_event:(Event) -> String
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module Nostr
2
+ class Event
3
+ attr_reader pubkey: String
4
+ attr_reader created_at: Integer
5
+ attr_reader kind: Integer
6
+ attr_reader tags: Array[Array[String]]
7
+ attr_reader content: String
8
+ attr_accessor id: String?|nil
9
+ attr_accessor sig: String?|nil
10
+
11
+ def initialize: (
12
+ pubkey: String,
13
+ kind: Integer,
14
+ content: String,
15
+ ?created_at: Integer,
16
+ ?tags: Array[Array[String]],
17
+ ?id: String|nil,
18
+ ?sig: String|nil
19
+ ) -> void
20
+
21
+ def serialize: -> [Integer, String, Integer, Integer, Array[Array[String]], String]
22
+
23
+ def to_h: -> {
24
+ id: String?|nil,
25
+ pubkey: String,
26
+ created_at: Integer,
27
+ kind: Integer,
28
+ tags: Array[Array[String]],
29
+ content: String,
30
+ sig: String?|nil
31
+ }
32
+ def ==: (Event other) -> bool
33
+
34
+ def sign:(String) -> Event
35
+
36
+ def add_event_reference: (String) -> Array[Array[String]]
37
+ def add_pubkey_reference: (String) -> Array[Array[String]]
38
+ end
39
+ end
@@ -0,0 +1,9 @@
1
+ module Nostr
2
+ module EventKind
3
+ SET_METADATA: Integer
4
+ TEXT_NOTE: Integer
5
+ RECOMMEND_SERVER: Integer
6
+ CONTACT_LIST: Integer
7
+ ENCRYPTED_DIRECT_MESSAGE: Integer
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ module Nostr
2
+ module Events
3
+ class EncryptedDirectMessage < Event
4
+ def initialize: (
5
+ plain_text: String,
6
+ sender_private_key: String,
7
+ recipient_public_key: String,
8
+ ?previous_direct_message: String|nil
9
+ ) -> void
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ module Nostr
2
+ class Filter
3
+ attr_reader ids: Array[String]
4
+ attr_reader authors: Array[String]
5
+ attr_reader kinds: Array[Integer]
6
+ attr_reader e: String
7
+ attr_reader p: String
8
+ attr_reader since: Integer
9
+ attr_reader until: Integer
10
+ attr_reader limit: Integer
11
+
12
+ def initialize: (**untyped) -> void
13
+ def to_h: -> {
14
+ ids: Array[String],
15
+ authors: Array[String],
16
+ kinds: Array[Integer],
17
+ e: String,
18
+ p: String,
19
+ since: Integer,
20
+ until: Integer,
21
+ limit: Integer
22
+ }
23
+ def ==: (Filter other) -> bool
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ # Classes
2
+ module Nostr
3
+ class KeyPair
4
+ attr_reader private_key: String
5
+ attr_reader public_key: String
6
+
7
+ def initialize: (private_key: String, public_key: String) -> void
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ # Classes
2
+ module Nostr
3
+ class Keygen
4
+ def initialize: -> void
5
+ def generate_key_pair: -> KeyPair
6
+ def generate_private_key: -> String
7
+ def extract_public_key: (String private_key) -> String
8
+
9
+ private
10
+
11
+ attr_reader group: untyped
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ # Classes
2
+ module Nostr
3
+ class Relay
4
+ attr_reader url: String
5
+ attr_reader name: String
6
+
7
+ def initialize: (url: String, name: String) -> void
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Nostr
2
+ class Subscription
3
+ attr_reader id: String
4
+ attr_reader filter: Filter
5
+
6
+ def initialize: (filter: Filter, ?id: String) -> void
7
+ def ==: (Subscription other) -> bool
8
+ end
9
+ end
@@ -0,0 +1,22 @@
1
+ # Classes
2
+ module Nostr
3
+ class User
4
+ attr_reader keypair: KeyPair
5
+
6
+ def initialize: (?keypair: KeyPair | nil, ?keygen: Keygen) -> void
7
+ def create_event: (
8
+ {
9
+ pubkey: String,
10
+ created_at: Integer,
11
+ kind: Integer,
12
+ tags: Array[String],
13
+ content: String,
14
+ created_at: Integer,
15
+ }
16
+ ) -> Event
17
+
18
+ private
19
+
20
+ def sign: (String event_sha256) -> String
21
+ end
22
+ end
@@ -0,0 +1,6 @@
1
+ # Added only to satisfy the Steep requirements. Not 100% reliable.
2
+ module ECDSA
3
+ class Group
4
+ Secp256k1: Group
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ # Added only to satisfy the Steep requirements. Not 100% reliable.
2
+ module EventEmitter
3
+ def add_listener: (untyped `type`, ?{once: true} params) -> Integer
4
+ alias on add_listener
5
+
6
+ def remove_listener: (untyped id_or_type) -> Array[untyped]?
7
+ def emit: (untyped `type`, *untyped data) -> Array[untyped]
8
+ def once: (untyped `type`) -> Integer
9
+ end
@@ -0,0 +1,18 @@
1
+ # Added only to satisfy the Steep requirements. Not 100% reliable.
2
+ module EventMachine
3
+ class Channel
4
+ @subs: Hash[untyped, untyped]
5
+ @uid: Integer
6
+
7
+ def initialize: -> void
8
+ def num_subscribers: -> Integer
9
+ def subscribe: (*untyped a) ?{ -> untyped } -> Integer
10
+ def unsubscribe: (untyped name) -> untyped
11
+ def push: (*untyped items) -> untyped
12
+ alias << push
13
+ def pop: (*untyped a) -> untyped
14
+
15
+ private
16
+ def gen_id: -> Integer
17
+ end
18
+ end
@@ -0,0 +1,69 @@
1
+ # Added only to satisfy the Steep requirements. Not 100% reliable.
2
+ module EventMachine
3
+ ERRNOS: Hash[untyped, untyped]
4
+ P: untyped
5
+ self.@next_tick_mutex: Thread::Mutex
6
+ self.@reactor_running: bool
7
+ self.@next_tick_queue: Array[^-> untyped]
8
+ self.@tails: Array[nil]
9
+ self.@resultqueue: (Array[untyped] | Thread::Queue)?
10
+ self.@threadqueue: Thread::Queue?
11
+ self.@threadpool: Array[untyped]?
12
+ self.@all_threads_spawned: bool
13
+ self.@reactor_pid: Integer
14
+ self.@conns: Hash[untyped, untyped]
15
+ self.@acceptors: Hash[untyped, Array[(Array[untyped] | Integer)?]]
16
+ self.@timers: Hash[untyped, Integer | ^-> untyped | false]
17
+ self.@wrapped_exception: Exception?
18
+ self.@reactor_thread: Thread?
19
+ self.@threadpool_size: bot
20
+ self.@error_handler: bot
21
+
22
+ def self.run: (?untyped blk, ?nil tail) ?{ -> untyped } -> nil
23
+ def self.run_block: -> nil
24
+ def self.reactor_thread?: -> bool
25
+ def self.schedule: (*untyped a) -> nil
26
+ def self.fork_reactor: -> Integer?
27
+ def self.cleanup_machine: -> Array[untyped]
28
+ def self.add_shutdown_hook: -> Array[nil]
29
+ def self.add_timer: (*Integer | ^-> untyped args) ?{ -> untyped } -> nil
30
+ def self.add_periodic_timer: (*untyped args) -> untyped
31
+ def self.cancel_timer: (untyped timer_or_sig) -> false?
32
+ def self.stop_event_loop: -> untyped
33
+ def self.start_server: (untyped server, ?nil port, ?nil handler, *untyped args) -> untyped
34
+ def self.attach_server: (untyped sock, ?nil handler, *untyped args) -> untyped
35
+ def self.stop_server: (untyped signature) -> untyped
36
+ def self.start_unix_domain_server: (untyped filename, *untyped args) -> untyped
37
+ def self.connect: (untyped server, ?nil port, ?nil handler, *untyped args) -> untyped
38
+ def self.bind_connect: (nil bind_addr, nil bind_port, untyped server, ?nil port, ?nil handler, *untyped args) -> untyped
39
+ def self.watch: (untyped io, ?nil handler, *untyped args) -> untyped
40
+ def self.attach: (untyped io, ?nil handler, *untyped args) -> untyped
41
+ def self.attach_io: (untyped io, bool watch_mode, ?nil handler, *untyped args) -> untyped
42
+ def self.reconnect: (untyped server, untyped port, untyped handler) -> untyped
43
+ def self.connect_unix_domain: (untyped socketname, *untyped args) -> untyped
44
+ def self.open_datagram_socket: (untyped address, untyped port, ?nil handler, *untyped args) -> untyped
45
+ def self.set_quantum: (untyped mills) -> untyped
46
+ def self.set_max_timers: (untyped ct) -> untyped
47
+ def self.get_max_timers: -> untyped
48
+ def self.connection_count: -> untyped
49
+ def self.run_deferred_callbacks: -> Integer
50
+ def self.defer: (?nil op, ?nil callback, ?nil errback) -> untyped
51
+ def self.spawn_threadpool: -> true
52
+ def self.defers_finished?: -> bool
53
+ def self.next_tick: (?nil pr) { -> nil } -> nil
54
+ def self.set_effective_user: (untyped username) -> untyped
55
+ def self.set_descriptor_table_size: (?nil n_descriptors) -> untyped
56
+ def self.popen: (untyped cmd, ?nil handler, *untyped args) -> untyped
57
+ def self.reactor_running?: -> bool
58
+ def self.open_keyboard: (?nil handler, *untyped args) -> untyped
59
+ def self.watch_file: (untyped filename, ?nil handler, *untyped args) -> untyped
60
+ def self.watch_process: (untyped pid, ?nil handler, *untyped args) -> untyped
61
+ def self.error_handler: (?nil cb) -> nil
62
+ def self.enable_proxy: (untyped from, untyped to, ?Integer bufsize, ?Integer length) -> untyped
63
+ def self.disable_proxy: (untyped from) -> untyped
64
+ def self.heartbeat_interval: -> untyped
65
+ def self.heartbeat_interval=: (untyped time) -> untyped
66
+ def self.event_callback: (untyped conn_binding, untyped opcode, untyped data) -> Integer?
67
+ def self._open_file_for_writing: (untyped filename, ?nil handler) -> untyped
68
+ def self.klass_from_handler: (?untyped klass, ?Integer? handler, *nil args) -> Integer
69
+ end
@@ -0,0 +1,4 @@
1
+ # Added only to satisfy the Steep requirements. Not 100% reliable.
2
+ module Schnorr
3
+ def self.sign: (String message, String private_key, ?String aux_rand) -> untyped
4
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nostr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wilson Silva
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-12 00:00:00.000000000 Z
11
+ date: 2023-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bech32
@@ -262,6 +262,20 @@ dependencies:
262
262
  - - "~>"
263
263
  - !ruby/object:Gem::Version
264
264
  version: '13.0'
265
+ - !ruby/object:Gem::Dependency
266
+ name: rbs
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - "~>"
270
+ - !ruby/object:Gem::Version
271
+ version: '2.8'
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - "~>"
277
+ - !ruby/object:Gem::Version
278
+ version: '2.8'
265
279
  - !ruby/object:Gem::Dependency
266
280
  name: rspec
267
281
  requirement: !ruby/object:Gem::Requirement
@@ -346,6 +360,34 @@ dependencies:
346
360
  - - "~>"
347
361
  - !ruby/object:Gem::Version
348
362
  version: '0.9'
363
+ - !ruby/object:Gem::Dependency
364
+ name: steep
365
+ requirement: !ruby/object:Gem::Requirement
366
+ requirements:
367
+ - - "~>"
368
+ - !ruby/object:Gem::Version
369
+ version: '1.3'
370
+ type: :development
371
+ prerelease: false
372
+ version_requirements: !ruby/object:Gem::Requirement
373
+ requirements:
374
+ - - "~>"
375
+ - !ruby/object:Gem::Version
376
+ version: '1.3'
377
+ - !ruby/object:Gem::Dependency
378
+ name: typeprof
379
+ requirement: !ruby/object:Gem::Requirement
380
+ requirements:
381
+ - - "~>"
382
+ - !ruby/object:Gem::Version
383
+ version: '0.21'
384
+ type: :development
385
+ prerelease: false
386
+ version_requirements: !ruby/object:Gem::Requirement
387
+ requirements:
388
+ - - "~>"
389
+ - !ruby/object:Gem::Version
390
+ version: '0.21'
349
391
  - !ruby/object:Gem::Dependency
350
392
  name: yard
351
393
  requirement: !ruby/object:Gem::Requirement
@@ -409,12 +451,14 @@ files:
409
451
  - LICENSE.txt
410
452
  - README.md
411
453
  - Rakefile
454
+ - Steepfile
412
455
  - lib/nostr.rb
413
456
  - lib/nostr/client.rb
414
457
  - lib/nostr/client_message_type.rb
458
+ - lib/nostr/crypto.rb
415
459
  - lib/nostr/event.rb
416
- - lib/nostr/event_fragment.rb
417
460
  - lib/nostr/event_kind.rb
461
+ - lib/nostr/events/encrypted_direct_message.rb
418
462
  - lib/nostr/filter.rb
419
463
  - lib/nostr/key_pair.rb
420
464
  - lib/nostr/keygen.rb
@@ -424,6 +468,23 @@ files:
424
468
  - lib/nostr/version.rb
425
469
  - nostr.gemspec
426
470
  - sig/nostr.rbs
471
+ - sig/nostr/client.rbs
472
+ - sig/nostr/client_message_type.rbs
473
+ - sig/nostr/crypto.rbs
474
+ - sig/nostr/event.rbs
475
+ - sig/nostr/event_kind.rbs
476
+ - sig/nostr/events/encrypted_direct_message.rbs
477
+ - sig/nostr/filter.rbs
478
+ - sig/nostr/key_pair.rbs
479
+ - sig/nostr/keygen.rbs
480
+ - sig/nostr/relay.rbs
481
+ - sig/nostr/subscription.rbs
482
+ - sig/nostr/user.rbs
483
+ - sig/vendor/ecsda/group/secp256k1.rbs
484
+ - sig/vendor/event_emitter.rbs
485
+ - sig/vendor/event_machine.rbs
486
+ - sig/vendor/event_machine/channel.rbs
487
+ - sig/vendor/schnorr.rbs
427
488
  homepage: https://github.com/wilsonsilva/nostr
428
489
  licenses:
429
490
  - MIT
@@ -447,7 +508,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
447
508
  - !ruby/object:Gem::Version
448
509
  version: '0'
449
510
  requirements: []
450
- rubygems_version: 3.4.1
511
+ rubygems_version: 3.4.7
451
512
  signing_key:
452
513
  specification_version: 4
453
514
  summary: Client and relay implementation of the Nostr protocol.