DhanHQ 2.1.8 → 2.2.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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.rubocop_todo.yml +143 -118
  4. data/CHANGELOG.md +177 -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 +26 -0
  23. data/lib/DhanHQ/constants.rb +1 -1
  24. data/lib/DhanHQ/contracts/expired_options_data_contract.rb +6 -6
  25. data/lib/DhanHQ/contracts/place_order_contract.rb +51 -0
  26. data/lib/DhanHQ/core/base_model.rb +26 -11
  27. data/lib/DhanHQ/errors.rb +4 -0
  28. data/lib/DhanHQ/helpers/request_helper.rb +17 -2
  29. data/lib/DhanHQ/helpers/response_helper.rb +34 -13
  30. data/lib/DhanHQ/models/edis.rb +150 -14
  31. data/lib/DhanHQ/models/expired_options_data.rb +307 -88
  32. data/lib/DhanHQ/models/forever_order.rb +261 -22
  33. data/lib/DhanHQ/models/funds.rb +76 -10
  34. data/lib/DhanHQ/models/historical_data.rb +148 -31
  35. data/lib/DhanHQ/models/holding.rb +82 -6
  36. data/lib/DhanHQ/models/instrument_helpers.rb +4 -4
  37. data/lib/DhanHQ/models/kill_switch.rb +113 -11
  38. data/lib/DhanHQ/models/ledger_entry.rb +101 -13
  39. data/lib/DhanHQ/models/margin.rb +133 -8
  40. data/lib/DhanHQ/models/market_feed.rb +181 -17
  41. data/lib/DhanHQ/models/option_chain.rb +184 -12
  42. data/lib/DhanHQ/models/order.rb +418 -36
  43. data/lib/DhanHQ/models/order_update.rb +0 -4
  44. data/lib/DhanHQ/models/position.rb +161 -10
  45. data/lib/DhanHQ/models/profile.rb +103 -7
  46. data/lib/DhanHQ/models/super_order.rb +275 -15
  47. data/lib/DhanHQ/models/trade.rb +279 -26
  48. data/lib/DhanHQ/rate_limiter.rb +40 -6
  49. data/lib/DhanHQ/resources/expired_options_data.rb +1 -1
  50. data/lib/DhanHQ/version.rb +1 -1
  51. data/lib/DhanHQ/ws/client.rb +11 -5
  52. data/lib/DhanHQ/ws/connection.rb +16 -2
  53. data/lib/DhanHQ/ws/market_depth/client.rb +2 -1
  54. data/lib/DhanHQ/ws/market_depth.rb +12 -12
  55. data/lib/DhanHQ/ws/orders/client.rb +78 -12
  56. data/lib/DhanHQ/ws/orders/connection.rb +2 -1
  57. data/lib/DhanHQ/ws/orders.rb +2 -1
  58. metadata +18 -5
  59. data/lib/DhanHQ/contracts/modify_order_contract_copy.rb +0 -100
@@ -2,54 +2,190 @@
2
2
 
3
3
  module DhanHQ
4
4
  module Models
5
- # Model wrapper for electronic DIS flows.
5
+ ##
6
+ # Model wrapper for electronic DIS (Delivery Instruction Slip) flows.
7
+ #
8
+ # To sell holding stocks, one needs to complete the CDSL eDIS flow:
9
+ # 1. Generate T-PIN using {tpin}
10
+ # 2. Retrieve escaped HTML form using {form} and enter T-PIN to mark stock for EDIS approval
11
+ # 3. Check status using {inquire} to verify if stock is approved and marked for sell action
12
+ #
13
+ # You can get ISIN (International Securities Identification Number) of portfolio stocks
14
+ # from the holdings API response.
15
+ #
16
+ # @example Generate T-PIN
17
+ # response = DhanHQ::Models::Edis.tpin
18
+ # # Returns 202 Accepted status
19
+ #
20
+ # @example Generate eDIS form for a single stock
21
+ # response = DhanHQ::Models::Edis.form(
22
+ # isin: "INE733E01010",
23
+ # qty: 1,
24
+ # exchange: "NSE",
25
+ # segment: "EQ",
26
+ # bulk: false
27
+ # )
28
+ # # => {
29
+ # # dhan_client_id: "1000000401",
30
+ # # edis_form_html: "<!DOCTYPE html>..."
31
+ # # }
32
+ #
33
+ # @example Check EDIS status for an ISIN
34
+ # status = DhanHQ::Models::Edis.inquire("INE00IN01015")
35
+ # # => {
36
+ # # client_id: "1000000401",
37
+ # # isin: "INE00IN01015",
38
+ # # total_qty: "10",
39
+ # # aprvd_qty: "4",
40
+ # # status: "SUCCESS",
41
+ # # remarks: "eDIS transaction done successfully"
42
+ # # }
43
+ #
6
44
  class Edis < BaseModel
7
45
  # Base path backing the model operations.
8
46
  HTTP_PATH = "/v2/edis"
9
47
 
10
48
  class << self
49
+ ##
11
50
  # Shared resource client used by the model helpers.
12
51
  #
13
- # @return [DhanHQ::Resources::Edis]
52
+ # @return [DhanHQ::Resources::Edis] The EDIS resource client instance
14
53
  def resource
15
54
  @resource ||= DhanHQ::Resources::Edis.new
16
55
  end
17
56
 
18
- # Submits an EDIS form request.
57
+ ##
58
+ # Retrieves escaped HTML form of CDSL and enters T-PIN to mark the stock for EDIS approval.
19
59
  #
20
- # @param params [Hash]
21
- # @return [Hash]
60
+ # User has to render this form at their end to unescape. The form contains hidden fields
61
+ # that will automatically submit to CDSL's eDIS verification endpoint.
62
+ #
63
+ # @param params [Hash{Symbol => String, Integer, Boolean}] The EDIS form request parameters
64
+ # @option params [String] :isin (required) International Securities Identification Number
65
+ # (12-digit alphanumeric code). You can get ISIN from the holdings API response.
66
+ # @option params [Integer] :qty (required) Number of shares to mark for EDIS transaction
67
+ # @option params [String] :exchange (required) Exchange identifier. Must be either "NSE" or "BSE"
68
+ # @option params [String] :segment (required) Segment identifier. Must be "EQ"
69
+ # @option params [Boolean] :bulk (optional, default: false) Set to true to mark EDIS for
70
+ # all stocks in portfolio. When true, other parameters may be ignored.
71
+ #
72
+ # @return [Hash{Symbol => String}] The EDIS form response containing escaped HTML form.
73
+ # Response keys are normalized to snake_case:
74
+ # - **:dhan_client_id** [String] User-specific identification generated by Dhan
75
+ # - **:edis_form_html** [String] Escaped HTML form that needs to be rendered and unescaped
76
+ #
77
+ # @example Generate form for a single stock
78
+ # response = DhanHQ::Models::Edis.form(
79
+ # isin: "INE733E01010",
80
+ # qty: 1,
81
+ # exchange: "NSE",
82
+ # segment: "EQ",
83
+ # bulk: false
84
+ # )
85
+ # html_form = response[:edis_form_html]
86
+ # # Render and unescape the HTML form to complete EDIS approval
87
+ #
88
+ # @example Generate form for bulk EDIS
89
+ # response = DhanHQ::Models::Edis.form(
90
+ # isin: "",
91
+ # qty: 0,
92
+ # exchange: "NSE",
93
+ # segment: "EQ",
94
+ # bulk: true
95
+ # )
22
96
  def form(params)
23
97
  resource.form(params)
24
98
  end
25
99
 
26
- # Submits a bulk EDIS form request.
100
+ ##
101
+ # Submits a bulk EDIS form request for multiple stocks.
27
102
  #
28
- # @param params [Hash]
29
- # @return [Hash]
103
+ # This is an alternative to using {form} with `bulk: true`. The exact parameter
104
+ # structure may differ from the single form request.
105
+ #
106
+ # @param params [Hash{Symbol => String, Integer, Boolean}] The bulk EDIS form request parameters
107
+ # @option params [String] :isin (optional) International Securities Identification Number.
108
+ # May be ignored for bulk requests
109
+ # @option params [Integer] :qty (optional) Number of shares. May be ignored for bulk requests
110
+ # @option params [String] :exchange (required) Exchange identifier ("NSE" or "BSE")
111
+ # @option params [String] :segment (required) Segment identifier ("EQ")
112
+ # @option params [Boolean] :bulk (optional, default: true) Set to true for bulk operations
113
+ #
114
+ # @return [Hash{Symbol => String}] The bulk EDIS form response containing escaped HTML form.
115
+ # Response keys are normalized to snake_case:
116
+ # - **:dhan_client_id** [String] User-specific identification generated by Dhan
117
+ # - **:edis_form_html** [String] Escaped HTML form that needs to be rendered and unescaped
118
+ #
119
+ # @example Bulk EDIS form request
120
+ # response = DhanHQ::Models::Edis.bulk_form(
121
+ # exchange: "NSE",
122
+ # segment: "EQ",
123
+ # bulk: true
124
+ # )
30
125
  def bulk_form(params)
31
126
  resource.bulk_form(params)
32
127
  end
33
128
 
34
- # Requests a TPIN for the configured client.
129
+ ##
130
+ # Generates a T-PIN (Transaction PIN) for the configured client.
131
+ #
132
+ # T-PIN is sent to the user's registered mobile number. This T-PIN is required
133
+ # when submitting the EDIS form to mark stocks for sell action.
35
134
  #
36
- # @return [Hash]
135
+ # @return [Hash{Symbol => String}] The T-PIN generation response. The T-PIN itself is sent
136
+ # to the registered mobile number and not returned in the response. Response typically
137
+ # contains a status indicating successful generation (e.g., "202 Accepted").
138
+ #
139
+ # @example Generate T-PIN
140
+ # response = DhanHQ::Models::Edis.tpin
141
+ # # T-PIN will be sent to registered mobile number
142
+ # # Check your mobile for the T-PIN before submitting the EDIS form
143
+ #
144
+ # @note This is a GET request with no body parameters required
37
145
  def tpin
38
146
  resource.tpin
39
147
  end
40
148
 
41
- # Inquires EDIS status for a specific ISIN.
149
+ ##
150
+ # Inquires the EDIS status for a specific ISIN to check if stock is approved and marked for sell action.
151
+ #
152
+ # You can check whether a stock has been approved through the EDIS process and is ready
153
+ # for sell action. Alternatively, you can pass "ALL" instead of an ISIN to get EDIS status
154
+ # of all holdings in your portfolio.
155
+ #
156
+ # @param isin [String] International Securities Identification Number (12-digit alphanumeric code).
157
+ # You can get ISIN from the holdings API response. Alternatively, pass "ALL" to get status
158
+ # for all holdings in your portfolio.
159
+ #
160
+ # @return [Hash{Symbol => String}] The EDIS inquiry response containing status information.
161
+ # Response keys are normalized to snake_case:
162
+ # - **:client_id** [String] User-specific identification
163
+ # - **:isin** [String] International Securities Identification Number that was queried
164
+ # - **:total_qty** [String] Total number of shares for the given stock
165
+ # - **:aprvd_qty** [String] Number of approved stocks that are marked for EDIS
166
+ # - **:status** [String] Status of the EDIS order (e.g., "SUCCESS", "PENDING", "FAILED")
167
+ # - **:remarks** [String] Remarks about the order status (e.g., "eDIS transaction done successfully")
168
+ #
169
+ # @example Check status for a specific ISIN
170
+ # status = DhanHQ::Models::Edis.inquire("INE00IN01015")
171
+ # puts status[:status] # => "SUCCESS"
172
+ # puts status[:aprvd_qty] # => "4"
173
+ # puts status[:total_qty] # => "10"
174
+ #
175
+ # @example Check status for all holdings
176
+ # all_status = DhanHQ::Models::Edis.inquire("ALL")
177
+ # # Returns status for all holdings in portfolio
42
178
  #
43
- # @param isin [String]
44
- # @return [Hash]
179
+ # @note This is a GET request with no body parameters. The ISIN is passed in the URL path.
45
180
  def inquire(isin)
46
181
  resource.inquire(isin)
47
182
  end
48
183
  end
49
184
 
185
+ ##
50
186
  # EDIS payloads are validated upstream so no contract is applied.
51
187
  #
52
- # @return [nil]
188
+ # @return [nil] No validation contract is needed for EDIS operations
53
189
  def validation_contract
54
190
  nil
55
191
  end