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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/CODE_REVIEW_ISSUES.md +2 -2
- data/GUIDE.md +63 -21
- data/README.md +16 -5
- data/README1.md +4 -4
- data/REVIEW_SUMMARY.md +2 -2
- data/docs/API_VERIFICATION.md +67 -0
- data/docs/AUTHENTICATION.md +54 -2
- data/docs/TESTING_GUIDE.md +40 -42
- data/docs/live_order_updates.md +2 -2
- data/docs/rails_integration.md +7 -7
- data/docs/standalone_ruby_websocket_integration.md +24 -24
- data/docs/technical_analysis.md +1 -1
- data/docs/websocket_integration.md +4 -4
- data/examples/comprehensive_websocket_examples.rb +2 -2
- data/examples/instrument_finder_test.rb +2 -2
- data/examples/market_depth_example.rb +2 -2
- data/examples/market_feed_example.rb +2 -2
- data/examples/order_update_example.rb +2 -2
- data/examples/trading_fields_example.rb +2 -2
- data/lib/DhanHQ/auth/token_generator.rb +33 -0
- data/lib/DhanHQ/auth/token_manager.rb +88 -0
- data/lib/DhanHQ/auth/token_renewal.rb +25 -0
- data/lib/DhanHQ/auth.rb +91 -31
- data/lib/DhanHQ/client.rb +42 -2
- data/lib/DhanHQ/configuration.rb +2 -2
- data/lib/DhanHQ/contracts/alert_order_contract.rb +20 -0
- data/lib/DhanHQ/contracts/order_contract.rb +0 -23
- data/lib/DhanHQ/contracts/trade_by_order_id_contract.rb +12 -0
- data/lib/DhanHQ/contracts/trade_contract.rb +0 -65
- data/lib/DhanHQ/contracts/trade_history_contract.rb +52 -0
- data/lib/DhanHQ/core/auth_api.rb +21 -0
- data/lib/DhanHQ/core/base_resource.rb +5 -5
- data/lib/DhanHQ/helpers/request_helper.rb +1 -1
- data/lib/DhanHQ/models/alert_order.rb +83 -0
- data/lib/DhanHQ/models/token_response.rb +88 -0
- data/lib/DhanHQ/resources/alert_orders.rb +11 -0
- data/lib/DhanHQ/resources/edis.rb +5 -20
- data/lib/DhanHQ/resources/ip_setup.rb +23 -0
- data/lib/DhanHQ/resources/trader_control.rb +23 -0
- data/lib/DhanHQ/version.rb +1 -1
- data/lib/dhan_hq.rb +31 -77
- metadata +43 -4
- data/lib/DhanHQ/config.rb +0 -33
- 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(
|
|
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("
|
|
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(
|
|
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("
|
|
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("
|
|
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
|
|
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
|
|
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
|
-
|
|
8
|
-
|
|
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
|
data/lib/DhanHQ/version.rb
CHANGED
data/lib/dhan_hq.rb
CHANGED
|
@@ -1,92 +1,46 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
3
|
+
require "json"
|
|
4
4
|
require "logger"
|
|
5
|
-
|
|
6
|
-
|
|
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/
|
|
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 `
|
|
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("
|
|
140
|
-
configuration.client_id = ENV.fetch("
|
|
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)
|