nostr 0.4.0 → 0.5.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 (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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd56d59d68235fe8fa4bceb67df4a7e83d4b6a8295ed31cc0152002800ad7d23
4
- data.tar.gz: 56b70ada7f9fd6cd29be1c7bc23b7a23adc49bfe2f8d8de48300f70709626a3e
3
+ metadata.gz: 168cbde3fb029345d4fa10043eead7c194a57fe3ee23c12b76bbaf79b1bdc71d
4
+ data.tar.gz: ff1a1837e897a8c0ad233a61ed4526fe3e4087c04474e54778a00a0d4313e361
5
5
  SHA512:
6
- metadata.gz: be113a67cd651739cc3bac1deb4bba30e3598cfd787e8971a764e82d58c03ad1c918d3edd14630bbb1a5e2c6504c3c344859f0449a1774df7bb7bf0d3c38f537
7
- data.tar.gz: c80bbf1f4d3caa25f48e1630b650587a2319197d7edba33e824b17e93f6355d8593c41364ad1fdb86a834d8cae63ad9f15e8feacae953b0ff8d7294f09c2c765
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
@@ -38,3 +47,17 @@ Metrics/ParameterLists:
38
47
 
39
48
  RSpec/ExampleLength:
40
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,9 +1,42 @@
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
+
7
40
  ## [0.4.0] - 2023-02-25
8
41
 
9
42
  ### Removed
@@ -49,6 +82,8 @@ principles of immutability and was a major source of internal complexity as I ne
49
82
 
50
83
  - Initial release
51
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
52
87
  [0.3.0]: https://github.com/wilsonsilva/nostr/compare/v0.2.0...v0.3.0
53
88
  [0.2.0]: https://github.com/wilsonsilva/nostr/compare/v0.1.0...v0.2.0
54
89
  [0.1.0]: https://github.com/wilsonsilva/nostr/compare/7fded5...v0.1.0
data/README.md CHANGED
@@ -4,31 +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
9
  ## Table of contents
11
10
 
12
- - [Installation](#installation)
13
- - [Usage](#usage)
14
- * [Requiring the gem](#requiring-the-gem)
15
- * [Generating a keypair](#generating-a-keypair)
16
- * [Generating a private key and a public key](#generating-a-private-key-and-a-public-key)
17
- * [Connecting to a Relay](#connecting-to-a-relay)
18
- * [WebSocket events](#websocket-events)
19
- * [Requesting for events / creating a subscription](#requesting-for-events--creating-a-subscription)
20
- * [Stop previous subscriptions](#stop-previous-subscriptions)
21
- * [Publishing an event](#publishing-an-event)
22
- * [Creating/updating your contact list](#creatingupdating-your-contact-list)
23
- * [Sending an encrypted direct message](#sending-an-encrypted-direct-message)
24
- - [Implemented NIPs](#implemented-nips)
25
- - [Development](#development)
11
+ - [Key features](#-key-features)
12
+ - [Installation](#-installation)
13
+ - [Quickstart](#-quickstart)
14
+ - [Documentation](#-documentation)
15
+ - [Implemented NIPs](#-implemented-nips)
16
+ - [Development](#-development)
26
17
  * [Type checking](#type-checking)
27
- - [Contributing](#contributing)
28
- - [License](#license)
29
- - [Code of Conduct](#code-of-conduct)
18
+ - [Contributing](#-contributing)
19
+ - [License](#-license)
20
+ - [Code of Conduct](#-code-of-conduct)
30
21
 
31
- ## Installation
22
+ ## 🔑 Key features
23
+
24
+ - Asynchronous
25
+ - Easy to use
26
+ - Fully documented
27
+ - Fully tested
28
+ - Fully typed
29
+
30
+ ## 📦 Installation
32
31
 
33
32
  Install the gem and add to the application's Gemfile by executing:
34
33
 
@@ -38,243 +37,103 @@ If bundler is not being used to manage dependencies, install the gem by executin
38
37
 
39
38
  $ gem install nostr
40
39
 
41
- ## Usage
40
+ ## ⚡️ Quickstart
42
41
 
43
- ### Requiring the gem
44
-
45
- 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).
46
44
 
47
45
  ```ruby
46
+ # Require the gem
48
47
  require 'nostr'
49
- ```
50
-
51
- ### Generating a keypair
52
-
53
- ```ruby
54
- keygen = Nostr::Keygen.new
55
- keypair = keygen.generate_key_pair
56
48
 
57
- keypair.private_key
58
- keypair.public_key
59
- ```
60
-
61
- ### Generating a private key and a public key
62
-
63
- ```ruby
64
- keygen = Nostr::Keygen.new
49
+ # Instantiate a client
50
+ client = Nostr::Client.new
65
51
 
66
- private_key = keygen.generate_private_key
67
- public_key = keygen.extract_public_key(private_key)
68
- ```
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
+ )
69
57
 
70
- ### 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
+ )
71
63
 
72
- 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
73
67
 
74
- You may instantiate multiple Clients and multiple Relays.
68
+ # Create a user with the keypair
69
+ user = Nostr::User.new(keypair: keypair)
75
70
 
76
- ```ruby
77
- client = Nostr::Client.new
78
- 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
+ )
79
76
 
77
+ # Connect asynchronously to a relay
78
+ relay = Nostr::Relay.new(url: 'wss://nostr.wine', name: 'Wine')
80
79
  client.connect(relay)
81
- ```
82
-
83
- ### WebSocket events
84
-
85
- All communication between clients and relays happen in WebSockets.
86
80
 
87
- The `:connect` event is fired when a connection with a WebSocket is opened. You must call `Nostr::Client#connect` first.
88
-
89
- ```ruby
81
+ # Listen asynchronously for the connect event
90
82
  client.on :connect do
91
- # all the code goes here
92
- end
93
- ```
94
-
95
- The `:close` event is fired when a connection with a WebSocket has been closed because of an error.
96
-
97
- ```ruby
98
- client.on :error do |error_message|
99
- puts error_message
100
- end
101
-
102
- # > Network error: wss://rsslay.fiatjaf.com: Unable to verify the server certificate for 'rsslay.fiatjaf.com'
103
- ```
104
-
105
- The `:message` event is fired when data is received through a WebSocket.
106
-
107
- ```ruby
108
- client.on :message do |message|
109
- puts message
110
- end
111
-
112
- # [
113
- # "EVENT",
114
- # "d34107357089bfc9882146d3bfab0386",
115
- # {
116
- # "content":"",
117
- # "created_at":1676456512,
118
- # "id":"18f63550da74454c5df7caa2a349edc5b2a6175ea4c5367fa4b4212781e5b310",
119
- # "kind":3,
120
- # "pubkey":"117a121fa41dc2caa0b3d6c5b9f42f90d114f1301d39f9ee96b646ebfee75e36",
121
- # "sig":"d171420bd62cf981e8f86f2dd8f8f86737ea2bbe2d98da88db092991d125535860d982139a3c4be39886188613a9912ef380be017686a0a8b74231dc6e0b03cb",
122
- # "tags":[
123
- # ["p","1cc821cc2d47191b15fcfc0f73afed39a86ac6fb34fbfa7993ee3e0f0186ef7c"]
124
- # ]
125
- # }
126
- # ]
127
- ```
128
-
129
- The `:close` event is fired when a connection with a WebSocket is closed.
130
-
131
- ```ruby
132
- client.on :close do |code, reason|
133
- # you may attempt to reconnect
134
-
135
- client.connect(relay)
136
- end
137
- ```
138
-
139
- ### Requesting for events / creating a subscription
140
-
141
- A client can request events and subscribe to new updates after it has established a connection with the Relay.
142
-
143
- You may use a `Nostr::Filter` instance with as many attributes as you wish:
83
+ # Send the event to the Relay
84
+ client.publish(text_note_event)
144
85
 
145
- ```ruby
146
- 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
147
89
  filter = Nostr::Filter.new(
148
- ids: ['8535d5e2d7b9dc07567f676fbe70428133c9884857e1915f5b1cc6514c2fdff8'],
149
- authors: ['ae00f88a885ce76afad5cbb2459ef0dcf0df0907adc6e4dac16e1bfbd7074577'],
150
- kinds: [Nostr::EventKind::TEXT_NOTE],
151
- e: ["f111593a72cc52a7f0978de5ecf29b4653d0cf539f1fa50d2168fc1dc8280e52"],
152
- p: ["f1f9b0996d4ff1bf75e79e4cc8577c89eb633e68415c7faf74cf17a07bf80bd8"],
153
- since: 1230981305,
154
- until: 1292190341,
155
- 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,
156
97
  )
157
98
 
158
- subscription = client.subscribe('a_random_subscription_id', filter)
159
- end
160
- ```
161
-
162
- With just a few:
99
+ # Subscribe to events matching conditions of a filter
100
+ subscription = client.subscribe(filter: filter)
163
101
 
164
- ```ruby
165
- client.on :connect do
166
- filter = Nostr::Filter.new(kinds: [Nostr::EventKind::TEXT_NOTE])
167
- subscription = client.subscribe('a_random_subscription_id', filter)
102
+ # Unsubscribe from events matching the filter above
103
+ client.unsubscribe(subscription.id)
168
104
  end
169
- ```
170
-
171
- Or omit the filter:
172
105
 
173
- ```ruby
174
- client.on :connect do
175
- subscription = client.subscribe('a_random_subscription_id')
106
+ # Listen for incoming messages and print them
107
+ client.on :message do |message|
108
+ puts message
176
109
  end
177
- ```
178
110
 
179
- Or even omit the subscription id:
180
-
181
- ```ruby
182
- client.on :connect do
183
- subscription = client.subscribe('a_random_subscription_id')
111
+ # Listen for error messages
112
+ client.on :error do |error_message|
113
+ # Handle the error
184
114
  end
185
- ```
186
-
187
- ### Stop previous subscriptions
188
-
189
- You can stop receiving messages from a subscription by calling `#unsubscribe`:
190
-
191
- ```ruby
192
- client.unsubscribe('your_subscription_id')
193
- ```
194
-
195
- ### Publishing an event
196
115
 
197
- To publish an event you need a keypair.
198
-
199
- ```ruby
200
- # Set up the private key
201
- private_key = 'a630b06e2f883378d0aa335b9adaf7734603e00433350b684fe53e184f08c58f'
202
- user = Nostr::User.new(private_key)
203
-
204
- # Create a signed event
205
- event = user.create_event(
206
- created_at: 1667422587, # optional, defaults to the current time
207
- kind: Nostr::EventKind::TEXT_NOTE,
208
- tags: [], # optional, defaults to []
209
- content: 'Your feedback is appreciated, now pay $8'
210
- )
211
-
212
- # Send it to the Relay
213
- client.publish(event)
214
- ```
215
-
216
- ### Creating/updating your contact list
217
-
218
- Every new contact list that gets published overwrites the past ones, so it should contain all entries.
219
-
220
- ```ruby
221
- # Creating a contact list event with 2 contacts
222
- update_contacts_event = user.create_event(
223
- kind: Nostr::EventKind::CONTACT_LIST,
224
- tags: [
225
- [
226
- "p", # mandatory
227
- "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245", # public key of the user to add to the contacts
228
- "wss://alicerelay.com/", # can be an empty string or can be omitted
229
- "alice" # can be an empty string or can be omitted
230
- ],
231
- [
232
- "p", # mandatory
233
- "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681", # public key of the user to add to the contacts
234
- "wss://bobrelay.com/nostr", # can be an empty string or can be omitted
235
- "bob" # can be an empty string or can be omitted
236
- ],
237
- ],
238
- )
239
-
240
- # Send it to the Relay
241
- client.publish(update_contacts_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
242
120
  ```
243
121
 
244
- ### Sending an encrypted direct message
122
+ ## 📚 Documentation
245
123
 
246
- ```ruby
247
- sender_private_key = '3185a47e3802f956ca5a2b4ea606c1d51c7610f239617e8f0f218d55bdf2b757'
124
+ I made a detailed documentation for this gem and it's usage. The code is also fully documented using YARD.
248
125
 
249
- encrypted_direct_message = Nostr::Events::EncryptedDirectMessage.new(
250
- sender_private_key: sender_private_key,
251
- recipient_public_key: '6c31422248998e300a1a457167565da7d15d0da96651296ee2791c29c11b6aa0',
252
- plain_text: 'Your feedback is appreciated, now pay $8',
253
- previous_direct_message: 'ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460' # optional
254
- )
255
-
256
- encrypted_direct_message.sign(sender_private_key)
257
-
258
- # #<Nostr::Events::EncryptedDirectMessage:0x0000000104c9fa68
259
- # @content="mjIFNo1sSP3KROE6QqhWnPSGAZRCuK7Np9X+88HSVSwwtFyiZ35msmEVoFgRpKx4?iv=YckChfS2oWCGpMt1uQ4GbQ==",
260
- # @created_at=1676456512,
261
- # @id="daac98826d5eb29f7c013b6160986c4baf4fe6d4b995df67c1b480fab1839a9b",
262
- # @kind=4,
263
- # @pubkey="8a9d69c56e3c691bec8f9565e4dcbe38ae1d88fffeec3ce66b9f47558a3aa8ca",
264
- # @sig="028bb5f5bab0396e2065000c84a4bcce99e68b1a79bb1b91a84311546f49c5b67570b48d4a328a1827e7a8419d74451347d4f55011a196e71edab31aa3d6bdac",
265
- # @tags=[["p", "6c31422248998e300a1a457167565da7d15d0da96651296ee2791c29c11b6aa0"], ["e", "ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460"]]>
126
+ - [Guide documentation](https://nostr-ruby.com)
127
+ - [YARD documentation](https://rubydoc.info/gems/nostr)
266
128
 
267
- # Send it to the Relay
268
- client.publish(encrypted_direct_message)
269
- ````
129
+ ## Implemented NIPs
270
130
 
271
- ## Implemented NIPs
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)
272
135
 
273
- - [x] [NIP-01 - Client](https://github.com/nostr-protocol/nips/blob/master/01.md)
274
- - [x] [NIP-02 - Client](https://github.com/nostr-protocol/nips/blob/master/02.md)
275
- - [x] [NIP-04 - Client](https://github.com/nostr-protocol/nips/blob/master/04.md)
276
-
277
- ## Development
136
+ ## 🔨 Development
278
137
 
279
138
  After checking out the repo, run `bin/setup` to install dependencies.
280
139
 
@@ -318,17 +177,22 @@ used to provide type checking and autocompletion in your editor. Run `bundle exe
318
177
  an RBS definition for the given Ruby file. And validate all definitions using [Steep](https://github.com/soutaro/steep)
319
178
  with the command `bundle exec steep check`.
320
179
 
321
- ## 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
322
186
 
323
187
  Bug reports and pull requests are welcome on GitHub at https://github.com/wilsonsilva/nostr.
324
188
  This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere
325
189
  to the [code of conduct](https://github.com/wilsonsilva/nostr/blob/main/CODE_OF_CONDUCT.md).
326
190
 
327
- ## License
191
+ ## 📜 License
328
192
 
329
193
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
330
194
 
331
- ## Code of Conduct
195
+ ## 👔 Code of Conduct
332
196
 
333
197
  Everyone interacting in the Nostr project's codebases, issue trackers, chat rooms and mailing lists is expected
334
198
  to follow the [code of conduct](https://github.com/wilsonsilva/nostr/blob/main/CODE_OF_CONDUCT.md).
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
+