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
@@ -0,0 +1,397 @@
1
+ # DhanHQ Client Gem - Code Review Issues
2
+
3
+ **API Documentation Reference**: https://dhanhq.co/docs/v2/
4
+
5
+ **Review Date**: 2025-01-27
6
+
7
+ ---
8
+
9
+ ## 🔴 Critical Issues
10
+
11
+ ### 1. **Missing Input Validation in Client Initialization**
12
+ **Location**: `lib/DhanHQ/client.rb:40`
13
+ **Issue**: The client initializes configuration conditionally, which can lead to runtime errors:
14
+ ```ruby
15
+ DhanHQ.configure_with_env if ENV.fetch("CLIENT_ID", nil)
16
+ ```
17
+ **Problem**: If `CLIENT_ID` exists but `ACCESS_TOKEN` doesn't, configuration will be partially initialized, leading to authentication failures later.
18
+ **Recommendation**: Validate both required credentials before proceeding or fail fast with a clear error message.
19
+
20
+ ### 2. **Race Condition in Rate Limiter**
21
+ **Location**: `lib/DhanHQ/rate_limiter.rb:51-99`
22
+ **Issue**: The `throttle!` method uses a mutex, but the cleanup threads (lines 144-161) modify shared state (`@buckets`) without synchronization.
23
+ **Problem**: Cleanup threads can reset counters while `throttle!` is checking/updating them, leading to incorrect rate limiting.
24
+ **Recommendation**: Use thread-safe operations for all bucket modifications or synchronize cleanup operations.
25
+
26
+ ### 3. **Incomplete Error Handling in WebSocket Connection**
27
+ **Location**: `lib/DhanHQ/ws/connection.rb:142-145`
28
+ **Issue**: Exceptions are caught but the connection may continue in an invalid state:
29
+ ```ruby
30
+ rescue StandardError => e
31
+ DhanHQ.logger&.error("[DhanHQ::WS] crashed #{e.class} #{e.message}")
32
+ failed = true
33
+ ```
34
+ **Problem**: The error is logged but the connection state may be inconsistent. No cleanup or state reset is performed.
35
+ **Recommendation**: Ensure proper cleanup and state reset on exceptions, and consider exposing error events to callers.
36
+
37
+ ### 4. **Missing Validation for Price Fields**
38
+ **Location**: `lib/DhanHQ/contracts/place_order_contract.rb:85-86`
39
+ **Issue**: Price validation allows `gt?: 0` but doesn't validate against reasonable upper bounds or check for NaN/Infinity.
40
+ **Problem**: Invalid float values (NaN, Infinity) or extremely large values could be sent to the API.
41
+ **Recommendation**: Add validation for finite numbers and reasonable bounds.
42
+
43
+ ---
44
+
45
+ ## 🟠 High Priority Issues
46
+
47
+ ### 5. **Inconsistent Error Object Handling**
48
+ **Location**: `lib/DhanHQ/core/base_model.rb:162`
49
+ **Issue**: The `update` method returns `ErrorObject` but other methods return `nil` or `false` on failure:
50
+ ```ruby
51
+ return DhanHQ::ErrorObject.new(response) unless success_response?(response)
52
+ ```
53
+ **Problem**: Inconsistent return types make error handling difficult for consumers.
54
+ **Recommendation**: Standardize error handling across all model methods (return `ErrorObject` consistently or raise exceptions).
55
+
56
+ ### 6. **Memory Leak in Order Tracker**
57
+ **Location**: `lib/DhanHQ/ws/orders/client.rb:18`
58
+ **Issue**: `@order_tracker` is a `Concurrent::Map` that grows indefinitely:
59
+ ```ruby
60
+ @order_tracker = Concurrent::Map.new
61
+ ```
62
+ **Problem**: Orders are never removed from the tracker, leading to unbounded memory growth over time.
63
+ **Recommendation**: Implement a cleanup mechanism (e.g., remove orders older than N days or limit the map size).
64
+
65
+ ### 7. **Missing Validation for Correlation ID Uniqueness**
66
+ **Location**: `lib/DhanHQ/models/order.rb:288-298`
67
+ **Issue**: The `place` method doesn't validate that `correlation_id` is unique before placing an order.
68
+ **Problem**: Duplicate correlation IDs could lead to confusion or idempotency issues.
69
+ **Recommendation**: Add validation or check for existing orders with the same correlation_id (if supported by API).
70
+
71
+ ### 8. **Thread Safety Issue in WebSocket Client**
72
+ **Location**: `lib/DhanHQ/ws/client.rb:166-172`
73
+ **Issue**: The `emit` method duplicates callbacks but doesn't protect against modification during iteration:
74
+ ```ruby
75
+ def emit(event, payload)
76
+ begin
77
+ @callbacks[event].dup
78
+ rescue StandardError
79
+ []
80
+ end.each { |cb| cb.call(payload) }
81
+ end
82
+ ```
83
+ **Problem**: While `.dup` is called, if callbacks are modified concurrently, the iteration could still be affected.
84
+ **Recommendation**: Use a more robust synchronization mechanism or immutable callback lists.
85
+
86
+ ### 9. **Incomplete Response Parsing**
87
+ **Location**: `lib/DhanHQ/helpers/response_helper.rb:77-96`
88
+ **Issue**: `parse_json` silently returns empty hash on JSON parse errors:
89
+ ```ruby
90
+ rescue JSON::ParserError
91
+ {} # Return an empty hash if the string is not valid JSON
92
+ ```
93
+ **Problem**: Silent failures make debugging difficult. An empty hash might be treated as success.
94
+ **Recommendation**: Log the error and consider raising an exception or returning an ErrorObject.
95
+
96
+ ### 10. **Missing Timeout Configuration**
97
+ **Location**: `lib/DhanHQ/client.rb:46-51`
98
+ **Issue**: Faraday connection doesn't set timeouts:
99
+ ```ruby
100
+ @connection = Faraday.new(url: DhanHQ.configuration.base_url) do |conn|
101
+ conn.request :json, parser_options: { symbolize_names: true }
102
+ conn.response :json, content_type: /\bjson$/
103
+ conn.response :logger if ENV["DHAN_DEBUG"] == "true"
104
+ conn.adapter Faraday.default_adapter
105
+ end
106
+ ```
107
+ **Problem**: Requests can hang indefinitely if the server doesn't respond.
108
+ **Recommendation**: Add timeout configuration (connect, read, write timeouts).
109
+
110
+ ---
111
+
112
+ ## 🟡 Medium Priority Issues
113
+
114
+ ### 11. **Inconsistent Key Normalization**
115
+ **Location**: Multiple files
116
+ **Issue**: Some methods use `snake_case`, others use `camelize_keys`, and some use `titleize_keys`:
117
+ - `lib/DhanHQ/core/base_api.rb:93` - Uses `titleize_keys` for optionchain
118
+ - `lib/DhanHQ/models/order.rb:235` - Uses `camelize_keys` for most APIs
119
+ **Problem**: Inconsistent key transformation can lead to API errors.
120
+ **Recommendation**: Document and standardize key transformation rules per API endpoint.
121
+
122
+ ### 12. **Missing Retry Logic for Transient Errors**
123
+ **Location**: `lib/DhanHQ/client.rb:61-71`
124
+ **Issue**: No automatic retry for transient network errors (5xx, timeouts).
125
+ **Problem**: Temporary failures require manual retry logic in application code.
126
+ **Recommendation**: Add configurable retry logic with exponential backoff for transient errors.
127
+
128
+ ### 13. **WebSocket Reconnection Backoff Not Reset Properly**
129
+ **Location**: `lib/DhanHQ/ws/connection.rb:154-162`
130
+ **Issue**: Backoff is reset only after a "clean session end", but the definition of "clean" is unclear:
131
+ ```ruby
132
+ else
133
+ backoff = 2.0 # reset only after a clean session end
134
+ end
135
+ ```
136
+ **Problem**: Backoff may not reset correctly, leading to excessive delays.
137
+ **Recommendation**: Clarify reset conditions and add logging for backoff behavior.
138
+
139
+ ### 14. **Missing Validation for Order Modification**
140
+ **Location**: `lib/DhanHQ/models/order.rb:366-390`
141
+ **Issue**: The `modify` method doesn't validate that the order is in a modifiable state (e.g., not already TRADED or CANCELLED).
142
+ **Problem**: API calls will fail, but validation could happen earlier.
143
+ **Recommendation**: Add state validation before attempting modification.
144
+
145
+ ### 15. **Incomplete Error Mapping**
146
+ **Location**: `lib/DhanHQ/helpers/response_helper.rb:50`
147
+ **Issue**: Error mapping relies on `DHAN_ERROR_MAPPING` but doesn't handle all possible error codes:
148
+ ```ruby
149
+ error_class = DhanHQ::Constants::DHAN_ERROR_MAPPING[error_code]
150
+ ```
151
+ **Problem**: Unknown error codes fall back to generic error handling, losing specificity.
152
+ **Recommendation**: Ensure all documented error codes are mapped, or log unmapped codes for investigation.
153
+
154
+ ### 16. **Missing Input Sanitization**
155
+ **Location**: `lib/DhanHQ/helpers/request_helper.rb:58-71`
156
+ **Issue**: Payload is converted to JSON without sanitization:
157
+ ```ruby
158
+ else req.body = payload.to_json
159
+ ```
160
+ **Problem**: Malicious or malformed data could be sent to the API.
161
+ **Recommendation**: Add input sanitization and validation before JSON serialization.
162
+
163
+ ### 17. **WebSocket Subscription State Not Persisted**
164
+ **Location**: `lib/DhanHQ/ws/sub_state.rb` (referenced but not reviewed)
165
+ **Issue**: Subscription state is in-memory only. On reconnection, subscriptions are restored from `@state.snapshot`, but if the process crashes, subscriptions are lost.
166
+ **Problem**: Requires manual re-subscription after crashes.
167
+ **Recommendation**: Consider persisting subscription state (optional, configurable).
168
+
169
+ ### 18. **Rate Limiter Cleanup Threads Never Stop**
170
+ **Location**: `lib/DhanHQ/rate_limiter.rb:144-161`
171
+ **Issue**: Cleanup threads run in infinite loops with no way to stop them:
172
+ ```ruby
173
+ Thread.new do
174
+ loop do
175
+ sleep(60)
176
+ @buckets[:per_minute]&.value = 0
177
+ end
178
+ end
179
+ ```
180
+ **Problem**: Threads continue running even after the rate limiter is no longer needed, wasting resources.
181
+ **Recommendation**: Add a shutdown mechanism or use a proper thread pool.
182
+
183
+ ### 19. **Missing Logging for Sensitive Operations**
184
+ **Location**: `lib/DhanHQ/models/order.rb:493`
185
+ **Issue**: Order placement failures are not logged:
186
+ ```ruby
187
+ else
188
+ # maybe store errors?
189
+ false
190
+ end
191
+ ```
192
+ **Problem**: Debugging order placement issues is difficult without logs.
193
+ **Recommendation**: Add structured logging for order operations (sanitize sensitive data).
194
+
195
+ ### 20. **Inconsistent API Type Handling**
196
+ **Location**: `lib/DhanHQ/core/base_api.rb:21`
197
+ **Issue**: API type defaults to `:non_trading_api` but some resources override it:
198
+ ```ruby
199
+ def initialize(api_type: self.class::API_TYPE)
200
+ ```
201
+ **Problem**: Inconsistent defaults can lead to incorrect rate limiting.
202
+ **Recommendation**: Ensure all resources explicitly set their API type or document the default.
203
+
204
+ ---
205
+
206
+ ## 🔵 Low Priority / Code Quality Issues
207
+
208
+ ### 21. **Duplicate Code in Error Handling**
209
+ **Location**: `lib/DhanHQ/core/base_model.rb:198-213`
210
+ **Issue**: `delete` and `destroy` methods have duplicate logic:
211
+ ```ruby
212
+ def delete
213
+ response = self.class.resource.delete("/#{id}")
214
+ success_response?(response)
215
+ rescue StandardError
216
+ false
217
+ end
218
+
219
+ def destroy
220
+ response = self.class.resource.delete("/#{id}")
221
+ success_response?(response)
222
+ rescue StandardError
223
+ false
224
+ end
225
+ ```
226
+ **Recommendation**: Extract common logic or make one delegate to the other.
227
+
228
+ ### 22. **Magic Numbers in Rate Limiter**
229
+ **Location**: `lib/DhanHQ/rate_limiter.rb:9-16`
230
+ **Issue**: Rate limits are hardcoded:
231
+ ```ruby
232
+ order_api: { per_second: 25, per_minute: 250, per_hour: 1000, per_day: 7000 },
233
+ ```
234
+ **Recommendation**: Make rate limits configurable via environment variables or configuration.
235
+
236
+ ### 23. **Missing Documentation for WebSocket Modes**
237
+ **Location**: `lib/DhanHQ/ws/client.rb:21-24`
238
+ **Issue**: Modes (`:ticker`, `:quote`, `:full`) are not well documented in the code:
239
+ ```ruby
240
+ @mode = mode # :ticker, :quote, :full (adjust to your API)
241
+ ```
242
+ **Recommendation**: Add comprehensive documentation explaining the differences and when to use each mode.
243
+
244
+ ### 24. **Inconsistent Method Naming**
245
+ **Location**: Various files
246
+ **Issue**: Some methods use `snake_case` (Ruby convention) while others use descriptive names inconsistently.
247
+ **Recommendation**: Establish and document naming conventions.
248
+
249
+ ### 25. **Missing Type Checking**
250
+ **Location**: `lib/DhanHQ/core/base_model.rb:241-243`
251
+ **Issue**: The `id` method tries multiple keys without type validation:
252
+ ```ruby
253
+ def id
254
+ @attributes[:id] || @attributes[:order_id] || @attributes[:security_id]
255
+ end
256
+ ```
257
+ **Problem**: Could return unexpected types if attributes contain non-string values.
258
+ **Recommendation**: Add type validation or conversion.
259
+
260
+ ### 26. **Unused Code**
261
+ **Location**: `lib/DhanHQ/contracts/modify_order_contract_copy.rb`
262
+ **Issue**: File appears to be a copy/backup that shouldn't be in the codebase.
263
+ **Recommendation**: Remove if unused, or rename/consolidate if needed.
264
+
265
+ ### 27. **Missing Validation for Array Responses**
266
+ **Location**: `lib/DhanHQ/core/base_model.rb:144-150`
267
+ **Issue**: `parse_collection_response` assumes arrays or `[:data]` structure:
268
+ ```ruby
269
+ return [] unless response.is_a?(Array) || (response.is_a?(Hash) && response[:data].is_a?(Array))
270
+ ```
271
+ **Problem**: Other response formats are silently ignored.
272
+ **Recommendation**: Add logging for unexpected response formats.
273
+
274
+ ### 28. **WebSocket URL Construction**
275
+ **Location**: `lib/DhanHQ/ws/client.rb:33`
276
+ **Issue**: URL is constructed with string interpolation:
277
+ ```ruby
278
+ @url = url || "wss://api-feed.dhan.co?version=#{ver}&token=#{token}&clientId=#{cid}&authType=2"
279
+ ```
280
+ **Problem**: Token and client ID are embedded in URL (visible in logs, connection strings).
281
+ **Recommendation**: Use proper URL encoding and consider sanitizing in logs.
282
+
283
+ ### 29. **Missing Validation for Order Status Transitions**
284
+ **Location**: `lib/DhanHQ/models/order.rb`
285
+ **Issue**: No validation that order status transitions are valid (e.g., can't go from CANCELLED to PENDING).
286
+ **Recommendation**: Add state machine validation if order lifecycle is important.
287
+
288
+ ### 30. **Incomplete Test Coverage**
289
+ **Location**: `spec/` directory
290
+ **Issue**: Based on file structure, some critical paths may lack test coverage (e.g., error handling, WebSocket reconnection).
291
+ **Recommendation**: Review and improve test coverage, especially for error paths and edge cases.
292
+
293
+ ---
294
+
295
+ ## 🔴 API Compliance Issues
296
+
297
+ ### 31. **Missing Alert Orders API Implementation**
298
+ **Location**: Not implemented
299
+ **Issue**: The API documentation shows Alert Orders endpoints (`/alerts/orders`) but the gem doesn't implement them:
300
+ - `POST /alerts/orders` - Place alert order
301
+ - `GET /alerts/orders` - Get all alert orders
302
+ - `GET /alerts/orders/{trigger-id}` - Get alert order by ID
303
+ - `PUT /alerts/orders/{trigger-id}` - Modify alert order
304
+ - `DELETE /alerts/orders/{trigger-id}` - Delete alert order
305
+ **Problem**: Users cannot use Conditional Triggers (Alerts) feature via the gem.
306
+ **Recommendation**: Implement `DhanHQ::Resources::AlertOrders` and `DhanHQ::Models::AlertOrder` classes.
307
+
308
+ ### 32. **Missing IP Setup API Implementation**
309
+ **Location**: Not implemented
310
+ **Issue**: The API documentation shows IP Setup endpoints (`/ip/*`) but the gem doesn't implement them:
311
+ - `POST /ip/setIP` - Set static IP
312
+ - `PUT /ip/modifyIP` - Modify static IP
313
+ - `GET /ip/getIP` - Get current static IP
314
+ **Problem**: Users cannot configure static IP whitelisting via the gem (required for order placement).
315
+ **Recommendation**: Implement `DhanHQ::Resources::IPSetup` resource class.
316
+
317
+ ### 33. **Path Parameter Naming Inconsistency**
318
+ **Location**: `lib/DhanHQ/resources/trades.rb:18`
319
+ **Issue**: API uses `{order-id}` (with hyphen) in path, but gem constructs paths with `/#{order_id}`:
320
+ ```ruby
321
+ def find(order_id)
322
+ get("/#{order_id}")
323
+ end
324
+ ```
325
+ **Problem**: While this works, it's inconsistent with API documentation format. More importantly, the trade history endpoint uses path parameters: `/trades/{from-date}/{to-date}/{page-number}` but the gem uses query parameters.
326
+ **Recommendation**: Verify path construction matches API spec exactly. For trade history, use path parameters as documented.
327
+
328
+ ### 34. **Trade History Endpoint Mismatch**
329
+ **Location**: `lib/DhanHQ/resources/statements.rb` (referenced)
330
+ **Issue**: API documentation shows trade history as: `GET /trades/{from-date}/{to-date}/{page-number}` (path parameters), but implementation might use query parameters.
331
+ **Problem**: Incorrect endpoint format could cause API errors.
332
+ **Recommendation**: Verify and fix trade history endpoint to use path parameters as per API spec.
333
+
334
+ ### 35. **Missing Validation for Required Headers**
335
+ **Location**: `lib/DhanHQ/helpers/request_helper.rb:28-42`
336
+ **Issue**: The `build_headers` method adds headers but doesn't validate that required headers are present before making requests:
337
+ ```ruby
338
+ headers = {
339
+ "Content-Type" => "application/json",
340
+ "Accept" => "application/json",
341
+ "access-token" => DhanHQ.configuration.access_token
342
+ }
343
+ ```
344
+ **Problem**: If `access_token` is nil, requests will fail at runtime rather than failing fast with a clear error.
345
+ **Recommendation**: Validate required headers before building request, raise clear error if missing.
346
+
347
+ ### 36. **Incorrect Response Status Code Handling**
348
+ **Location**: `lib/DhanHQ/resources/positions.rb` (position conversion)
349
+ **Issue**: API documentation shows position conversion returns `202 Accepted`, but the gem might expect `200 OK`.
350
+ **Problem**: Success detection might fail for async operations.
351
+ **Recommendation**: Handle `202 Accepted` status codes appropriately for async operations.
352
+
353
+ ### 37. **Missing Pagination Support**
354
+ **Location**: Various `all` methods
355
+ **Issue**: Some endpoints support pagination (e.g., trade history has `page-number`), but the gem doesn't expose pagination helpers consistently.
356
+ **Problem**: Users cannot easily paginate through large result sets.
357
+ **Recommendation**: Add pagination support with `page` and `per_page` parameters where API supports it.
358
+
359
+ ### 38. **Date Format Validation Missing**
360
+ **Location**: `lib/DhanHQ/models/trade.rb:211-244`
361
+ **Issue**: Trade history validates date format, but other date parameters (e.g., in historical data, option chain expiry) might not validate format strictly.
362
+ **Problem**: Invalid date formats could cause API errors.
363
+ **Recommendation**: Add consistent date format validation (`YYYY-MM-DD`) across all date parameters.
364
+
365
+ ---
366
+
367
+ ## 📋 Summary
368
+
369
+ ### Critical Issues: 4
370
+ ### High Priority Issues: 6
371
+ ### Medium Priority Issues: 10
372
+ ### Low Priority Issues: 10
373
+ ### API Compliance Issues: 8
374
+
375
+ ### Key Areas Requiring Attention:
376
+ 1. **Thread Safety**: Rate limiter and WebSocket clients need better synchronization
377
+ 2. **Error Handling**: Inconsistent error handling patterns across the codebase
378
+ 3. **Memory Management**: Order tracker and cleanup threads need lifecycle management
379
+ 4. **Input Validation**: Missing validation for edge cases (NaN, Infinity, bounds)
380
+ 5. **Configuration**: Missing timeout configuration and better credential validation
381
+ 6. **Documentation**: Some areas lack clear documentation
382
+ 7. **API Compliance**: Missing implementations for Alert Orders and IP Setup APIs
383
+ 8. **Endpoint Consistency**: Path parameter construction and response handling need verification
384
+
385
+ ### Recommended Next Steps:
386
+ 1. Fix critical issues first (especially thread safety and error handling)
387
+ 2. Implement missing API endpoints (Alert Orders, IP Setup)
388
+ 3. Verify all endpoint paths match API documentation exactly
389
+ 4. Add comprehensive integration tests against live API
390
+ 5. Implement proper logging and monitoring
391
+ 6. Add configuration validation on startup
392
+ 7. Document API compliance with official DhanHQ API documentation
393
+ 8. Add pagination support where API provides it
394
+
395
+ ---
396
+
397
+ **Note**: This review is based on static code analysis and API documentation comparison. Dynamic testing and API compliance verification against https://api.dhan.co/v2/#/ should be performed to validate these findings.