DhanHQ 2.1.10 → 2.2.1

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.rubocop_todo.yml +143 -118
  4. data/CHANGELOG.md +127 -0
  5. data/CODE_REVIEW_ISSUES.md +397 -0
  6. data/FIXES_APPLIED.md +373 -0
  7. data/GUIDE.md +41 -0
  8. data/README.md +55 -0
  9. data/RELEASING.md +60 -0
  10. data/REVIEW_SUMMARY.md +120 -0
  11. data/VERSION_UPDATE.md +82 -0
  12. data/core +0 -0
  13. data/docs/AUTHENTICATION.md +63 -0
  14. data/docs/DATA_API_PARAMETERS.md +278 -0
  15. data/docs/PR_2.2.0.md +48 -0
  16. data/docs/RELEASE_GUIDE.md +492 -0
  17. data/docs/TESTING_GUIDE.md +1514 -0
  18. data/docs/live_order_updates.md +25 -1
  19. data/docs/rails_integration.md +29 -0
  20. data/docs/websocket_integration.md +22 -0
  21. data/lib/DhanHQ/client.rb +65 -9
  22. data/lib/DhanHQ/configuration.rb +27 -0
  23. data/lib/DhanHQ/constants.rb +1 -1
  24. data/lib/DhanHQ/contracts/place_order_contract.rb +51 -0
  25. data/lib/DhanHQ/core/base_model.rb +17 -10
  26. data/lib/DhanHQ/errors.rb +4 -0
  27. data/lib/DhanHQ/helpers/request_helper.rb +17 -2
  28. data/lib/DhanHQ/helpers/response_helper.rb +34 -13
  29. data/lib/DhanHQ/models/expired_options_data.rb +0 -6
  30. data/lib/DhanHQ/models/instrument_helpers.rb +4 -4
  31. data/lib/DhanHQ/models/order.rb +19 -2
  32. data/lib/DhanHQ/models/order_update.rb +0 -4
  33. data/lib/DhanHQ/rate_limiter.rb +40 -6
  34. data/lib/DhanHQ/version.rb +1 -1
  35. data/lib/DhanHQ/ws/client.rb +12 -5
  36. data/lib/DhanHQ/ws/connection.rb +16 -2
  37. data/lib/DhanHQ/ws/market_depth/client.rb +3 -1
  38. data/lib/DhanHQ/ws/market_depth.rb +12 -12
  39. data/lib/DhanHQ/ws/orders/client.rb +76 -11
  40. data/lib/DhanHQ/ws/orders/connection.rb +3 -1
  41. metadata +18 -5
  42. data/lib/DhanHQ/contracts/modify_order_contract_copy.rb +0 -100
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 300207afdb6b293a9b73b5cf6d2bb11da0eb8251bed6ab489c115287ab201051
4
- data.tar.gz: 49fde0cde20215c959d167860529ccaa2e984b1aa46653f8024a463a8ff8db53
3
+ metadata.gz: 7f0476726fe811ed0f25424e4e29c0e4d0b2bb7f18732883aed5902ae8fde017
4
+ data.tar.gz: ece7774203912cb63ce57c9b723450290e01239415d573aa4b5a190039023ded
5
5
  SHA512:
6
- metadata.gz: eb75dbe33b1c937cb825dde8f8a2e86748f1fce2f230a52190ca5862a900f40b64d7f17319cf34c6847253d5c98ab42396e6ee5d46b9ae66c26c34c473d7fb69
7
- data.tar.gz: d491b32c1ec671414d2d1c7bdef765cde05631bca5be3c41ff1df66d7060901b6e58b5612092891e25b3d06b7b920525ef69097a91b3104cdd2364b8c97c3a6f
6
+ metadata.gz: 4733638b5d2687f0f4ebfb9f08925ae980ce90d822fe0473438b43057b242e64f6cf3915a69b602adc87eeb9b2d282c62c2446ecef44cd2f327d2997844b5d52
7
+ data.tar.gz: fec3e15617126ddc8f218765b284f1ba8e7c14defd0c3d41b3b4d5cf16480188a0abdb5f449835c7b4243ed21a606a38566ca4858a50ecf56f1ed8824f4864d8
data/.rubocop.yml CHANGED
@@ -8,7 +8,7 @@ require:
8
8
  - rubocop-rake
9
9
 
10
10
  AllCops:
11
- TargetRubyVersion: 3.1
11
+ TargetRubyVersion: 3.2
12
12
  NewCops: enable
13
13
 
14
14
  Style/StringLiterals:
data/.rubocop_todo.yml CHANGED
@@ -1,26 +1,31 @@
1
1
  # This configuration was generated by
2
- # `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 999`
3
- # on 2025-10-12 11:03:03 UTC using RuboCop version 1.80.2.
2
+ # `rubocop --auto-gen-config --exclude-limit 9999`
3
+ # on 2026-01-19 19:18:55 UTC using RuboCop version 1.82.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 4
10
- # This cop supports safe autocorrection (--autocorrect).
11
- # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
12
- # URISchemes: http, https
13
- Layout/LineLength:
14
- Exclude:
15
- - 'lib/DhanHQ/ws/decoder.rb'
16
-
17
- # Offense count: 2
9
+ # Offense count: 3
18
10
  # Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
19
11
  Lint/DuplicateBranch:
20
12
  Exclude:
21
13
  - 'bin/ta_strategy.rb'
14
+ - 'lib/DhanHQ/helpers/response_helper.rb'
22
15
  - 'lib/dhanhq/analysis/helpers/bias_aggregator.rb'
23
16
 
17
+ # Offense count: 1
18
+ # Configuration parameters: AllowComments, AllowEmptyLambdas.
19
+ Lint/EmptyBlock:
20
+ Exclude:
21
+ - 'spec/support/script_data_helper.rb'
22
+
23
+ # Offense count: 1
24
+ # This cop supports safe autocorrection (--autocorrect).
25
+ Lint/RedundantCopDisableDirective:
26
+ Exclude:
27
+ - 'spec/dhan_hq/models/order_spec.rb'
28
+
24
29
  # Offense count: 3
25
30
  # Configuration parameters: AllowComments, AllowNil.
26
31
  Lint/SuppressedException:
@@ -28,134 +33,55 @@ Lint/SuppressedException:
28
33
  - 'lib/DhanHQ/ws/connection.rb'
29
34
  - 'lib/DhanHQ/ws/registry.rb'
30
35
 
31
- # Offense count: 42
32
- # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
36
+ # Offense count: 72
37
+ # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
33
38
  Metrics/AbcSize:
34
- Exclude:
35
- - 'bin/ta_strategy.rb'
36
- - 'bin/ws_feed_test.rb'
37
- - 'lib/DhanHQ/helpers/response_helper.rb'
38
- - 'lib/DhanHQ/models/order.rb'
39
- - 'lib/DhanHQ/rate_limiter.rb'
40
- - 'lib/DhanHQ/ws/client.rb'
41
- - 'lib/DhanHQ/ws/connection.rb'
42
- - 'lib/DhanHQ/ws/decoder.rb'
43
- - 'lib/DhanHQ/ws/orders/connection.rb'
44
- - 'lib/DhanHQ/ws/websocket_packet_parser.rb'
45
- - 'lib/dhan_hq.rb'
46
- - 'lib/dhanhq/analysis/helpers/bias_aggregator.rb'
47
- - 'lib/dhanhq/analysis/multi_timeframe_analyzer.rb'
48
- - 'lib/dhanhq/analysis/options_buying_advisor.rb'
49
- - 'lib/ta/candles.rb'
50
- - 'lib/ta/fetcher.rb'
51
- - 'lib/ta/indicators.rb'
52
- - 'lib/ta/technical_analysis.rb'
39
+ Max: 100
53
40
 
54
- # Offense count: 1
55
- # Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
41
+ # Offense count: 2
42
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
56
43
  # AllowedMethods: refine
57
44
  Metrics/BlockLength:
58
- Exclude:
59
- - 'lib/DhanHQ/ws/connection.rb'
45
+ Max: 32
60
46
 
61
- # Offense count: 8
62
- # Configuration parameters: CountComments, Max, CountAsOne.
47
+ # Offense count: 11
48
+ # Configuration parameters: CountComments, CountAsOne.
63
49
  Metrics/ClassLength:
64
- Exclude:
65
- - 'lib/DhanHQ/core/base_model.rb'
66
- - 'lib/DhanHQ/models/order.rb'
67
- - 'lib/DhanHQ/ws/connection.rb'
68
- - 'lib/DhanHQ/ws/orders/connection.rb'
69
- - 'lib/DhanHQ/ws/websocket_packet_parser.rb'
70
- - 'lib/dhanhq/analysis/multi_timeframe_analyzer.rb'
71
- - 'lib/dhanhq/analysis/options_buying_advisor.rb'
72
- - 'lib/ta/technical_analysis.rb'
50
+ Max: 631
73
51
 
74
- # Offense count: 25
75
- # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
52
+ # Offense count: 40
53
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
76
54
  Metrics/CyclomaticComplexity:
77
- Exclude:
78
- - 'bin/ta_strategy.rb'
79
- - 'bin/ws_feed_test.rb'
80
- - 'lib/DhanHQ/helpers/response_helper.rb'
81
- - 'lib/DhanHQ/models/order.rb'
82
- - 'lib/DhanHQ/ws/connection.rb'
83
- - 'lib/DhanHQ/ws/decoder.rb'
84
- - 'lib/DhanHQ/ws/orders/connection.rb'
85
- - 'lib/DhanHQ/ws/segments.rb'
86
- - 'lib/DhanHQ/ws/websocket_packet_parser.rb'
87
- - 'lib/dhanhq/analysis/helpers/bias_aggregator.rb'
88
- - 'lib/dhanhq/analysis/multi_timeframe_analyzer.rb'
89
- - 'lib/dhanhq/analysis/options_buying_advisor.rb'
90
- - 'lib/ta/candles.rb'
91
- - 'lib/ta/indicators.rb'
92
- - 'lib/ta/technical_analysis.rb'
55
+ Max: 33
93
56
 
94
- # Offense count: 52
95
- # Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
57
+ # Offense count: 101
58
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
96
59
  Metrics/MethodLength:
97
- Exclude:
98
- - 'bin/ta_strategy.rb'
99
- - 'bin/ws_feed_test.rb'
100
- - 'lib/DhanHQ/core/base_model.rb'
101
- - 'lib/DhanHQ/helpers/response_helper.rb'
102
- - 'lib/DhanHQ/models/holding.rb'
103
- - 'lib/DhanHQ/models/instrument.rb'
104
- - 'lib/DhanHQ/models/ledger_entry.rb'
105
- - 'lib/DhanHQ/models/order.rb'
106
- - 'lib/DhanHQ/rate_limiter.rb'
107
- - 'lib/DhanHQ/ws/connection.rb'
108
- - 'lib/DhanHQ/ws/decoder.rb'
109
- - 'lib/DhanHQ/ws/orders/connection.rb'
110
- - 'lib/DhanHQ/ws/segments.rb'
111
- - 'lib/DhanHQ/ws/singleton_lock.rb'
112
- - 'lib/DhanHQ/ws/websocket_packet_parser.rb'
113
- - 'lib/dhanhq/analysis/helpers/bias_aggregator.rb'
114
- - 'lib/dhanhq/analysis/multi_timeframe_analyzer.rb'
115
- - 'lib/dhanhq/analysis/options_buying_advisor.rb'
116
- - 'lib/ta/candles.rb'
117
- - 'lib/ta/fetcher.rb'
118
- - 'lib/ta/indicators.rb'
119
- - 'lib/ta/technical_analysis.rb'
60
+ Max: 88
120
61
 
121
- # Offense count: 3
122
- # Configuration parameters: CountComments, Max, CountAsOne.
62
+ # Offense count: 5
63
+ # Configuration parameters: CountComments, CountAsOne.
123
64
  Metrics/ModuleLength:
124
- Exclude:
125
- - 'bin/ta_strategy.rb'
126
- - 'lib/DhanHQ/constants.rb'
127
- - 'lib/ta/indicators.rb'
65
+ Max: 158
128
66
 
129
67
  # Offense count: 1
130
- # Configuration parameters: Max, CountKeywordArgs, MaxOptionalParameters.
68
+ # Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
131
69
  Metrics/ParameterLists:
132
- Exclude:
133
- - 'lib/ta/technical_analysis.rb'
70
+ Max: 7
134
71
 
135
- # Offense count: 21
136
- # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
72
+ # Offense count: 31
73
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
137
74
  Metrics/PerceivedComplexity:
138
- Exclude:
139
- - 'bin/ta_strategy.rb'
140
- - 'bin/ws_feed_test.rb'
141
- - 'lib/DhanHQ/helpers/response_helper.rb'
142
- - 'lib/DhanHQ/models/order.rb'
143
- - 'lib/DhanHQ/ws/connection.rb'
144
- - 'lib/DhanHQ/ws/decoder.rb'
145
- - 'lib/DhanHQ/ws/orders/connection.rb'
146
- - 'lib/dhanhq/analysis/helpers/bias_aggregator.rb'
147
- - 'lib/dhanhq/analysis/multi_timeframe_analyzer.rb'
148
- - 'lib/dhanhq/analysis/options_buying_advisor.rb'
149
- - 'lib/ta/candles.rb'
150
- - 'lib/ta/indicators.rb'
151
- - 'lib/ta/technical_analysis.rb'
75
+ Max: 28
152
76
 
153
- # Offense count: 1
77
+ # Offense count: 5
154
78
  # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
155
79
  # AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
156
80
  Naming/MethodParameterName:
157
81
  Exclude:
82
+ - 'lib/DhanHQ/ws/base_connection.rb'
158
83
  - 'lib/DhanHQ/ws/connection.rb'
84
+ - 'lib/DhanHQ/ws/orders/connection.rb'
159
85
 
160
86
  # Offense count: 7
161
87
  # Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
@@ -168,18 +94,117 @@ Naming/PredicateMethod:
168
94
  - 'lib/DhanHQ/models/super_order.rb'
169
95
  - 'lib/DhanHQ/ws/singleton_lock.rb'
170
96
 
171
- # Offense count: 5
97
+ # Offense count: 13
172
98
  # Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
173
99
  # SupportedStyles: snake_case, normalcase, non_integer
174
100
  # AllowedIdentifiers: TLS1_1, TLS1_2, capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
175
101
  Naming/VariableNumber:
176
102
  Exclude:
103
+ - 'lib/DhanHQ/ws/base_connection.rb'
177
104
  - 'lib/DhanHQ/ws/connection.rb'
105
+ - 'lib/DhanHQ/ws/market_depth/client.rb'
178
106
  - 'lib/DhanHQ/ws/orders/connection.rb'
179
107
 
180
- # Offense count: 3
108
+ # Offense count: 4
181
109
  # Configuration parameters: MinSize.
182
110
  Performance/CollectionLiteralInLoop:
183
111
  Exclude:
112
+ - 'lib/DhanHQ/ws/base_connection.rb'
184
113
  - 'lib/dhanhq/analysis/multi_timeframe_analyzer.rb'
185
114
  - 'lib/ta/fetcher.rb'
115
+
116
+ # Offense count: 1
117
+ Performance/MapMethodChain:
118
+ Exclude:
119
+ - 'lib/DhanHQ/ws/market_depth/client.rb'
120
+
121
+ # Offense count: 1
122
+ RSpec/BeforeAfterAll:
123
+ Exclude:
124
+ - '**/spec/spec_helper.rb'
125
+ - '**/spec/rails_helper.rb'
126
+ - '**/spec/support/**/*.rb'
127
+ - 'spec/dhan_hq/configuration_spec.rb'
128
+
129
+ # Offense count: 4
130
+ # Configuration parameters: AssignmentOnly.
131
+ RSpec/InstanceVariable:
132
+ Exclude:
133
+ - 'spec/dhan_hq/configuration_spec.rb'
134
+
135
+ # Offense count: 6
136
+ # Configuration parameters: EnforcedStyle.
137
+ # SupportedStyles: have_received, receive
138
+ RSpec/MessageSpies:
139
+ Exclude:
140
+ - 'spec/dhan_hq/base_model_spec.rb'
141
+ - 'spec/dhan_hq/helpers/response_helper_spec.rb'
142
+ - 'spec/dhan_hq/ws/orders/client_spec.rb'
143
+
144
+ # Offense count: 2
145
+ RSpec/RepeatedExample:
146
+ Exclude:
147
+ - 'spec/dhan_hq/contracts/expired_options_data_contract_spec.rb'
148
+
149
+ # Offense count: 1
150
+ # Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
151
+ # SupportedInflectors: default, active_support
152
+ RSpec/SpecFilePathFormat:
153
+ Exclude:
154
+ - '**/spec/routing/**/*'
155
+ - 'spec/dhan_hq/helpers/response_helper_spec.rb'
156
+
157
+ # Offense count: 1
158
+ # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
159
+ RSpec/VerifiedDoubles:
160
+ Exclude:
161
+ - 'spec/dhan_hq/ws/orders/client_spec.rb'
162
+
163
+ # Offense count: 3
164
+ # Configuration parameters: AllowedConstants.
165
+ Style/Documentation:
166
+ Exclude:
167
+ - 'spec/**/*'
168
+ - 'test/**/*'
169
+ - 'bin/comprehensive_test.rb'
170
+ - 'bin/test_helpers.rb'
171
+ - 'lib/DhanHQ/ws/market_depth.rb'
172
+
173
+ # Offense count: 1
174
+ # This cop supports safe autocorrection (--autocorrect).
175
+ # Configuration parameters: EnforcedStyle, AllowComments.
176
+ # SupportedStyles: empty, nil, both
177
+ Style/EmptyElse:
178
+ Exclude:
179
+ - 'lib/DhanHQ/ws/market_depth/decoder.rb'
180
+
181
+ # Offense count: 30
182
+ # This cop supports safe autocorrection (--autocorrect).
183
+ Style/IfUnlessModifier:
184
+ Exclude:
185
+ - 'bin/ta_strategy.rb'
186
+ - 'lib/DhanHQ/contracts/order_contract.rb'
187
+ - 'lib/DhanHQ/contracts/place_order_contract.rb'
188
+ - 'lib/DhanHQ/contracts/slice_order_contract.rb'
189
+ - 'lib/DhanHQ/helpers/response_helper.rb'
190
+ - 'lib/DhanHQ/models/expired_options_data.rb'
191
+ - 'lib/DhanHQ/models/funds.rb'
192
+ - 'lib/DhanHQ/models/trade.rb'
193
+ - 'lib/DhanHQ/rate_limiter.rb'
194
+ - 'lib/DhanHQ/ws/orders/client.rb'
195
+ - 'lib/dhanhq/analysis/options_buying_advisor.rb'
196
+ - 'lib/ta/indicators.rb'
197
+ - 'spec/spec_helper.rb'
198
+
199
+ # Offense count: 1
200
+ # Configuration parameters: Max.
201
+ Style/SafeNavigationChainLength:
202
+ Exclude:
203
+ - 'lib/DhanHQ/ws/market_depth/client.rb'
204
+
205
+ # Offense count: 31
206
+ # This cop supports safe autocorrection (--autocorrect).
207
+ # Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
208
+ # URISchemes: http, https
209
+ Layout/LineLength:
210
+ Max: 181
data/CHANGELOG.md CHANGED
@@ -1,5 +1,132 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [2.2.0] - 2026-01-31
4
+
5
+ ### Authentication & token handling
6
+
7
+ - **Dynamic access token resolution**: Token can be resolved at request time via `config.access_token_provider` (Proc/lambda). When set, the provider is called on each request; when not set, the gem falls back to `config.access_token`. No memoization — token is fetched per request for production-safe rotation.
8
+ - **Auto-expiry detection**: API error code **807** (token expired) now raises `DhanHQ::TokenExpiredError` so callers can handle expiry explicitly. Error codes 401, 807, 809, and 808 are treated as auth failures for retry logic.
9
+ - **Retry-on-401 with token re-fetch**: When the API returns 401 or token-expired (InvalidAuthenticationError, InvalidTokenError, TokenExpiredError, AuthenticationFailedError) and `config.access_token_provider` is set, the client retries the request **once** after the next token resolution (provider is called again). No separate “refresh” call — the provider is the source of the new token.
10
+ - **Optional `on_token_expired` hook**: `config.on_token_expired` (callable) is invoked when an auth failure triggers a retry, before the retry is performed. Use for logging or refreshing token in your store; the retry then uses the token from `access_token_provider`.
11
+ - **`DhanHQ::AuthenticationError`**: New error for local auth failures (missing token or provider returned nil/empty). API-level auth errors continue to use `InvalidAuthenticationError` / `InvalidTokenError` / `TokenExpiredError` as before.
12
+
13
+ ### Configuration
14
+
15
+ - **New**: `config.access_token_provider` — callable that returns the access token string at request time.
16
+ - **New**: `config.on_token_expired` — optional callable invoked when 401/token-expired triggers a retry (only when `access_token_provider` is set).
17
+ - **New**: `config.resolved_access_token` — returns the token to use (from provider or static `access_token`); raises `AuthenticationError` if provider returns nil/empty.
18
+
19
+ ### Errors
20
+
21
+ - **New**: `DhanHQ::AuthenticationError` — raised when token cannot be resolved (missing config or provider returned nil/empty).
22
+ - **New**: `DhanHQ::TokenExpiredError` — raised when API returns error code 807 (token expired). Mapped from `DHAN_ERROR_MAPPING["807"]`.
23
+
24
+ ### Tests
25
+
26
+ - **WebMock specs for auth failures**: `spec/dhan_hq/client_spec.rb` — contexts for 401, 403, 807, retry-on-401 with provider, retry then raise when 401 persists, and `on_token_expired` hook.
27
+ - **Response helper**: Spec for 807 → TokenExpiredError in `spec/dhan_hq/helpers/response_helper_spec.rb`.
28
+
29
+ ### Documentation
30
+
31
+ - **README.md**: New subsection “Dynamic access token (optional)” under Configuration.
32
+ - **GUIDE.md**: Short “Dynamic access token” note and link to docs/AUTHENTICATION.md.
33
+ - **docs/AUTHENTICATION.md**: New doc for static vs dynamic token, retry-on-401, and auth-related errors.
34
+ - **docs/TESTING_GUIDE.md**: Optional access_token_provider / on_token_expired in config examples.
35
+ - **docs/rails_integration.md**: “Dynamic access token (optional)” with Rails initializer example.
36
+ - **docs/websocket_integration.md**, **docs/live_order_updates.md**: Pointer to docs/AUTHENTICATION.md for dynamic token.
37
+
38
+ ### Backward compatibility
39
+
40
+ - **Non-breaking**: Existing `config.access_token = "static-token"` continues to work. `access_token_provider` is optional. Safe to release as a **minor** version bump.
41
+
42
+ ---
43
+
44
+ ## [2.1.11] - 2025-01-27
45
+
46
+ This release includes comprehensive bug fixes, security improvements, and reliability enhancements. All changes are **backward compatible** - no breaking changes.
47
+
48
+ ### 🔴 Critical Fixes
49
+
50
+ #### Thread Safety & Concurrency
51
+ - **Rate limiter race condition**: Fixed thread safety issue where cleanup threads modified shared state without synchronization. Added mutex protection and graceful shutdown mechanism.
52
+ - **WebSocket thread safety**: Fixed callback iteration race condition by creating frozen snapshots to prevent modification during event emission.
53
+
54
+ #### Error Handling & Validation
55
+ - **Client credential validation**: Moved validation to request time (in `build_headers`) rather than initialization, maintaining backward compatibility while ensuring credentials are validated before API calls.
56
+ - **WebSocket error handling**: Added proper cleanup and state reset on exceptions, improved logging with backtraces for better debugging.
57
+ - **Price field validation**: Added comprehensive validation for all float fields (price, trigger_price, bo_profit_value, bo_stop_loss_value, drv_strike_price) to reject NaN, Infinity, and values exceeding reasonable bounds (1,000,000,000).
58
+
59
+ ### 🟠 High Priority Fixes
60
+
61
+ #### Memory Management
62
+ - **Order tracker memory leak**: Fixed unbounded memory growth in WebSocket order tracker by implementing automatic cleanup with configurable limits:
63
+ - Maximum tracked orders: 10,000 (configurable via `DHAN_WS_MAX_TRACKED_ORDERS`)
64
+ - Maximum order age: 7 days (configurable via `DHAN_WS_MAX_ORDER_AGE`)
65
+ - Automatic cleanup thread runs hourly
66
+
67
+ #### Reliability & Error Handling
68
+ - **JSON parse error handling**: Improved error handling for invalid JSON responses. Empty strings return empty hash (backward compatible), but truly invalid JSON now raises `DataError` with detailed logging.
69
+ - **Timeout configuration**: Added configurable timeouts to prevent requests from hanging indefinitely:
70
+ - Connection timeout: 10s (configurable via `DHAN_CONNECT_TIMEOUT`)
71
+ - Read timeout: 30s (configurable via `DHAN_READ_TIMEOUT`)
72
+ - Write timeout: 30s (configurable via `DHAN_WRITE_TIMEOUT`)
73
+ - **Retry logic**: Added automatic retry with exponential backoff for transient errors (RateLimitError, InternalServerError, NetworkError, timeouts). Default: 3 retries with exponential backoff (1s, 2s, 4s, capped at 30s).
74
+
75
+ ### 🟡 Medium Priority Fixes
76
+
77
+ #### Code Quality & Reliability
78
+ - **Order modification validation**: Added warning logs for invalid order states (TRADED, CANCELLED, EXPIRED, CLOSED) but still attempts API call - API handles final validation (backward compatible).
79
+ - **Error mapping**: Added logging for unmapped error codes to aid investigation and debugging.
80
+ - **Rate limiter cleanup**: Added `shutdown()` method to gracefully stop cleanup threads and prevent resource leaks.
81
+ - **Order operation logging**: Added structured logging for order placement and modification operations to aid debugging.
82
+
83
+ ### 🔵 Low Priority Fixes
84
+
85
+ #### Code Quality
86
+ - **Code deduplication**: Made `delete` delegate to `destroy`, removing duplicate code.
87
+ - **Type consistency**: Added `.to_s` conversion for `id` method to ensure consistent string return type.
88
+ - **Response format logging**: Added logging for unexpected response formats in collection parsing to help identify API changes.
89
+
90
+ ### ✅ API Compliance
91
+
92
+ - **Header validation**: Validates required headers (`access_token`, `client_id` for DATA APIs) before making requests, providing clear error messages.
93
+ - **202 Accepted status**: Properly handles `202 Accepted` status code for async operations (e.g., position conversion).
94
+
95
+ ### ➕ Added
96
+
97
+ #### Configuration Options
98
+ - **Timeout configuration** via environment variables:
99
+ - `DHAN_CONNECT_TIMEOUT` - Connection timeout in seconds (default: 10)
100
+ - `DHAN_READ_TIMEOUT` - Read timeout in seconds (default: 30)
101
+ - `DHAN_WRITE_TIMEOUT` - Write timeout in seconds (default: 30)
102
+ - **WebSocket order tracker configuration** via environment variables:
103
+ - `DHAN_WS_MAX_TRACKED_ORDERS` - Maximum orders to track (default: 10,000)
104
+ - `DHAN_WS_MAX_ORDER_AGE` - Maximum order age in seconds (default: 604,800 = 7 days)
105
+
106
+ #### Test Coverage
107
+ - `spec/dhan_hq/contracts/place_order_contract_spec.rb` - Comprehensive price validation tests
108
+ - `spec/dhan_hq/helpers/response_helper_spec.rb` - JSON parsing and error handling tests
109
+ - `spec/dhan_hq/ws/orders/client_spec.rb` - Order tracker cleanup and thread safety tests
110
+ - Updated existing specs to cover new functionality and improvements
111
+
112
+ ### 🔄 Changed
113
+
114
+ - **Error handling**: Improved error messages and logging throughout the codebase
115
+ - **Thread safety**: Enhanced thread safety in rate limiter and WebSocket clients
116
+ - **Memory management**: Order tracker now automatically cleans up old orders
117
+ - **JSON parsing**: Invalid JSON now raises `DataError` with logging (empty strings still return empty hash for backward compatibility)
118
+
119
+ ### 🗑️ Removed
120
+
121
+ - `lib/DhanHQ/contracts/modify_order_contract_copy.rb` - Removed unused duplicate file
122
+
123
+ ### 📝 Notes
124
+
125
+ - **Backward Compatibility**: All changes maintain 100% backward compatibility. No breaking changes.
126
+ - **API Compliance**: All fixes align with official API documentation at https://api.dhan.co/v2/#/
127
+ - **Performance**: Memory leak fixes and cleanup mechanisms improve long-running application stability
128
+ - **Reliability**: Retry logic and improved error handling increase resilience to transient failures
129
+
3
130
  ## [2.1.10] - 2025-11-11
4
131
 
5
132
  ### Fixed