nostr 0.3.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +1 -1
  3. data/.rubocop.yml +26 -0
  4. data/.tool-versions +2 -1
  5. data/CHANGELOG.md +65 -1
  6. data/README.md +96 -183
  7. data/Steepfile +2 -0
  8. data/docs/.gitignore +4 -0
  9. data/docs/.vitepress/config.mjs +112 -0
  10. data/docs/README.md +44 -0
  11. data/docs/api-examples.md +49 -0
  12. data/docs/bun.lockb +0 -0
  13. data/docs/common-use-cases/bech32-encoding-and-decoding-(NIP-19).md +190 -0
  14. data/docs/core/client.md +108 -0
  15. data/docs/core/keys.md +136 -0
  16. data/docs/core/user.md +43 -0
  17. data/docs/events/contact-list.md +29 -0
  18. data/docs/events/encrypted-direct-message.md +28 -0
  19. data/docs/events/recommend-server.md +32 -0
  20. data/docs/events/set-metadata.md +20 -0
  21. data/docs/events/text-note.md +15 -0
  22. data/docs/events.md +11 -0
  23. data/docs/getting-started/installation.md +21 -0
  24. data/docs/getting-started/overview.md +170 -0
  25. data/docs/implemented-nips.md +9 -0
  26. data/docs/index.md +44 -0
  27. data/docs/markdown-examples.md +85 -0
  28. data/docs/package.json +12 -0
  29. data/docs/relays/connecting-to-a-relay.md +21 -0
  30. data/docs/relays/publishing-events.md +29 -0
  31. data/docs/relays/receiving-events.md +6 -0
  32. data/docs/subscriptions/creating-a-subscription.md +49 -0
  33. data/docs/subscriptions/deleting-a-subscription.md +10 -0
  34. data/docs/subscriptions/filtering-subscription-events.md +115 -0
  35. data/docs/subscriptions/updating-a-subscription.md +4 -0
  36. data/lib/nostr/bech32.rb +203 -0
  37. data/lib/nostr/client.rb +2 -1
  38. data/lib/nostr/crypto.rb +147 -0
  39. data/lib/nostr/errors/error.rb +7 -0
  40. data/lib/nostr/errors/invalid_hrp_error.rb +21 -0
  41. data/lib/nostr/errors/invalid_key_format_error.rb +20 -0
  42. data/lib/nostr/errors/invalid_key_length_error.rb +20 -0
  43. data/lib/nostr/errors/invalid_key_type_error.rb +18 -0
  44. data/lib/nostr/errors/key_validation_error.rb +6 -0
  45. data/lib/nostr/errors.rb +8 -0
  46. data/lib/nostr/event.rb +157 -12
  47. data/lib/nostr/event_kind.rb +8 -0
  48. data/lib/nostr/events/encrypted_direct_message.rb +54 -0
  49. data/lib/nostr/filter.rb +4 -4
  50. data/lib/nostr/key.rb +100 -0
  51. data/lib/nostr/key_pair.rb +30 -6
  52. data/lib/nostr/keygen.rb +43 -4
  53. data/lib/nostr/private_key.rb +36 -0
  54. data/lib/nostr/public_key.rb +36 -0
  55. data/lib/nostr/relay_message_type.rb +18 -0
  56. data/lib/nostr/subscription.rb +2 -2
  57. data/lib/nostr/user.rb +17 -36
  58. data/lib/nostr/version.rb +1 -1
  59. data/lib/nostr.rb +8 -1
  60. data/nostr.gemspec +9 -9
  61. data/sig/nostr/bech32.rbs +14 -0
  62. data/sig/nostr/client.rbs +5 -5
  63. data/sig/nostr/crypto.rbs +16 -0
  64. data/sig/nostr/errors/error.rbs +4 -0
  65. data/sig/nostr/errors/invalid_hrb_error.rbs +6 -0
  66. data/sig/nostr/errors/invalid_key_format_error.rbs +5 -0
  67. data/sig/nostr/errors/invalid_key_length_error.rbs +5 -0
  68. data/sig/nostr/errors/invalid_key_type_error.rbs +5 -0
  69. data/sig/nostr/errors/key_validation_error.rbs +4 -0
  70. data/sig/nostr/event.rbs +24 -9
  71. data/sig/nostr/event_kind.rbs +1 -0
  72. data/sig/nostr/events/encrypted_direct_message.rbs +12 -0
  73. data/sig/nostr/filter.rbs +3 -12
  74. data/sig/nostr/key.rbs +16 -0
  75. data/sig/nostr/key_pair.rbs +7 -3
  76. data/sig/nostr/keygen.rbs +5 -2
  77. data/sig/nostr/private_key.rbs +4 -0
  78. data/sig/nostr/public_key.rbs +4 -0
  79. data/sig/nostr/relay_message_type.rbs +8 -0
  80. data/sig/nostr/user.rbs +4 -10
  81. data/sig/vendor/bech32/nostr/entity.rbs +41 -0
  82. data/sig/vendor/bech32/nostr/nip19.rbs +20 -0
  83. data/sig/vendor/bech32/segwit_addr.rbs +21 -0
  84. data/sig/vendor/bech32.rbs +25 -0
  85. data/sig/vendor/event_emitter.rbs +10 -3
  86. data/sig/vendor/event_machine/channel.rbs +1 -1
  87. data/sig/vendor/faye/websocket/api.rbs +45 -0
  88. data/sig/vendor/faye/websocket/client.rbs +43 -0
  89. data/sig/vendor/faye/websocket.rbs +30 -0
  90. metadata +83 -23
  91. data/lib/nostr/event_fragment.rb +0 -111
  92. data/sig/nostr/event_fragment.rbs +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 371ed11c0474fd944cc55a054d553945623f7439f67c55f3eadc564805d2fb11
4
- data.tar.gz: f7fbe86119bd7816e7066ea3603263dee7327b06daeb4b92f9e90977f52ef8ae
3
+ metadata.gz: 168cbde3fb029345d4fa10043eead7c194a57fe3ee23c12b76bbaf79b1bdc71d
4
+ data.tar.gz: ff1a1837e897a8c0ad233a61ed4526fe3e4087c04474e54778a00a0d4313e361
5
5
  SHA512:
6
- metadata.gz: fa602354304ce9e77377b80cab60146f51ac8943b1399070a87ce81a5e44582f0a23b50f1736fafd9d7d0f13042b8b7292b9d29684077ad878e2439ddf7970ef
7
- data.tar.gz: 83fc3d535a1e35438522779ef7dc3e101b4fea3a3f9874db9457b4f6c61d74469ded6ba973923d731789d3c50d7aa66b1c0770d62451794d45b52720c7928ebf
6
+ metadata.gz: e5549507ded84026a2295c3914324e8c74aff3c1ae80322db3cd449e7f65c3475186e9daaa76f7a22241e33b6759c2073da5a31a910a2082c8e49a99081dc5bf
7
+ data.tar.gz: 19f69ed10ae3ba42113992541912bb18a4aa3ad8239b582b996e7c7845c4624c4a9ee73d800f51fbd883d2bdd9ea603eeb807ade147bcfc22db7183c1db30ce6
data/.editorconfig CHANGED
@@ -6,6 +6,6 @@ max_line_length = 120
6
6
  trim_trailing_whitespace = true
7
7
 
8
8
  # 2 space indentation
9
- [*.rb]
9
+ [{*.rb, *.mjs}]
10
10
  indent_style = space
11
11
  indent_size = 2
data/.rubocop.yml CHANGED
@@ -9,8 +9,17 @@ AllCops:
9
9
  DisplayCopNames: true
10
10
  NewCops: enable
11
11
 
12
+ # ----------------------- Gemspec -----------------------
13
+
14
+ Gemspec/DevelopmentDependencies:
15
+ Enabled: false
16
+
12
17
  # ----------------------- Style -----------------------
13
18
 
19
+ Style/RaiseArgs:
20
+ Exclude:
21
+ - 'lib/nostr/key.rb'
22
+
14
23
  Style/StringLiterals:
15
24
  Enabled: true
16
25
  EnforcedStyle: single_quotes
@@ -31,7 +40,24 @@ Metrics/BlockLength:
31
40
  - '**/*_spec.rb'
32
41
  - nostr.gemspec
33
42
 
43
+ Metrics/ParameterLists:
44
+ CountKeywordArgs: false
45
+
34
46
  # ----------------------- RSpec -----------------------
35
47
 
36
48
  RSpec/ExampleLength:
37
49
  Enabled: false
50
+
51
+ RSpec/FilePath:
52
+ Exclude:
53
+ - spec/nostr/errors/invalid_*
54
+
55
+ RSpec/SpecFilePathFormat:
56
+ Exclude:
57
+ - spec/nostr/errors/invalid_*
58
+
59
+ # ----------------------- Naming -----------------------
60
+
61
+ Naming/MemoizedInstanceVariableName:
62
+ Exclude:
63
+ - 'spec/nostr/key.rb'
data/.tool-versions CHANGED
@@ -1 +1,2 @@
1
- ruby 3.2.0
1
+ ruby 3.2.2
2
+ bun 1.0.11
data/CHANGELOG.md CHANGED
@@ -1,14 +1,76 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
- The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.1/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.5.0] 2023-11-20
8
+
9
+ ### Added
10
+
11
+ - Added relay message type enums `Nostr::RelayMessageType`
12
+ - Compliance with [NIP-19](https://github.com/nostr-protocol/nips/blob/master/19.md) - bech32-formatted strings
13
+ - `Nostr::PrivateKey` and `Nostr::PublicKey` to represent private and public keys, respectively
14
+ - Added a validation of private and public keys
15
+ - Added an ability to convert keys to and from Bech32 format
16
+ - Added RBS types for `faye-websocket` and `bech32`
17
+
18
+ ### Changed
19
+
20
+ - Set the gem's homepage to [`https://nostr-ruby.com/`](https://nostr-ruby.com/)
21
+ - Updated the filter's documentation to reflect the removal of prefix matching
22
+ - Updated the subscription's id documentation to reflect the changes in the protocol definition
23
+ - Updated `Nostr::PrivateKey` and `Nostr::PublicKey` internally, instead of Strings
24
+ - Updated the gem `bip-schnorr` to version `0.6` (was `0.4`)
25
+ - Updated the gem `puma` to version `6.4` (was `6.3`)
26
+ - Updated the gem `rake` to version `13.1` (was `13.0`)
27
+ - Updated the gem `rbs` to version `3.3` (was `2.8`)
28
+ - Updated the gem `rubocop` to version `1.57` (was `1.42`)
29
+ - Updated the gem `rubocop-rspec` to version `2.25` (was `2.16`)
30
+ - Updated the gem `steep` to version `1.6` (was `1.4`)
31
+
32
+ ## Fixed
33
+
34
+ - Fixed the RBS type of the constant `Nostr::Crypto::BN_BASE`
35
+ - Fixed the return type of `Nostr::Crypto#decrypt_text` when given an invalid ciphertext
36
+ - Fixed the RBS type of `Nostr::Filter#to_h`, `Nostr::Filter#e` and `Nostr::Filter#p`
37
+ - Fixed the RBS types of `EventEmitter` and `EventMachine::Channel`
38
+ - Fixed the generation of private keys
39
+
40
+ ## [0.4.0] - 2023-02-25
41
+
42
+ ### Removed
43
+
44
+ - Removed `EventFragment` class. The `Event` class is no longer a Value Object. In other words, it is no longer
45
+ immutable and it may be invalid by not having attributes `id` or `sig`. The `EventFragment` abstraction, along with the
46
+ principles of immutability and was a major source of internal complexity as I needed to scale the codebase.
47
+
48
+ ### Added
49
+
50
+ - Client compliance with [NIP-04](https://github.com/nostr-protocol/nips/blob/master/04.md) (encrypted direct messages)
51
+ - Extracted the cryptographic concerns into a `Crypto` class.
52
+ - Added the setters `Event#id=` and `Event#sig=`
53
+ - Added a method on the event class to sign events (`Event#sign`)
54
+ - Added a missing test for `EventKind::CONTACT_LIST`
55
+ - Added two convenience methods to append event and pubkey references to an event's tags `add_event_reference` and
56
+ `add_pubkey_reference`
57
+
58
+ ### Fixed
59
+
60
+ - Fixed the generation of public keys
61
+ - Fixed the RBS signature of `User#create_event`
62
+
7
63
  ## [0.3.0] - 2023-02-15
8
64
 
9
65
  ### Added
10
66
 
11
67
  - Client compliance wth [NIP-02](https://github.com/nostr-protocol/nips/blob/master/02.md) (manage contact lists)
68
+ - RBS type checking using Steep and TypeProf
69
+
70
+ ## Fixed
71
+
72
+ - Fixed a documentation typo
73
+ - Fixed a documentation error regarding the receiving of messages via websockets
12
74
 
13
75
  ## [0.2.0] - 2023-01-12
14
76
 
@@ -20,6 +82,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
20
82
 
21
83
  - Initial release
22
84
 
85
+ [0.5.0]: https://github.com/wilsonsilva/nostr/compare/v0.4.0...v0.5.0
86
+ [0.4.0]: https://github.com/wilsonsilva/nostr/compare/v0.3.0...v0.4.0
23
87
  [0.3.0]: https://github.com/wilsonsilva/nostr/compare/v0.2.0...v0.3.0
24
88
  [0.2.0]: https://github.com/wilsonsilva/nostr/compare/v0.1.0...v0.2.0
25
89
  [0.1.0]: https://github.com/wilsonsilva/nostr/compare/7fded5...v0.1.0
data/README.md CHANGED
@@ -4,10 +4,30 @@
4
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/c7633eb2c89eb95ee7f2/maintainability)](https://codeclimate.com/github/wilsonsilva/nostr/maintainability)
5
5
  [![Test Coverage](https://api.codeclimate.com/v1/badges/c7633eb2c89eb95ee7f2/test_coverage)](https://codeclimate.com/github/wilsonsilva/nostr/test_coverage)
6
6
 
7
- Asynchronous Nostr client. Please note that the API is likely to change as the gem is still in development and
8
- has not yet reached a stable release. Use with caution.
7
+ Asynchronous Nostr client for Rubyists.
9
8
 
10
- ## Installation
9
+ ## Table of contents
10
+
11
+ - [Key features](#-key-features)
12
+ - [Installation](#-installation)
13
+ - [Quickstart](#-quickstart)
14
+ - [Documentation](#-documentation)
15
+ - [Implemented NIPs](#-implemented-nips)
16
+ - [Development](#-development)
17
+ * [Type checking](#type-checking)
18
+ - [Contributing](#-contributing)
19
+ - [License](#-license)
20
+ - [Code of Conduct](#-code-of-conduct)
21
+
22
+ ## 🔑 Key features
23
+
24
+ - Asynchronous
25
+ - Easy to use
26
+ - Fully documented
27
+ - Fully tested
28
+ - Fully typed
29
+
30
+ ## 📦 Installation
11
31
 
12
32
  Install the gem and add to the application's Gemfile by executing:
13
33
 
@@ -17,215 +37,103 @@ If bundler is not being used to manage dependencies, install the gem by executin
17
37
 
18
38
  $ gem install nostr
19
39
 
20
- ## Usage
40
+ ## ⚡️ Quickstart
21
41
 
22
- ### Requiring the gem
23
-
24
- All examples below assume that the gem has been required.
42
+ Here is a quick example of how to use the gem. For more detailed documentation, please check the
43
+ [documentation website](https://nostr-ruby.com).
25
44
 
26
45
  ```ruby
46
+ # Require the gem
27
47
  require 'nostr'
28
- ```
29
-
30
- ### Generating a keypair
31
-
32
- ```ruby
33
- keygen = Nostr::Keygen.new
34
- keypair = keygen.generate_keypair
35
-
36
- keypair.private_key
37
- keypair.public_key
38
- ```
39
-
40
- ### Generating a private key and a public key
41
48
 
42
- ```ruby
43
- keygen = Nostr::Keygen.new
49
+ # Instantiate a client
50
+ client = Nostr::Client.new
44
51
 
45
- private_key = keygen.generate_private_key
46
- public_key = keygen.extract_public_key(private_key)
47
- ```
52
+ # a) Use an existing keypair
53
+ keypair = Nostr::KeyPair.new(
54
+ private_key: Nostr::PrivateKey.new('add-your-hex-private-key-here'),
55
+ public_key: Nostr::PublicKey.new('add-your-hex-public-key-here'),
56
+ )
48
57
 
49
- ### Connecting to a Relay
58
+ # b) Or build a keypair from a private key
59
+ keygen = Nostr::Keygen.new
60
+ keypair = keygen.get_key_pair_from_private_key(
61
+ Nostr::PrivateKey.new('add-your-hex-private-key-here')
62
+ )
50
63
 
51
- Clients can connect to multiple Relays. In this version, a Client can only connect to a single Relay at a time.
64
+ # c) Or create a new keypair
65
+ keygen = Nostr::Keygen.new
66
+ keypair = keygen.generate_keypair
52
67
 
53
- You may instantiate multiple Clients and multiple Relays.
68
+ # Create a user with the keypair
69
+ user = Nostr::User.new(keypair: keypair)
54
70
 
55
- ```ruby
56
- client = Nostr::Client.new
57
- relay = Nostr::Relay.new(url: 'wss://relay.damus.io', name: 'Damus')
71
+ # Create a signed event
72
+ text_note_event = user.create_event(
73
+ kind: Nostr::EventKind::TEXT_NOTE,
74
+ content: 'Your feedback is appreciated, now pay $8'
75
+ )
58
76
 
77
+ # Connect asynchronously to a relay
78
+ relay = Nostr::Relay.new(url: 'wss://nostr.wine', name: 'Wine')
59
79
  client.connect(relay)
60
- ```
61
80
 
62
- ### WebSocket events
63
-
64
- All communication between clients and relays happen in WebSockets.
65
-
66
- The `:connect` event is fired when a connection with a WebSocket is opened. You must call `Nostr::Client#connect` first.
67
-
68
- ```ruby
81
+ # Listen asynchronously for the connect event
69
82
  client.on :connect do
70
- # all the code goes here
71
- end
72
- ```
73
-
74
- The `:close` event is fired when a connection with a WebSocket has been closed because of an error.
75
-
76
- ```ruby
77
- client.on :error do |error_message|
78
- puts error_message
79
- end
80
-
81
- # > Network error: wss://rsslay.fiatjaf.com: Unable to verify the server certificate for 'rsslay.fiatjaf.com'
82
- ```
83
-
84
- The `:message` event is fired when data is received through a WebSocket.
85
-
86
- ```ruby
87
- client.on :message do |message|
88
- puts message
89
- end
90
-
91
- # [
92
- # "EVENT",
93
- # "d34107357089bfc9882146d3bfab0386",
94
- # {
95
- # "content":"",
96
- # "created_at":1676456512,
97
- # "id":"18f63550da74454c5df7caa2a349edc5b2a6175ea4c5367fa4b4212781e5b310",
98
- # "kind":3,
99
- # "pubkey":"117a121fa41dc2caa0b3d6c5b9f42f90d114f1301d39f9ee96b646ebfee75e36",
100
- # "sig":"d171420bd62cf981e8f86f2dd8f8f86737ea2bbe2d98da88db092991d125535860d982139a3c4be39886188613a9912ef380be017686a0a8b74231dc6e0b03cb",
101
- # "tags":[
102
- # ["p","1cc821cc2d47191b15fcfc0f73afed39a86ac6fb34fbfa7993ee3e0f0186ef7c"]
103
- # ]
104
- # }
105
- # ]
106
- ```
107
-
108
- The `:close` event is fired when a connection with a WebSocket is closed.
109
-
110
- ```ruby
111
- client.on :close do |code, reason|
112
- # you may attempt to reconnect
83
+ # Send the event to the Relay
84
+ client.publish(text_note_event)
113
85
 
114
- client.connect(relay)
115
- end
116
- ```
117
-
118
- ### Requesting for events / creating a subscription
119
-
120
- A client can request events and subscribe to new updates after it has established a connection with the Relay.
121
-
122
- You may use a `Nostr::Filter` instance with as many attributes as you wish:
123
-
124
- ```ruby
125
- client.on :connect do
86
+ # Create a filter to receive the first 20 text notes
87
+ # and encrypted direct messages from the relay that
88
+ # were created in the previous hour
126
89
  filter = Nostr::Filter.new(
127
- ids: ['8535d5e2d7b9dc07567f676fbe70428133c9884857e1915f5b1cc6514c2fdff8'],
128
- authors: ['ae00f88a885ce76afad5cbb2459ef0dcf0df0907adc6e4dac16e1bfbd7074577'],
129
- kinds: [Nostr::EventKind::TEXT_NOTE],
130
- e: ["f111593a72cc52a7f0978de5ecf29b4653d0cf539f1fa50d2168fc1dc8280e52"],
131
- p: ["f1f9b0996d4ff1bf75e79e4cc8577c89eb633e68415c7faf74cf17a07bf80bd8"],
132
- since: 1230981305,
133
- until: 1292190341,
134
- limit: 420,
90
+ kinds: [
91
+ Nostr::EventKind::TEXT_NOTE,
92
+ Nostr::EventKind::ENCRYPTED_DIRECT_MESSAGE
93
+ ],
94
+ since: Time.now.to_i - 3600, # 1 hour ago
95
+ until: Time.now.to_i,
96
+ limit: 20,
135
97
  )
136
98
 
137
- subscription = client.subscribe('a_random_subscription_id', filter)
138
- end
139
- ```
140
-
141
- With just a few:
99
+ # Subscribe to events matching conditions of a filter
100
+ subscription = client.subscribe(filter: filter)
142
101
 
143
- ```ruby
144
- client.on :connect do
145
- filter = Nostr::Filter.new(kinds: [Nostr::EventKind::TEXT_NOTE])
146
- subscription = client.subscribe('a_random_subscription_id', filter)
102
+ # Unsubscribe from events matching the filter above
103
+ client.unsubscribe(subscription.id)
147
104
  end
148
- ```
149
-
150
- Or omit the filter:
151
105
 
152
- ```ruby
153
- client.on :connect do
154
- subscription = client.subscribe('a_random_subscription_id')
106
+ # Listen for incoming messages and print them
107
+ client.on :message do |message|
108
+ puts message
155
109
  end
156
- ```
157
-
158
- Or even omit the subscription id:
159
110
 
160
- ```ruby
161
- client.on :connect do
162
- subscription = client.subscribe('a_random_subscription_id')
111
+ # Listen for error messages
112
+ client.on :error do |error_message|
113
+ # Handle the error
163
114
  end
164
- ```
165
-
166
- ### Stop previous subscriptions
167
-
168
- You can stop receiving messages from a subscription by calling `#unsubscribe`:
169
-
170
- ```ruby
171
- client.unsubscribe('your_subscription_id')
172
- ```
173
-
174
- ### Publishing an event
175
115
 
176
- To publish an event you need a keypair.
177
-
178
- ```ruby
179
- # Set up the private key
180
- private_key = 'a630b06e2f883378d0aa335b9adaf7734603e00433350b684fe53e184f08c58f'
181
- user = Nostr::User.new(private_key)
182
-
183
- # Create a signed event
184
- event = user.create_event(
185
- created_at: 1667422587, # optional, defaults to the current time
186
- kind: Nostr::EventKind::TEXT_NOTE,
187
- tags: [], # optional, defaults to []
188
- content: 'Your feedback is appreciated, now pay $8'
189
- )
190
-
191
- # Send it to the Relay
192
- client.publish(event)
116
+ # Listen for the close event
117
+ client.on :close do |code, reason|
118
+ # You may attempt to reconnect to the relay here
119
+ end
193
120
  ```
194
121
 
195
- ### Creating/updating your contact list
196
-
197
- Every new contact list that gets published overwrites the past ones, so it should contain all entries.
122
+ ## 📚 Documentation
198
123
 
199
- ```ruby
200
- # Creating a contact list event with 2 contacts
201
- update_contacts_event = user.create_event(
202
- kind: Nostr::EventKind::CONTACT_LIST,
203
- tags: [
204
- [
205
- "p", # mandatory
206
- "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245", # public key of the user to add to the contacts
207
- "wss://alicerelay.com/", # can be an empty string or can be omitted
208
- "alice" # can be an empty string or can be omitted
209
- ],
210
- [
211
- "p", # mandatory
212
- "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681", # public key of the user to add to the contacts
213
- "wss://bobrelay.com/nostr", # can be an empty string or can be omitted
214
- "bob" # can be an empty string or can be omitted
215
- ],
216
- ],
217
- )
124
+ I made a detailed documentation for this gem and it's usage. The code is also fully documented using YARD.
218
125
 
219
- # Send it to the Relay
220
- client.publish(update_contacts_event)
221
- ```
126
+ - [Guide documentation](https://nostr-ruby.com)
127
+ - [YARD documentation](https://rubydoc.info/gems/nostr)
222
128
 
223
- ## NIPS
129
+ ## ✅ Implemented NIPs
224
130
 
225
- - [x] [NIP-01 - Client](https://github.com/nostr-protocol/nips/blob/master/01.md)
226
- - [x] [NIP-02 - Client](https://github.com/nostr-protocol/nips/blob/master/02.md)
131
+ - [x] [NIP-01 - Basic protocol flow description](https://github.com/nostr-protocol/nips/blob/master/01.md)
132
+ - [x] [NIP-02 - Contact List and Petnames](https://github.com/nostr-protocol/nips/blob/master/02.md)
133
+ - [x] [NIP-04 - Encrypted Direct Message](https://github.com/nostr-protocol/nips/blob/master/04.md)
134
+ - [x] [NIP-19 - Bech32-encoded entities](https://github.com/nostr-protocol/nips/blob/master/19.md)
227
135
 
228
- ## Development
136
+ ## 🔨 Development
229
137
 
230
138
  After checking out the repo, run `bin/setup` to install dependencies.
231
139
 
@@ -269,17 +177,22 @@ used to provide type checking and autocompletion in your editor. Run `bundle exe
269
177
  an RBS definition for the given Ruby file. And validate all definitions using [Steep](https://github.com/soutaro/steep)
270
178
  with the command `bundle exec steep check`.
271
179
 
272
- ## Contributing
180
+ ## 🐞 Issues & Bugs
181
+
182
+ If you find any issues or bugs, please report them [here](https://github.com/wilsonsilva/nostr/issues), I will be happy
183
+ to have a look at them and fix them as soon as possible.
184
+
185
+ ## 🤝 Contributing
273
186
 
274
187
  Bug reports and pull requests are welcome on GitHub at https://github.com/wilsonsilva/nostr.
275
188
  This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere
276
189
  to the [code of conduct](https://github.com/wilsonsilva/nostr/blob/main/CODE_OF_CONDUCT.md).
277
190
 
278
- ## License
191
+ ## 📜 License
279
192
 
280
193
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
281
194
 
282
- ## Code of Conduct
195
+ ## 👔 Code of Conduct
283
196
 
284
197
  Everyone interacting in the Nostr project's codebases, issue trackers, chat rooms and mailing lists is expected
285
198
  to follow the [code of conduct](https://github.com/wilsonsilva/nostr/blob/main/CODE_OF_CONDUCT.md).
data/Steepfile CHANGED
@@ -6,7 +6,9 @@ target :lib do
6
6
  check 'lib'
7
7
 
8
8
  # Core libraries
9
+ library 'base64'
9
10
  library 'digest'
11
+ library 'openssl'
10
12
  library 'securerandom'
11
13
 
12
14
  # Gems
data/docs/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ /node_modules/
2
+ .vitepress/dist
3
+ .vitepress/temp
4
+ .vitepress/cache
@@ -0,0 +1,112 @@
1
+ import { defineConfig } from 'vitepress'
2
+ import { withMermaid } from "vitepress-plugin-mermaid";
3
+
4
+ // https://vitepress.dev/reference/site-config
5
+ // https://www.npmjs.com/package/vitepress-plugin-mermaid
6
+ export default defineConfig(withMermaid({
7
+ title: "Nostr",
8
+ description: "Documentation of the Nostr Ruby gem",
9
+ // https://vitepress.dev/reference/site-config#head
10
+ head: [
11
+ ['link', { rel: 'icon', href: '/favicon.ico' }]
12
+ ],
13
+ themeConfig: {
14
+ // https://vitepress.dev/reference/default-theme-last-updated
15
+ lastUpdated: true,
16
+
17
+ // https://vitepress.dev/reference/default-theme-config
18
+ nav: [
19
+ { text: 'Home', link: '/' },
20
+ { text: 'Guide', link: '/getting-started/overview' }
21
+ ],
22
+
23
+ // https://vitepress.dev/reference/default-theme-search
24
+ search: {
25
+ provider: 'local'
26
+ },
27
+
28
+ // https://vitepress.dev/reference/default-theme-sidebar
29
+ sidebar: [
30
+ {
31
+ text: 'Getting started',
32
+ collapsed: false,
33
+ items: [
34
+ { text: 'Overview', link: '/getting-started/overview' },
35
+ { text: 'Installation', link: '/getting-started/installation' },
36
+ ]
37
+ },
38
+ {
39
+ text: 'Core',
40
+ collapsed: false,
41
+ items: [
42
+ { text: 'Client', link: '/core/client' },
43
+ { text: 'Keys', link: '/core/keys' },
44
+ { text: 'User', link: '/core/user' },
45
+ ]
46
+ },
47
+ {
48
+ text: 'Relays',
49
+ items: [
50
+ { text: 'Connecting to a relay', link: '/relays/connecting-to-a-relay' },
51
+ { text: 'Publishing events', link: '/relays/publishing-events' },
52
+ { text: 'Receiving events', link: '/relays/receiving-events' },
53
+ ]
54
+ },
55
+ {
56
+ text: 'Subscriptions',
57
+ collapsed: false,
58
+ items: [
59
+ { text: 'Creating a subscription', link: '/subscriptions/creating-a-subscription' },
60
+ { text: 'Filtering subscription events', link: '/subscriptions/filtering-subscription-events' },
61
+ { text: 'Updating a subscription', link: '/subscriptions/updating-a-subscription' },
62
+ { text: 'Deleting a subscription', link: '/subscriptions/deleting-a-subscription' },
63
+ ]
64
+ },
65
+ {
66
+ text: 'Events',
67
+ link: '/events',
68
+ collapsed: false,
69
+ items: [
70
+ { text: 'Set Metadata', link: '/events/set-metadata' },
71
+ { text: 'Text Note', link: '/events/text-note' },
72
+ { text: 'Recommend Server', link: '/events/recommend-server' },
73
+ { text: 'Contact List', link: '/events/contact-list' },
74
+ { text: 'Encrypted Direct Message', link: '/events/encrypted-direct-message' },
75
+ ]
76
+ },
77
+ {
78
+ text: 'Common use cases',
79
+ collapsed: false,
80
+ items: [
81
+ { text: 'Bech32 enc/decoding (NIP-19)', link: '/common-use-cases/bech32-encoding-and-decoding-(NIP-19)' },
82
+ ]
83
+ },
84
+ {
85
+ text: 'Implemented NIPs',
86
+ link: '/implemented-nips',
87
+ },
88
+ ],
89
+
90
+ // https://vitepress.dev/reference/default-theme-config#sociallinks
91
+ socialLinks: [
92
+ { icon: 'github', link: 'https://github.com/wilsonsilva/nostr' }
93
+ ],
94
+
95
+ // https://vitepress.dev/reference/default-theme-edit-link
96
+ editLink: {
97
+ pattern: 'https://github.com/wilsonsilva/nostr/edit/main/docs/:path',
98
+ text: 'Edit this page on GitHub'
99
+ },
100
+
101
+ // https://vitepress.dev/reference/default-theme-footer
102
+ footer: {
103
+ message: 'Released under the <a href="https://github.com/wilsonsilva/nostr/blob/main/LICENSE.txt">MIT License</a>.',
104
+ copyright: 'Copyright © 2023-present <a href="https://github.com/wilsonsilva">Wilson Silva</a>'
105
+ }
106
+ },
107
+
108
+ // https://vitepress.dev/reference/site-config#ignoredeadlinks
109
+ ignoreDeadLinks: [
110
+ /^https?:\/\/localhost/
111
+ ],
112
+ }))
data/docs/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # Nostr Docs
2
+
3
+ VitePress-powered documentation for the Nostr Ruby gem.
4
+
5
+ ## Live Demo
6
+
7
+ https://nostr-ruby.com/
8
+
9
+ ## Development
10
+
11
+ ### Requirements
12
+
13
+ - [Bun](https://bun.sh/)
14
+
15
+ ### Installation
16
+
17
+ ```shell
18
+ bun install
19
+ ```
20
+
21
+ ### Tasks
22
+
23
+ The `docs:dev` script will start a local dev server with instant hot updates. Run it with the following command:
24
+
25
+ ```shell
26
+ bun run docs:dev
27
+ ```
28
+
29
+ Run this command to build the docs:
30
+
31
+ ```shell
32
+ bun run docs:build
33
+ ```
34
+
35
+ Once built, preview it locally by running:
36
+
37
+ ```shell
38
+ bun run docs:preview
39
+ ```
40
+
41
+ The preview command will boot up a local static web server that will serve the output directory .`vitepress/dist` at
42
+ http://localhost:4173. You can use this to make sure everything looks good before pushing to production.
43
+
44
+