DhanHQ 2.2.2 → 2.4.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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/CODE_REVIEW_ISSUES.md +2 -2
  4. data/GUIDE.md +63 -21
  5. data/README.md +16 -5
  6. data/README1.md +4 -4
  7. data/REVIEW_SUMMARY.md +2 -2
  8. data/docs/API_VERIFICATION.md +67 -0
  9. data/docs/AUTHENTICATION.md +54 -2
  10. data/docs/TESTING_GUIDE.md +40 -42
  11. data/docs/live_order_updates.md +2 -2
  12. data/docs/rails_integration.md +7 -7
  13. data/docs/standalone_ruby_websocket_integration.md +24 -24
  14. data/docs/technical_analysis.md +1 -1
  15. data/docs/websocket_integration.md +4 -4
  16. data/examples/comprehensive_websocket_examples.rb +2 -2
  17. data/examples/instrument_finder_test.rb +2 -2
  18. data/examples/market_depth_example.rb +2 -2
  19. data/examples/market_feed_example.rb +2 -2
  20. data/examples/order_update_example.rb +2 -2
  21. data/examples/trading_fields_example.rb +2 -2
  22. data/lib/DhanHQ/auth/token_generator.rb +33 -0
  23. data/lib/DhanHQ/auth/token_manager.rb +88 -0
  24. data/lib/DhanHQ/auth/token_renewal.rb +25 -0
  25. data/lib/DhanHQ/auth.rb +91 -31
  26. data/lib/DhanHQ/client.rb +42 -2
  27. data/lib/DhanHQ/configuration.rb +2 -2
  28. data/lib/DhanHQ/contracts/alert_order_contract.rb +20 -0
  29. data/lib/DhanHQ/contracts/order_contract.rb +0 -23
  30. data/lib/DhanHQ/contracts/trade_by_order_id_contract.rb +12 -0
  31. data/lib/DhanHQ/contracts/trade_contract.rb +0 -65
  32. data/lib/DhanHQ/contracts/trade_history_contract.rb +52 -0
  33. data/lib/DhanHQ/core/auth_api.rb +21 -0
  34. data/lib/DhanHQ/core/base_resource.rb +5 -5
  35. data/lib/DhanHQ/helpers/request_helper.rb +1 -1
  36. data/lib/DhanHQ/models/alert_order.rb +83 -0
  37. data/lib/DhanHQ/models/token_response.rb +88 -0
  38. data/lib/DhanHQ/resources/alert_orders.rb +11 -0
  39. data/lib/DhanHQ/resources/edis.rb +5 -20
  40. data/lib/DhanHQ/resources/ip_setup.rb +23 -0
  41. data/lib/DhanHQ/resources/trader_control.rb +23 -0
  42. data/lib/DhanHQ/version.rb +1 -1
  43. data/lib/dhan_hq.rb +31 -77
  44. metadata +43 -4
  45. data/lib/DhanHQ/config.rb +0 -33
  46. data/lib/DhanHQ/models/edis.rb +0 -194
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DhanHQ
4
+ module Contracts
5
+ # Validation contract for trade-by-order-id requests.
6
+ class TradeByOrderIdContract < BaseContract
7
+ params do
8
+ required(:order_id).filled(:string, min_size?: 1)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "date"
4
-
5
3
  module DhanHQ
6
4
  module Contracts
7
5
  ##
@@ -10,68 +8,5 @@ module DhanHQ
10
8
  # No input validation needed for GET requests
11
9
  # These contracts are mainly for documentation and future extensibility
12
10
  end
13
-
14
- ##
15
- # Validation contract for trade history requests
16
- class TradeHistoryContract < BaseContract
17
- params do
18
- required(:from_date).filled(:string)
19
- required(:to_date).filled(:string)
20
- optional(:page).filled(:integer, gteq?: 0)
21
- end
22
-
23
- rule(:from_date) do
24
- key.failure("must be in YYYY-MM-DD format (e.g., 2024-01-15)") unless valid_date_format?(value)
25
- key.failure("must be a valid trading date (no weekend dates)") if valid_date_format?(value) && !trading_day?(Date.parse(value))
26
- end
27
-
28
- rule(:to_date) do
29
- key.failure("must be in YYYY-MM-DD format (e.g., 2024-01-15)") unless valid_date_format?(value)
30
- end
31
-
32
- rule(:from_date, :to_date) do
33
- from_date_valid = valid_date_format?(values[:from_date])
34
- to_date_valid = valid_date_format?(values[:to_date])
35
-
36
- if values[:from_date] && values[:to_date] && from_date_valid && to_date_valid
37
- begin
38
- from_date = Date.parse(values[:from_date])
39
- to_date = Date.parse(values[:to_date])
40
-
41
- key.failure("from_date must be before to_date") if from_date >= to_date
42
- rescue Date::Error
43
- key.failure("invalid date format")
44
- end
45
- end
46
- end
47
-
48
- private
49
-
50
- def valid_date_format?(date_string)
51
- return false unless date_string.is_a?(String)
52
- return false unless date_string.match?(/\A\d{4}-\d{2}-\d{2}\z/)
53
-
54
- begin
55
- Date.parse(date_string)
56
- true
57
- rescue Date::Error
58
- false
59
- end
60
- end
61
-
62
- def trading_day?(date)
63
- return false unless date.is_a?(Date)
64
-
65
- (1..5).cover?(date.wday)
66
- end
67
- end
68
-
69
- ##
70
- # Validation contract for trade by order ID requests
71
- class TradeByOrderIdContract < BaseContract
72
- params do
73
- required(:order_id).filled(:string, min_size?: 1)
74
- end
75
- end
76
11
  end
77
12
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+
5
+ module DhanHQ
6
+ module Contracts
7
+ # Validation contract for trade history requests.
8
+ class TradeHistoryContract < BaseContract
9
+ params do
10
+ required(:from_date).filled(:string)
11
+ required(:to_date).filled(:string)
12
+ optional(:page).filled(:integer, gteq?: 0)
13
+ end
14
+
15
+ rule(:from_date) do
16
+ key.failure("must be in YYYY-MM-DD format (e.g., 2024-01-15)") unless valid_date_format?(value)
17
+ next unless valid_date_format?(value)
18
+
19
+ key.failure("must be a valid trading date (no weekend dates)") unless trading_day?(Date.parse(value))
20
+ end
21
+
22
+ rule(:to_date) do
23
+ key.failure("must be in YYYY-MM-DD format (e.g., 2024-01-15)") unless valid_date_format?(value)
24
+ end
25
+
26
+ rule(:from_date, :to_date) do
27
+ from = values[:from_date]
28
+ to = values[:to_date]
29
+ next unless valid_date_format?(from) && valid_date_format?(to)
30
+
31
+ key.failure("from_date must be before to_date") if Date.parse(from) >= Date.parse(to)
32
+ rescue Date::Error
33
+ key.failure("invalid date format")
34
+ end
35
+
36
+ private
37
+
38
+ def valid_date_format?(date_string)
39
+ return false unless date_string.is_a?(String) && date_string.match?(/\A\d{4}-\d{2}-\d{2}\z/)
40
+
41
+ Date.parse(date_string)
42
+ true
43
+ rescue Date::Error
44
+ false
45
+ end
46
+
47
+ def trading_day?(date)
48
+ date.is_a?(Date) && (1..5).cover?(date.wday)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+
5
+ module DhanHQ
6
+ # Faraday client for Dhan auth endpoints.
7
+ #
8
+ # This class intentionally lives at the top-level namespace so it autoloads
9
+ # cleanly from `lib/DhanHQ/core/auth_api.rb` with Zeitwerk `collapse`.
10
+ class AuthAPI
11
+ BASE_URL = "https://auth.dhan.co"
12
+
13
+ def connection
14
+ @connection ||= Faraday.new(url: BASE_URL) do |faraday|
15
+ faraday.request :url_encoded
16
+ faraday.response :json, content_type: /\bjson$/
17
+ faraday.adapter Faraday.default_adapter
18
+ end
19
+ end
20
+ end
21
+ end
@@ -11,7 +11,7 @@ module DhanHQ
11
11
  #
12
12
  # @return [Array<Hash>, Hash]
13
13
  def all
14
- get(self.class::HTTP_PATH)
14
+ get("")
15
15
  end
16
16
 
17
17
  # Retrieves a single resource by identifier.
@@ -19,7 +19,7 @@ module DhanHQ
19
19
  # @param id [String, Integer]
20
20
  # @return [Hash]
21
21
  def find(id)
22
- get("#{self.class::HTTP_PATH}/#{id}")
22
+ get("/#{id}")
23
23
  end
24
24
 
25
25
  # Creates a new resource instance.
@@ -27,7 +27,7 @@ module DhanHQ
27
27
  # @param params [Hash]
28
28
  # @return [Hash]
29
29
  def create(params)
30
- post(self.class::HTTP_PATH, params: params)
30
+ post("", params: params)
31
31
  end
32
32
 
33
33
  # Updates an existing resource.
@@ -36,7 +36,7 @@ module DhanHQ
36
36
  # @param params [Hash]
37
37
  # @return [Hash]
38
38
  def update(id, params)
39
- put("#{self.class::HTTP_PATH}/#{id}", params: params)
39
+ put("/#{id}", params: params)
40
40
  end
41
41
 
42
42
  # Deletes a resource by identifier.
@@ -44,7 +44,7 @@ module DhanHQ
44
44
  # @param id [String, Integer]
45
45
  # @return [Hash]
46
46
  def delete(id)
47
- super("#{self.class::HTTP_PATH}/#{id}")
47
+ super("/#{id}")
48
48
  end
49
49
  end
50
50
  end
@@ -44,7 +44,7 @@ module DhanHQ
44
44
  client_id = DhanHQ.configuration&.client_id
45
45
  unless client_id
46
46
  raise DhanHQ::InvalidAuthenticationError,
47
- "client_id is required for DATA APIs but not set. Please configure DhanHQ with CLIENT_ID."
47
+ "client_id is required for DATA APIs but not set. Please configure DhanHQ with DHAN_CLIENT_ID."
48
48
  end
49
49
  headers["client-id"] = client_id
50
50
  end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../contracts/alert_order_contract"
4
+
5
+ module DhanHQ
6
+ module Models
7
+ # Model for alert/conditional orders. CRUD via AlertOrders resource; validated by AlertOrderContract.
8
+ class AlertOrder < BaseModel
9
+ HTTP_PATH = "/alerts/orders"
10
+
11
+ attributes :alert_id, :exchange_segment, :security_id, :condition,
12
+ :trigger_price, :order_type, :transaction_type, :quantity,
13
+ :price, :status, :created_at
14
+
15
+ class << self
16
+ def api_type
17
+ :order_api
18
+ end
19
+
20
+ def resource
21
+ @resource ||= DhanHQ::Resources::AlertOrders.new
22
+ end
23
+
24
+ def validation_contract
25
+ Contracts::AlertOrderContract
26
+ end
27
+
28
+ def all
29
+ response = resource.all
30
+ return [] unless response.is_a?(Array)
31
+
32
+ response.map { |attrs| new(attrs, skip_validation: true) }
33
+ end
34
+
35
+ def find(alert_id)
36
+ response = resource.find(alert_id)
37
+ return nil unless response.is_a?(Hash) || (response.is_a?(Array) && response.any?)
38
+
39
+ payload = response.is_a?(Array) ? response.first : response
40
+ new(payload, skip_validation: true)
41
+ end
42
+
43
+ def create(params)
44
+ normalized = snake_case(params)
45
+ validate_params!(normalized, DhanHQ::Contracts::AlertOrderContract)
46
+ response = resource.create(camelize_keys(normalized))
47
+ return nil unless response.is_a?(Hash) && response["alertId"]
48
+
49
+ find(response["alertId"])
50
+ end
51
+ end
52
+
53
+ def id
54
+ alert_id&.to_s
55
+ end
56
+
57
+ def save # rubocop:disable Naming/PredicateMethod
58
+ return false unless valid?
59
+
60
+ payload = to_request_params
61
+ response = if new_record?
62
+ self.class.resource.create(camelize_keys(payload))
63
+ else
64
+ self.class.resource.update(id, camelize_keys(payload))
65
+ end
66
+ return false if new_record? && !(response.is_a?(Hash) && response["alertId"])
67
+ return false if !new_record? && !success_response?(response)
68
+
69
+ @attributes.merge!(normalize_keys(response))
70
+ assign_attributes
71
+ true
72
+ end
73
+
74
+ def destroy # rubocop:disable Naming/PredicateMethod
75
+ return false if new_record?
76
+
77
+ response = self.class.resource.delete(id)
78
+ success_response?(response)
79
+ end
80
+ alias delete destroy
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+
5
+ module DhanHQ
6
+ module Models
7
+ # Represents a Dhan API token response with expiry tracking and validation.
8
+ #
9
+ # TokenResponse wraps the response from Dhan's token generation and renewal
10
+ # endpoints, providing convenient methods for checking token validity and
11
+ # determining when refresh is needed.
12
+ #
13
+ # @example From token generation
14
+ # response = Auth.generate_access_token(
15
+ # dhan_client_id: "123",
16
+ # pin: "1234",
17
+ # totp: "654321"
18
+ # )
19
+ # token = TokenResponse.new(response)
20
+ # token.expired? # => false
21
+ # token.expires_in # => 86400 (seconds)
22
+ # token.needs_refresh? # => false
23
+ #
24
+ # @example Checking token status
25
+ # if token.needs_refresh?(buffer_seconds: 600)
26
+ # # Refresh token 10 minutes before expiry
27
+ # new_token = Auth.renew_token(...)
28
+ # end
29
+ #
30
+ # @attr_reader [String] client_id Dhan client ID
31
+ # @attr_reader [String] client_name Dhan client name
32
+ # @attr_reader [String] ucc Unique client code
33
+ # @attr_reader [Boolean] power_of_attorney POA status
34
+ # @attr_reader [String] access_token The authentication token
35
+ # @attr_reader [Time] expiry_time Token expiration timestamp
36
+ class TokenResponse
37
+ attr_reader :client_id,
38
+ :client_name,
39
+ :ucc,
40
+ :power_of_attorney,
41
+ :access_token,
42
+ :expiry_time
43
+
44
+ def initialize(data)
45
+ data = normalize_keys(data)
46
+
47
+ @client_id = data["dhanClientId"]
48
+ @client_name = data["dhanClientName"]
49
+ @ucc = data["dhanClientUcc"]
50
+ @power_of_attorney = data["givenPowerOfAttorney"]
51
+ @access_token = data["accessToken"]
52
+ @expiry_time = parse_time(data["expiryTime"])
53
+ end
54
+
55
+ def expired?
56
+ return true unless expiry_time
57
+
58
+ Time.now >= expiry_time
59
+ end
60
+
61
+ def expires_in
62
+ return 0 unless expiry_time
63
+
64
+ expiry_time - Time.now
65
+ end
66
+
67
+ def needs_refresh?(buffer_seconds: 300)
68
+ return true unless expiry_time
69
+
70
+ Time.now >= (expiry_time - buffer_seconds)
71
+ end
72
+
73
+ private
74
+
75
+ def normalize_keys(data)
76
+ return {} unless data.is_a?(Hash)
77
+
78
+ data.transform_keys(&:to_s)
79
+ end
80
+
81
+ def parse_time(value)
82
+ return nil if value.nil? || value.to_s.strip.empty?
83
+
84
+ Time.parse(value.to_s)
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DhanHQ
4
+ module Resources
5
+ # Resource for alert/conditional orders per API docs: /alerts/orders (GET/POST/PUT/DELETE).
6
+ class AlertOrders < BaseResource
7
+ API_TYPE = :order_api
8
+ HTTP_PATH = "/alerts/orders"
9
+ end
10
+ end
11
+ end
@@ -2,40 +2,25 @@
2
2
 
3
3
  module DhanHQ
4
4
  module Resources
5
- # Resource client for electronic DIS flows.
5
+ # Resource for EDIS per https://dhanhq.co/docs/v2/edis/
6
+ # GET /edis/tpin, POST /edis/form (body: isin, qty, exchange, segment, bulk),
7
+ # POST /edis/bulkform, GET /edis/inquire/{isin}.
6
8
  class Edis < BaseAPI
7
- # EDIS endpoints are served from the trading API.
8
- API_TYPE = :order_api
9
- # Base path for EDIS endpoints.
10
- HTTP_PATH = "/v2/edis"
9
+ API_TYPE = :order_api
10
+ HTTP_PATH = "/edis"
11
11
 
12
- # Creates a TPIN request form.
13
- #
14
- # @param params [Hash]
15
- # @return [Hash]
16
12
  def form(params)
17
13
  post("/form", params: params)
18
14
  end
19
15
 
20
- # Bulk EDIS form submission.
21
- #
22
- # @param params [Hash]
23
- # @return [Hash]
24
16
  def bulk_form(params)
25
17
  post("/bulkform", params: params)
26
18
  end
27
19
 
28
- # Generates a TPIN for the client.
29
- #
30
- # @return [Hash]
31
20
  def tpin
32
21
  get("/tpin")
33
22
  end
34
23
 
35
- # Checks the EDIS status for a given ISIN.
36
- #
37
- # @param isin [String]
38
- # @return [Hash]
39
24
  def inquire(isin)
40
25
  get("/inquire/#{isin}")
41
26
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DhanHQ
4
+ module Resources
5
+ # Resource for IP whitelist per API docs: GET /ip/getIP, POST /ip/setIP, PUT /ip/modifyIP.
6
+ class IPSetup < BaseAPI
7
+ API_TYPE = :order_api
8
+ HTTP_PATH = "/ip"
9
+
10
+ def current
11
+ get("/getIP")
12
+ end
13
+
14
+ def set(ip:)
15
+ post("/setIP", params: { ip: ip })
16
+ end
17
+
18
+ def update(ip:)
19
+ put("/modifyIP", params: { ip: ip })
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DhanHQ
4
+ module Resources
5
+ # Resource for trader control (kill switch): status (GET), enable/disable (POST /trader-control).
6
+ class TraderControl < BaseAPI
7
+ API_TYPE = :order_api
8
+ HTTP_PATH = "/trader-control"
9
+
10
+ def status
11
+ get("")
12
+ end
13
+
14
+ def enable
15
+ post("", params: { action: "ENABLE" })
16
+ end
17
+
18
+ def disable
19
+ post("", params: { action: "DISABLE" })
20
+ end
21
+ end
22
+ end
23
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module DhanHQ
4
4
  # Semantic version of the DhanHQ client gem.
5
- VERSION = "2.2.2"
5
+ VERSION = "2.4.0"
6
6
  end
data/lib/dhan_hq.rb CHANGED
@@ -1,92 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dotenv/load"
3
+ require "json"
4
4
  require "logger"
5
-
6
- # Helper Methods
5
+ require "zeitwerk"
6
+ require "dotenv/load"
7
+ # Minimal eager requires for backward-compatible constants.
8
+ # These are widely referenced (e.g. `DhanHQ::BaseAPI`) and should not depend on
9
+ # the autoloader being fully configured.
7
10
  require_relative "DhanHQ/helpers/api_helper"
8
11
  require_relative "DhanHQ/helpers/attribute_helper"
9
12
  require_relative "DhanHQ/helpers/validation_helper"
10
13
  require_relative "DhanHQ/helpers/request_helper"
11
14
  require_relative "DhanHQ/helpers/response_helper"
12
- require_relative "DhanHQ/json_loader"
13
-
14
15
  require_relative "DhanHQ/core/base_api"
15
- require_relative "DhanHQ/core/base_resource"
16
16
  require_relative "DhanHQ/core/base_model"
17
- require_relative "DhanHQ/core/error_handler"
18
-
19
- require_relative "DhanHQ/version"
20
- require_relative "DhanHQ/errors"
21
- require_relative "DhanHQ/error_object"
22
-
23
- require_relative "DhanHQ/client"
24
- require_relative "DhanHQ/configuration"
25
- require_relative "DhanHQ/rate_limiter"
26
- require_relative "DhanHQ/auth"
27
-
28
- # Contracts
29
- require_relative "DhanHQ/contracts/base_contract"
30
- require_relative "DhanHQ/contracts/historical_data_contract"
31
- require_relative "DhanHQ/contracts/margin_calculator_contract"
32
- require_relative "DhanHQ/contracts/position_conversion_contract"
33
- require_relative "DhanHQ/contracts/slice_order_contract"
34
- require_relative "DhanHQ/contracts/trade_contract"
35
- require_relative "DhanHQ/contracts/expired_options_data_contract"
36
-
37
- # Resources
38
- require_relative "DhanHQ/resources/option_chain"
39
- require_relative "DhanHQ/resources/orders"
40
- require_relative "DhanHQ/resources/forever_orders"
41
- require_relative "DhanHQ/resources/super_orders"
42
- require_relative "DhanHQ/resources/funds"
43
- require_relative "DhanHQ/resources/holdings"
44
- require_relative "DhanHQ/resources/positions"
45
- require_relative "DhanHQ/resources/statements"
46
- require_relative "DhanHQ/resources/trades"
47
- require_relative "DhanHQ/resources/historical_data"
48
- require_relative "DhanHQ/resources/margin_calculator"
49
- require_relative "DhanHQ/resources/market_feed"
50
- require_relative "DhanHQ/resources/instruments"
51
- require_relative "DhanHQ/resources/edis"
52
- require_relative "DhanHQ/resources/kill_switch"
53
- require_relative "DhanHQ/resources/profile"
54
- require_relative "DhanHQ/resources/expired_options_data"
55
-
56
- # Models
57
- require_relative "DhanHQ/models/order"
58
- require_relative "DhanHQ/models/funds"
59
- require_relative "DhanHQ/models/option_chain"
60
- require_relative "DhanHQ/models/forever_order"
61
- require_relative "DhanHQ/models/super_order"
62
- require_relative "DhanHQ/models/historical_data"
63
- require_relative "DhanHQ/models/market_feed"
64
- require_relative "DhanHQ/models/instrument"
65
- require_relative "DhanHQ/models/position"
66
- require_relative "DhanHQ/models/holding"
67
- require_relative "DhanHQ/models/ledger_entry"
68
- require_relative "DhanHQ/models/trade"
69
- require_relative "DhanHQ/models/margin"
70
- require_relative "DhanHQ/models/edis"
71
- require_relative "DhanHQ/models/kill_switch"
72
- require_relative "DhanHQ/models/profile"
73
- require_relative "DhanHQ/models/order_update"
74
- require_relative "DhanHQ/models/expired_options_data"
75
-
76
- require_relative "DhanHQ/constants"
77
- require_relative "DhanHQ/ws"
78
- require_relative "DhanHQ/ws/singleton_lock"
79
- require_relative "ta"
80
- require_relative "dhanhq/analysis/multi_timeframe_analyzer"
81
- require_relative "dhanhq/analysis/helpers/bias_aggregator"
82
- require_relative "dhanhq/analysis/helpers/moneyness_helper"
83
- require_relative "dhanhq/contracts/options_buying_advisor_contract"
84
- require_relative "dhanhq/analysis/options_buying_advisor"
17
+ require_relative "DhanHQ/core/base_resource"
85
18
 
86
19
  # The top-level module for the DhanHQ client library.
87
20
  #
88
21
  # Provides configuration management for setting credentials and API-related settings.
89
22
  module DhanHQ
23
+ LOADER = Zeitwerk::Loader.new
24
+ LOADER.tag = "dhanhq"
25
+ LOADER.inflector.inflect(
26
+ "api_helper" => "APIHelper",
27
+ "auth_api" => "AuthAPI",
28
+ "base_api" => "BaseAPI",
29
+ "ip_setup" => "IPSetup",
30
+ "json_loader" => "JSONLoader",
31
+ "ws" => "WS"
32
+ )
33
+ LOADER.push_dir(File.join(__dir__, "DhanHQ"), namespace: self)
34
+ LOADER.push_dir(File.join(__dir__, "dhanhq"), namespace: self)
35
+ LOADER.collapse(File.join(__dir__, "DhanHQ", "core"))
36
+ LOADER.collapse(File.join(__dir__, "DhanHQ", "helpers"))
37
+ LOADER.collapse(File.join(__dir__, "dhanhq", "analysis", "helpers"))
38
+ LOADER.ignore(
39
+ File.join(__dir__, "DhanHQ", "errors.rb"),
40
+ File.join(__dir__, "DhanHQ", "version.rb")
41
+ )
42
+ LOADER.setup
43
+
90
44
  class Error < StandardError; end
91
45
 
92
46
  class << self
@@ -127,7 +81,7 @@ module DhanHQ
127
81
 
128
82
  # Configures the DhanHQ client using environment variables.
129
83
  #
130
- # When credentials are injected via `ACCESS_TOKEN` and `CLIENT_ID` this helper
84
+ # When credentials are injected via `DHAN_ACCESS_TOKEN` and `DHAN_CLIENT_ID` this helper
131
85
  # can be used to initialise a configuration without a block.
132
86
  #
133
87
  # @example
@@ -136,8 +90,8 @@ module DhanHQ
136
90
  # @return [void]
137
91
  def configure_with_env
138
92
  self.configuration ||= Configuration.new
139
- configuration.access_token = ENV.fetch("ACCESS_TOKEN", nil)
140
- configuration.client_id = ENV.fetch("CLIENT_ID", nil)
93
+ configuration.access_token = ENV.fetch("DHAN_ACCESS_TOKEN", nil)
94
+ configuration.client_id = ENV.fetch("DHAN_CLIENT_ID", nil)
141
95
  configuration.base_url = ENV.fetch("DHAN_BASE_URL", BASE_URL)
142
96
  configuration.ws_version = ENV.fetch("DHAN_WS_VERSION", configuration.ws_version || 2).to_i
143
97
  configuration.ws_order_url = ENV.fetch("DHAN_WS_ORDER_URL", configuration.ws_order_url)