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
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
+