nostr 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +1 -1
  3. data/.rubocop.yml +23 -0
  4. data/.tool-versions +2 -1
  5. data/CHANGELOG.md +36 -1
  6. data/README.md +92 -228
  7. data/docs/.gitignore +4 -0
  8. data/docs/.vitepress/config.mjs +112 -0
  9. data/docs/README.md +44 -0
  10. data/docs/api-examples.md +49 -0
  11. data/docs/bun.lockb +0 -0
  12. data/docs/common-use-cases/bech32-encoding-and-decoding-(NIP-19).md +190 -0
  13. data/docs/core/client.md +108 -0
  14. data/docs/core/keys.md +136 -0
  15. data/docs/core/user.md +43 -0
  16. data/docs/events/contact-list.md +29 -0
  17. data/docs/events/encrypted-direct-message.md +28 -0
  18. data/docs/events/recommend-server.md +32 -0
  19. data/docs/events/set-metadata.md +20 -0
  20. data/docs/events/text-note.md +15 -0
  21. data/docs/events.md +11 -0
  22. data/docs/getting-started/installation.md +21 -0
  23. data/docs/getting-started/overview.md +170 -0
  24. data/docs/implemented-nips.md +9 -0
  25. data/docs/index.md +44 -0
  26. data/docs/markdown-examples.md +85 -0
  27. data/docs/package.json +12 -0
  28. data/docs/relays/connecting-to-a-relay.md +21 -0
  29. data/docs/relays/publishing-events.md +29 -0
  30. data/docs/relays/receiving-events.md +6 -0
  31. data/docs/subscriptions/creating-a-subscription.md +49 -0
  32. data/docs/subscriptions/deleting-a-subscription.md +10 -0
  33. data/docs/subscriptions/filtering-subscription-events.md +115 -0
  34. data/docs/subscriptions/updating-a-subscription.md +4 -0
  35. data/lib/nostr/bech32.rb +203 -0
  36. data/lib/nostr/client.rb +2 -1
  37. data/lib/nostr/crypto.rb +11 -7
  38. data/lib/nostr/errors/error.rb +7 -0
  39. data/lib/nostr/errors/invalid_hrp_error.rb +21 -0
  40. data/lib/nostr/errors/invalid_key_format_error.rb +20 -0
  41. data/lib/nostr/errors/invalid_key_length_error.rb +20 -0
  42. data/lib/nostr/errors/invalid_key_type_error.rb +18 -0
  43. data/lib/nostr/errors/key_validation_error.rb +6 -0
  44. data/lib/nostr/errors.rb +8 -0
  45. data/lib/nostr/event.rb +3 -4
  46. data/lib/nostr/events/encrypted_direct_message.rb +4 -3
  47. data/lib/nostr/filter.rb +4 -4
  48. data/lib/nostr/key.rb +100 -0
  49. data/lib/nostr/key_pair.rb +30 -6
  50. data/lib/nostr/keygen.rb +43 -4
  51. data/lib/nostr/private_key.rb +36 -0
  52. data/lib/nostr/public_key.rb +36 -0
  53. data/lib/nostr/relay_message_type.rb +18 -0
  54. data/lib/nostr/subscription.rb +2 -2
  55. data/lib/nostr/user.rb +17 -8
  56. data/lib/nostr/version.rb +1 -1
  57. data/lib/nostr.rb +6 -0
  58. data/nostr.gemspec +9 -9
  59. data/sig/nostr/bech32.rbs +14 -0
  60. data/sig/nostr/client.rbs +5 -5
  61. data/sig/nostr/crypto.rbs +5 -5
  62. data/sig/nostr/errors/error.rbs +4 -0
  63. data/sig/nostr/errors/invalid_hrb_error.rbs +6 -0
  64. data/sig/nostr/errors/invalid_key_format_error.rbs +5 -0
  65. data/sig/nostr/errors/invalid_key_length_error.rbs +5 -0
  66. data/sig/nostr/errors/invalid_key_type_error.rbs +5 -0
  67. data/sig/nostr/errors/key_validation_error.rbs +4 -0
  68. data/sig/nostr/event.rbs +4 -4
  69. data/sig/nostr/events/encrypted_direct_message.rbs +2 -2
  70. data/sig/nostr/filter.rbs +3 -12
  71. data/sig/nostr/key.rbs +16 -0
  72. data/sig/nostr/key_pair.rbs +7 -3
  73. data/sig/nostr/keygen.rbs +5 -2
  74. data/sig/nostr/private_key.rbs +4 -0
  75. data/sig/nostr/public_key.rbs +4 -0
  76. data/sig/nostr/relay_message_type.rbs +8 -0
  77. data/sig/nostr/user.rbs +4 -8
  78. data/sig/vendor/bech32/nostr/entity.rbs +41 -0
  79. data/sig/vendor/bech32/nostr/nip19.rbs +20 -0
  80. data/sig/vendor/bech32/segwit_addr.rbs +21 -0
  81. data/sig/vendor/bech32.rbs +25 -0
  82. data/sig/vendor/event_emitter.rbs +10 -3
  83. data/sig/vendor/event_machine/channel.rbs +1 -1
  84. data/sig/vendor/faye/websocket/api.rbs +45 -0
  85. data/sig/vendor/faye/websocket/client.rbs +43 -0
  86. data/sig/vendor/faye/websocket.rbs +30 -0
  87. metadata +79 -21
data/lib/nostr/keygen.rb CHANGED
@@ -44,10 +44,11 @@ module Nostr
44
44
  # private_key = keygen.generate_private_key
45
45
  # private_key # => '893c4cc8088924796b41dc788f7e2f746734497010b1a9f005c1faad7074b900'
46
46
  #
47
- # @return [String] A 32-bytes hex-encoded private key.
47
+ # @return [PrivateKey] A 32-bytes hex-encoded private key.
48
48
  #
49
49
  def generate_private_key
50
- (SecureRandom.random_number(group.order - 1) + 1).to_s(16)
50
+ hex_value = (SecureRandom.random_number(group.order - 1) + 1).to_s(16).rjust(64, '0')
51
+ PrivateKey.new(hex_value)
51
52
  end
52
53
 
53
54
  # Extracts a public key from a private key
@@ -59,10 +60,36 @@ module Nostr
59
60
  # public_key = keygen.extract_public_key(private_key)
60
61
  # public_key # => '2d7661527d573cc8e84f665fa971dd969ba51e2526df00c149ff8e40a58f9558'
61
62
  #
62
- # @return [String] A 32-bytes hex-encoded public key.
63
+ # @param [PrivateKey] private_key A 32-bytes hex-encoded private key.
64
+ #
65
+ # @raise [ArgumentError] if the private key is not an instance of +PrivateKey+
66
+ #
67
+ # @return [PublicKey] A 32-bytes hex-encoded public key.
63
68
  #
64
69
  def extract_public_key(private_key)
65
- group.generator.multiply_by_scalar(private_key.to_i(16)).x.to_s(16).rjust(64, '0')
70
+ validate_private_key(private_key)
71
+ hex_value = group.generator.multiply_by_scalar(private_key.to_i(16)).x.to_s(16).rjust(64, '0')
72
+ PublicKey.new(hex_value)
73
+ end
74
+
75
+ # Builds a key pair from an existing private key
76
+ #
77
+ # @api public
78
+ #
79
+ # @example
80
+ # private_key = Nostr::PrivateKey.new('893c4cc8088924796b41dc788f7e2f746734497010b1a9f005c1faad7074b900')
81
+ # keygen.get_key_pair_from_private_key(private_key)
82
+ #
83
+ # @param private_key [PrivateKey] 32-bytes hex-encoded private key.
84
+ #
85
+ # @raise [ArgumentError] if the private key is not an instance of +PrivateKey+
86
+ #
87
+ # @return [Nostr::KeyPair]
88
+ #
89
+ def get_key_pair_from_private_key(private_key)
90
+ validate_private_key(private_key)
91
+ public_key = extract_public_key(private_key)
92
+ KeyPair.new(private_key:, public_key:)
66
93
  end
67
94
 
68
95
  private
@@ -74,5 +101,17 @@ module Nostr
74
101
  # @return [ECDSA::Group]
75
102
  #
76
103
  attr_reader :group
104
+
105
+ # Validates that the private key is an instance of +PrivateKey+
106
+ #
107
+ # @api private
108
+ #
109
+ # @raise [ArgumentError] if the private key is not an instance of +PrivateKey+
110
+ #
111
+ # @return [void]
112
+ #
113
+ def validate_private_key(private_key)
114
+ raise ArgumentError, 'private_key is not an instance of PrivateKey' unless private_key.is_a?(Nostr::PrivateKey)
115
+ end
77
116
  end
78
117
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nostr
4
+ # 32-bytes lowercase hex-encoded private key
5
+ class PrivateKey < Key
6
+ # Human-readable part of the Bech32 encoded address
7
+ #
8
+ # @api private
9
+ #
10
+ # @return [String] The human-readable part of the Bech32 encoded address
11
+ #
12
+ def self.hrp
13
+ 'nsec'
14
+ end
15
+
16
+ private
17
+
18
+ # Validates the hex value of the private key
19
+ #
20
+ # @api private
21
+ #
22
+ # @param [String] hex_value The private key in hex format
23
+ #
24
+ # @raise InvalidKeyTypeError when the private key is not a string
25
+ # @raise InvalidKeyLengthError when the private key's length is not 64 characters
26
+ # @raise InvalidKeyFormatError when the private key is in an invalid format
27
+ #
28
+ # @return [void]
29
+ #
30
+ def validate_hex_value(hex_value)
31
+ raise InvalidKeyTypeError, 'private' unless hex_value.is_a?(String)
32
+ raise InvalidKeyLengthError, 'private' unless hex_value.size == Key::LENGTH
33
+ raise InvalidKeyFormatError, 'private' unless hex_value.match(Key::FORMAT)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nostr
4
+ # 32-bytes lowercase hex-encoded public key
5
+ class PublicKey < Key
6
+ # Human-readable part of the Bech32 encoded address
7
+ #
8
+ # @api private
9
+ #
10
+ # @return [String] The human-readable part of the Bech32 encoded address
11
+ #
12
+ def self.hrp
13
+ 'npub'
14
+ end
15
+
16
+ private
17
+
18
+ # Validates the hex value of the public key
19
+ #
20
+ # @api private
21
+ #
22
+ # @param [String] hex_value The public key in hex format
23
+ #
24
+ # @raise InvalidKeyTypeError when the public key is not a string
25
+ # @raise InvalidKeyLengthError when the public key's length is not 64 characters
26
+ # @raise InvalidKeyFormatError when the public key is in an invalid format
27
+ #
28
+ # @return [void]
29
+ #
30
+ def validate_hex_value(hex_value)
31
+ raise InvalidKeyTypeError, 'public' unless hex_value.is_a?(String)
32
+ raise InvalidKeyLengthError, 'public' unless hex_value.size == Key::LENGTH
33
+ raise InvalidKeyFormatError, 'public' unless hex_value.match(Key::FORMAT)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nostr
4
+ # Clients can send 4 types of messages, which must be JSON arrays
5
+ module RelayMessageType
6
+ # @return [String] Used to notify clients all stored events have been sent
7
+ EOSE = 'EOSE'
8
+
9
+ # @return [String] Used to send events requested to clients
10
+ EVENT = 'EVENT'
11
+
12
+ # @return [String] Used to send human-readable messages to clients
13
+ NOTICE = 'NOTICE'
14
+
15
+ # @return [String] Used to notify clients if an EVENT was successful
16
+ OK = 'OK'
17
+ end
18
+ end
@@ -5,7 +5,7 @@ require 'securerandom'
5
5
  module Nostr
6
6
  # A subscription the result of a request to receive events from a relay
7
7
  class Subscription
8
- # A random string that should be used to represent a subscription
8
+ # An arbitrary, non-empty string of max length 64 chars used to represent a subscription
9
9
  #
10
10
  # @api public
11
11
  #
@@ -41,7 +41,7 @@ module Nostr
41
41
  # @example Subscribing to all events created after a certain time
42
42
  # subscription = Nostr::Subscription.new(filter: Nostr::Filter.new(since: 1230981305))
43
43
  #
44
- # @param id [String] A random string that should be used to represent a subscription
44
+ # @param id [String] An arbitrary, non-empty string of max length 64 chars used to represent a subscription
45
45
  # @param filter [Filter] An object that determines what events will be sent in that subscription
46
46
  #
47
47
  def initialize(filter:, id: SecureRandom.hex)
data/lib/nostr/user.rb CHANGED
@@ -47,17 +47,26 @@ module Nostr
47
47
  # content: 'Your feedback is appreciated, now pay $8'
48
48
  # )
49
49
  #
50
- # @param event_attributes [Hash]
51
- # @option event_attributes [String] :pubkey 32-bytes hex-encoded public key of the event creator.
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 3.
54
- # @option event_attributes [Array<Array>] :tags An array of tags. Each tag is an array of strings.
55
- # @option event_attributes [String] :content Arbitrary string.
50
+ # @param created_at [Integer] Date of the creation of the vent. A UNIX timestamp, in seconds.
51
+ # @param kind [Integer] The kind of the event. An integer from 0 to 3.
52
+ # @param tags [Array<Array>] An array of tags. Each tag is an array of strings.
53
+ # @param content [String] Arbitrary string.
56
54
  #
57
55
  # @return [Event]
58
56
  #
59
- def create_event(event_attributes)
60
- event = Event.new(**event_attributes.merge(pubkey: keypair.public_key))
57
+ def create_event(
58
+ kind:,
59
+ content:,
60
+ created_at: Time.now.to_i,
61
+ tags: []
62
+ )
63
+ event = Event.new(
64
+ pubkey: keypair.public_key,
65
+ kind:,
66
+ content:,
67
+ created_at:,
68
+ tags:
69
+ )
61
70
  event.sign(keypair.private_key)
62
71
  end
63
72
  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.4.0'
5
+ VERSION = '0.5.0'
6
6
  end
data/lib/nostr.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'nostr/errors'
4
+ require_relative 'nostr/bech32'
3
5
  require_relative 'nostr/crypto'
4
6
  require_relative 'nostr/version'
5
7
  require_relative 'nostr/keygen'
@@ -7,12 +9,16 @@ require_relative 'nostr/client_message_type'
7
9
  require_relative 'nostr/filter'
8
10
  require_relative 'nostr/subscription'
9
11
  require_relative 'nostr/relay'
12
+ require_relative 'nostr/relay_message_type'
10
13
  require_relative 'nostr/key_pair'
11
14
  require_relative 'nostr/event_kind'
12
15
  require_relative 'nostr/event'
13
16
  require_relative 'nostr/events/encrypted_direct_message'
14
17
  require_relative 'nostr/client'
15
18
  require_relative 'nostr/user'
19
+ require_relative 'nostr/key'
20
+ require_relative 'nostr/private_key'
21
+ require_relative 'nostr/public_key'
16
22
 
17
23
  # Encapsulates all the gem's logic
18
24
  module Nostr
data/nostr.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = 'Client and relay implementation of the Nostr protocol.'
12
12
  spec.description = 'Client and relay implementation of the Nostr protocol.'
13
- spec.homepage = 'https://github.com/wilsonsilva/nostr'
13
+ spec.homepage = 'https://nostr-ruby.com/'
14
14
  spec.license = 'MIT'
15
15
  spec.required_ruby_version = '>= 3.2.0'
16
16
  spec.metadata['rubygems_mfa_required'] = 'true'
@@ -31,8 +31,8 @@ Gem::Specification.new do |spec|
31
31
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
32
32
  spec.require_paths = ['lib']
33
33
 
34
- spec.add_dependency 'bech32', '~> 1.3'
35
- spec.add_dependency 'bip-schnorr', '~> 0.4'
34
+ spec.add_dependency 'bech32', '~> 1.4'
35
+ spec.add_dependency 'bip-schnorr', '~> 0.6'
36
36
  spec.add_dependency 'ecdsa', '~> 1.2'
37
37
  spec.add_dependency 'event_emitter', '~> 0.2'
38
38
  spec.add_dependency 'faye-websocket', '~> 0.11'
@@ -47,17 +47,17 @@ Gem::Specification.new do |spec|
47
47
  spec.add_development_dependency 'guard-rubocop', '~> 1.5'
48
48
  spec.add_development_dependency 'overcommit', '~> 0.59'
49
49
  spec.add_development_dependency 'pry', '~> 0.14'
50
- spec.add_development_dependency 'puma', '~> 5.6'
50
+ spec.add_development_dependency 'puma', '~> 6.4'
51
51
  spec.add_development_dependency 'rack', '~> 3.0'
52
- spec.add_development_dependency 'rake', '~> 13.0'
53
- spec.add_development_dependency 'rbs', '~> 2.8'
52
+ spec.add_development_dependency 'rake', '~> 13.1'
53
+ spec.add_development_dependency 'rbs', '~> 3.3'
54
54
  spec.add_development_dependency 'rspec', '~> 3.12'
55
- spec.add_development_dependency 'rubocop', '~> 1.42'
55
+ spec.add_development_dependency 'rubocop', '~> 1.57'
56
56
  spec.add_development_dependency 'rubocop-rake', '~> 0.6'
57
- spec.add_development_dependency 'rubocop-rspec', '2.16'
57
+ spec.add_development_dependency 'rubocop-rspec', '2.25'
58
58
  spec.add_development_dependency 'simplecov', '= 0.17'
59
59
  spec.add_development_dependency 'simplecov-console', '~> 0.9'
60
- spec.add_development_dependency 'steep', '~> 1.3'
60
+ spec.add_development_dependency 'steep', '~> 1.6'
61
61
  spec.add_development_dependency 'typeprof', '~> 0.21'
62
62
  spec.add_development_dependency 'yard', '~> 0.9'
63
63
  spec.add_development_dependency 'yard-junk', '~> 0.0.9'
@@ -0,0 +1,14 @@
1
+ module Nostr
2
+ module Bech32
3
+ # Perhaps a bug in RBS/Steep. +decode+ and +encode+ are not recognized as public class methods.
4
+ def self?.decode: (String data) -> [String, String]
5
+ def self?.encode: (hrp: String, data: String) -> String
6
+
7
+ def naddr_encode: (pubkey: PublicKey, ?relays: Array[String], ?kind: Integer, ?identifier: String) -> String
8
+ def nevent_encode: (id: PublicKey, ?relays: Array[String], ?kind: Integer) -> String
9
+ def nprofile_encode: (pubkey: PublicKey, ?relays: Array[String]) -> String
10
+ def npub_encode: (String npub) -> String
11
+ def nrelay_encode: (String nrelay) -> String
12
+ def nsec_encode: (String nsec) -> String
13
+ end
14
+ end
data/sig/nostr/client.rbs CHANGED
@@ -5,16 +5,16 @@ module Nostr
5
5
  def initialize: -> void
6
6
  def connect: (Relay relay) -> Thread
7
7
  def subscribe: (?subscription_id: String, ?filter: Filter) -> Subscription
8
- def unsubscribe: (String subscription_id) -> untyped
8
+ def unsubscribe: (String subscription_id) -> void
9
9
  def publish: (Event event) -> untyped
10
10
 
11
11
  private
12
12
 
13
13
  attr_reader subscriptions: Hash[String, Subscription]
14
- attr_reader parent_to_child_channel: untyped
15
- attr_reader child_to_parent_channel: untyped
14
+ attr_reader parent_to_child_channel: EventMachine::Channel
15
+ attr_reader child_to_parent_channel: EventMachine::Channel
16
16
 
17
- def execute_within_an_em_thread: { -> untyped } -> Thread
18
- def initialize_channels: -> untyped
17
+ def execute_within_an_em_thread: { -> void } -> Thread
18
+ def initialize_channels: -> void
19
19
  end
20
20
  end
data/sig/nostr/crypto.rbs CHANGED
@@ -1,16 +1,16 @@
1
1
  module Nostr
2
2
  class Crypto
3
- BN_BASE: Integer
3
+ BN_BASE: 0 | 2 | 10 | 16
4
4
  CIPHER_CURVE: String
5
5
  CIPHER_ALGORITHM: String
6
6
 
7
- def encrypt_text: (String, String, String) -> String
8
- def decrypt_text: (String, String, String) -> String
9
- def sign_event: (Event, String) -> Event
7
+ def encrypt_text: (PrivateKey, PublicKey, String) -> String
8
+ def decrypt_text: (PrivateKey, PublicKey, String) -> String
9
+ def sign_event: (Event, PrivateKey) -> Event
10
10
 
11
11
  private
12
12
 
13
- def compute_shared_key: (String, String) -> String
13
+ def compute_shared_key: (PrivateKey, PublicKey) -> String
14
14
  def hash_event:(Event) -> String
15
15
  end
16
16
  end
@@ -0,0 +1,4 @@
1
+ module Nostr
2
+ class Error < StandardError
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Nostr
2
+ class InvalidHRPError < KeyValidationError
3
+ def initialize: (String, String) -> void
4
+ end
5
+ end
6
+
@@ -0,0 +1,5 @@
1
+ module Nostr
2
+ class InvalidKeyFormatError < KeyValidationError
3
+ def initialize: (String) -> void
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Nostr
2
+ class InvalidKeyLengthError < KeyValidationError
3
+ def initialize: (String) -> void
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Nostr
2
+ class InvalidKeyTypeError < KeyValidationError
3
+ def initialize: (String) -> void
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module Nostr
2
+ class KeyValidationError < Error
3
+ end
4
+ end
data/sig/nostr/event.rbs CHANGED
@@ -1,6 +1,6 @@
1
1
  module Nostr
2
2
  class Event
3
- attr_reader pubkey: String
3
+ attr_reader pubkey: PublicKey
4
4
  attr_reader created_at: Integer
5
5
  attr_reader kind: Integer
6
6
  attr_reader tags: Array[Array[String]]
@@ -9,7 +9,7 @@ module Nostr
9
9
  attr_accessor sig: String?|nil
10
10
 
11
11
  def initialize: (
12
- pubkey: String,
12
+ pubkey: PublicKey,
13
13
  kind: Integer,
14
14
  content: String,
15
15
  ?created_at: Integer,
@@ -31,9 +31,9 @@ module Nostr
31
31
  }
32
32
  def ==: (Event other) -> bool
33
33
 
34
- def sign:(String) -> Event
34
+ def sign:(PrivateKey) -> Event
35
35
 
36
36
  def add_event_reference: (String) -> Array[Array[String]]
37
- def add_pubkey_reference: (String) -> Array[Array[String]]
37
+ def add_pubkey_reference: (PublicKey) -> Array[Array[String]]
38
38
  end
39
39
  end
@@ -3,8 +3,8 @@ module Nostr
3
3
  class EncryptedDirectMessage < Event
4
4
  def initialize: (
5
5
  plain_text: String,
6
- sender_private_key: String,
7
- recipient_public_key: String,
6
+ sender_private_key: PrivateKey,
7
+ recipient_public_key: PublicKey,
8
8
  ?previous_direct_message: String|nil
9
9
  ) -> void
10
10
  end
data/sig/nostr/filter.rbs CHANGED
@@ -3,23 +3,14 @@ module Nostr
3
3
  attr_reader ids: Array[String]
4
4
  attr_reader authors: Array[String]
5
5
  attr_reader kinds: Array[Integer]
6
- attr_reader e: String
7
- attr_reader p: String
6
+ attr_reader e: Array[String]
7
+ attr_reader p: Array[String]
8
8
  attr_reader since: Integer
9
9
  attr_reader until: Integer
10
10
  attr_reader limit: Integer
11
11
 
12
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
- }
13
+ def to_h: -> Hash[::Symbol, (::Array[::String] | ::Array[::Integer] | ::Integer)]
23
14
  def ==: (Filter other) -> bool
24
15
  end
25
16
  end
data/sig/nostr/key.rbs ADDED
@@ -0,0 +1,16 @@
1
+ module Nostr
2
+ class Key < String
3
+ FORMAT: Regexp
4
+ LENGTH: int
5
+
6
+ def self.from_bech32: (String) -> Key
7
+ def self.hrp: -> String
8
+
9
+ def initialize: (String) -> void
10
+ def to_bech32: -> String
11
+
12
+ private
13
+
14
+ def validate_hex_value: (String) -> nil
15
+ end
16
+ end
@@ -1,9 +1,13 @@
1
1
  # Classes
2
2
  module Nostr
3
3
  class KeyPair
4
- attr_reader private_key: String
5
- attr_reader public_key: String
4
+ attr_reader private_key: PrivateKey
5
+ attr_reader public_key: PublicKey
6
6
 
7
- def initialize: (private_key: String, public_key: String) -> void
7
+ def initialize: (private_key: PrivateKey, public_key: PublicKey) -> void
8
+
9
+ private
10
+
11
+ def validate_keys: (PrivateKey, PublicKey) -> void
8
12
  end
9
13
  end
data/sig/nostr/keygen.rbs CHANGED
@@ -3,11 +3,14 @@ module Nostr
3
3
  class Keygen
4
4
  def initialize: -> void
5
5
  def generate_key_pair: -> KeyPair
6
- def generate_private_key: -> String
7
- def extract_public_key: (String private_key) -> String
6
+ def generate_private_key: -> PrivateKey
7
+ def extract_public_key: (PrivateKey private_key) -> PublicKey
8
+ def get_key_pair_from_private_key: (PrivateKey private_key) -> KeyPair
8
9
 
9
10
  private
10
11
 
11
12
  attr_reader group: untyped
13
+
14
+ def validate_private_key: (PrivateKey private_key) -> void
12
15
  end
13
16
  end
@@ -0,0 +1,4 @@
1
+ module Nostr
2
+ class PrivateKey < Key
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Nostr
2
+ class PublicKey < Key
3
+ end
4
+ end
@@ -0,0 +1,8 @@
1
+ module Nostr
2
+ module RelayMessageType
3
+ EOSE: String
4
+ EVENT: String
5
+ NOTICE: String
6
+ OK: String
7
+ end
8
+ end
data/sig/nostr/user.rbs CHANGED
@@ -5,14 +5,10 @@ module Nostr
5
5
 
6
6
  def initialize: (?keypair: KeyPair | nil, ?keygen: Keygen) -> void
7
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
- }
8
+ kind: Integer,
9
+ content: String,
10
+ ?created_at: Integer,
11
+ ?tags: Array[Array[String]],
16
12
  ) -> Event
17
13
 
18
14
  private
@@ -0,0 +1,41 @@
1
+ # Added only to satisfy the Steep requirements. Not 100% reliable.
2
+ module Bech32
3
+ module Nostr
4
+ class BareEntity
5
+ attr_reader hrp: untyped
6
+ attr_reader data: untyped
7
+
8
+ def initialize: (untyped hrp, untyped data) -> void
9
+ def encode: -> untyped
10
+ end
11
+
12
+ class TLVEntry
13
+ attr_reader type: (Float | Integer | String)?
14
+ attr_reader label: String?
15
+ attr_reader value: (Float | Integer | String)?
16
+
17
+ def initialize: ((Float | Integer | String)? `type`, (Float | Integer | String)? value, ?String? label) -> void
18
+ def to_payload: -> String
19
+ def to_s: -> String
20
+
21
+ private
22
+
23
+ def hex_string?: ((Float | Integer | String)? str) -> bool
24
+ end
25
+
26
+ class TLVEntity
27
+ TYPE_SPECIAL: Integer
28
+ TYPE_RELAY: Integer
29
+ TYPE_AUTHOR: Integer
30
+ TYPE_KIND: Integer
31
+ TYPES: [Integer, Integer, Integer, Integer]
32
+
33
+ attr_reader hrp: untyped
34
+ attr_reader entries: Array[TLVEntry]
35
+
36
+ def initialize: (untyped hrp, Array[TLVEntry] entries) -> void
37
+ def self.parse: (untyped hrp, untyped data) -> TLVEntity
38
+ def encode: -> untyped
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,20 @@
1
+ # Added only to satisfy the Steep requirements. Not 100% reliable.
2
+ module Bech32
3
+ module Nostr
4
+ module NIP19
5
+ HRP_PUBKEY: String
6
+ HRP_PRIVATE_KEY: String
7
+ HRP_NOTE_ID: String
8
+ HRP_PROFILE: String
9
+ HRP_EVENT: String
10
+ HRP_RELAY: String
11
+ HRP_EVENT_COORDINATE: String
12
+ BARE_PREFIXES: [String, String, String]
13
+ TLV_PREFIXES: [String, String, String, String]
14
+ ALL_PREFIXES: Array[String]
15
+
16
+ def decode: (untyped string) -> untyped
17
+ def self.decode: (untyped string) -> untyped
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # Added only to satisfy the Steep requirements. Not 100% reliable.
2
+ module Bech32
3
+ class SegwitAddr
4
+ HRP_MAINNET: String
5
+ HRP_TESTNET: String
6
+ HRP_REGTEST: String
7
+
8
+ attr_accessor hrp: String
9
+ attr_accessor ver: (Float | Integer | String)?
10
+ attr_accessor prog: Array[(Float | Integer | String)?]
11
+
12
+ def initialize: (?nil addr) -> void
13
+ def to_script_pubkey: -> ((Float | Integer | String)?)
14
+ def script_pubkey=: (untyped script_pubkey) -> (Array[(Float | Integer | String)?])
15
+ def addr: -> untyped
16
+
17
+ private
18
+
19
+ def parse_addr: (untyped addr) -> nil
20
+ end
21
+ end