nostr 0.3.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 (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
+