DhanHQ 2.1.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +26 -0
- data/CHANGELOG.md +20 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/GUIDE.md +555 -0
- data/LICENSE.txt +21 -0
- data/README.md +463 -0
- data/README1.md +521 -0
- data/Rakefile +12 -0
- data/TAGS +10 -0
- data/TODO-1.md +14 -0
- data/TODO.md +127 -0
- data/app/services/live/order_update_guard_support.rb +75 -0
- data/app/services/live/order_update_hub.rb +76 -0
- data/app/services/live/order_update_persistence_support.rb +68 -0
- data/config/initializers/order_update_hub.rb +16 -0
- data/diagram.html +184 -0
- data/diagram.md +34 -0
- data/docs/rails_integration.md +304 -0
- data/exe/DhanHQ +4 -0
- data/lib/DhanHQ/client.rb +116 -0
- data/lib/DhanHQ/config.rb +32 -0
- data/lib/DhanHQ/configuration.rb +72 -0
- data/lib/DhanHQ/constants.rb +170 -0
- data/lib/DhanHQ/contracts/base_contract.rb +15 -0
- data/lib/DhanHQ/contracts/historical_data_contract.rb +28 -0
- data/lib/DhanHQ/contracts/margin_calculator_contract.rb +19 -0
- data/lib/DhanHQ/contracts/modify_order_contract copy.rb +100 -0
- data/lib/DhanHQ/contracts/modify_order_contract.rb +22 -0
- data/lib/DhanHQ/contracts/option_chain_contract.rb +31 -0
- data/lib/DhanHQ/contracts/order_contract.rb +102 -0
- data/lib/DhanHQ/contracts/place_order_contract.rb +119 -0
- data/lib/DhanHQ/contracts/position_conversion_contract.rb +24 -0
- data/lib/DhanHQ/contracts/slice_order_contract.rb +111 -0
- data/lib/DhanHQ/core/base_api.rb +105 -0
- data/lib/DhanHQ/core/base_model.rb +266 -0
- data/lib/DhanHQ/core/base_resource.rb +50 -0
- data/lib/DhanHQ/core/error_handler.rb +19 -0
- data/lib/DhanHQ/error_object.rb +49 -0
- data/lib/DhanHQ/errors.rb +45 -0
- data/lib/DhanHQ/helpers/api_helper.rb +17 -0
- data/lib/DhanHQ/helpers/attribute_helper.rb +72 -0
- data/lib/DhanHQ/helpers/model_helper.rb +7 -0
- data/lib/DhanHQ/helpers/request_helper.rb +69 -0
- data/lib/DhanHQ/helpers/response_helper.rb +98 -0
- data/lib/DhanHQ/helpers/validation_helper.rb +36 -0
- data/lib/DhanHQ/json_loader.rb +23 -0
- data/lib/DhanHQ/models/edis.rb +58 -0
- data/lib/DhanHQ/models/forever_order.rb +85 -0
- data/lib/DhanHQ/models/funds.rb +50 -0
- data/lib/DhanHQ/models/historical_data.rb +77 -0
- data/lib/DhanHQ/models/holding.rb +56 -0
- data/lib/DhanHQ/models/kill_switch.rb +49 -0
- data/lib/DhanHQ/models/ledger_entry.rb +60 -0
- data/lib/DhanHQ/models/margin.rb +54 -0
- data/lib/DhanHQ/models/market_feed.rb +41 -0
- data/lib/DhanHQ/models/option_chain.rb +79 -0
- data/lib/DhanHQ/models/order.rb +239 -0
- data/lib/DhanHQ/models/position.rb +60 -0
- data/lib/DhanHQ/models/profile.rb +44 -0
- data/lib/DhanHQ/models/super_order.rb +69 -0
- data/lib/DhanHQ/models/trade.rb +79 -0
- data/lib/DhanHQ/rate_limiter.rb +107 -0
- data/lib/DhanHQ/requests/optionchain/nifty.json +5 -0
- data/lib/DhanHQ/requests/optionchain/nifty_expiries.json +4 -0
- data/lib/DhanHQ/requests/orders/create.json +0 -0
- data/lib/DhanHQ/resources/edis.rb +44 -0
- data/lib/DhanHQ/resources/forever_orders.rb +53 -0
- data/lib/DhanHQ/resources/funds.rb +21 -0
- data/lib/DhanHQ/resources/historical_data.rb +34 -0
- data/lib/DhanHQ/resources/holdings.rb +21 -0
- data/lib/DhanHQ/resources/kill_switch.rb +21 -0
- data/lib/DhanHQ/resources/margin_calculator.rb +22 -0
- data/lib/DhanHQ/resources/market_feed.rb +56 -0
- data/lib/DhanHQ/resources/option_chain.rb +31 -0
- data/lib/DhanHQ/resources/orders.rb +70 -0
- data/lib/DhanHQ/resources/positions.rb +29 -0
- data/lib/DhanHQ/resources/profile.rb +25 -0
- data/lib/DhanHQ/resources/statements.rb +42 -0
- data/lib/DhanHQ/resources/super_orders.rb +46 -0
- data/lib/DhanHQ/resources/trades.rb +23 -0
- data/lib/DhanHQ/version.rb +6 -0
- data/lib/DhanHQ/ws/client.rb +182 -0
- data/lib/DhanHQ/ws/cmd_bus.rb +38 -0
- data/lib/DhanHQ/ws/connection.rb +240 -0
- data/lib/DhanHQ/ws/decoder.rb +83 -0
- data/lib/DhanHQ/ws/errors.rb +0 -0
- data/lib/DhanHQ/ws/orders/client.rb +59 -0
- data/lib/DhanHQ/ws/orders/connection.rb +148 -0
- data/lib/DhanHQ/ws/orders.rb +13 -0
- data/lib/DhanHQ/ws/packets/depth_delta_packet.rb +20 -0
- data/lib/DhanHQ/ws/packets/disconnect_packet.rb +15 -0
- data/lib/DhanHQ/ws/packets/full_packet.rb +40 -0
- data/lib/DhanHQ/ws/packets/header.rb +23 -0
- data/lib/DhanHQ/ws/packets/index_packet.rb +14 -0
- data/lib/DhanHQ/ws/packets/market_depth_level.rb +21 -0
- data/lib/DhanHQ/ws/packets/market_status_packet.rb +14 -0
- data/lib/DhanHQ/ws/packets/oi_packet.rb +15 -0
- data/lib/DhanHQ/ws/packets/prev_close_packet.rb +16 -0
- data/lib/DhanHQ/ws/packets/quote_packet.rb +26 -0
- data/lib/DhanHQ/ws/packets/ticker_packet.rb +16 -0
- data/lib/DhanHQ/ws/registry.rb +46 -0
- data/lib/DhanHQ/ws/segments.rb +75 -0
- data/lib/DhanHQ/ws/singleton_lock.rb +54 -0
- data/lib/DhanHQ/ws/sub_state.rb +59 -0
- data/lib/DhanHQ/ws/websocket_packet_parser.rb +165 -0
- data/lib/DhanHQ/ws.rb +37 -0
- data/lib/DhanHQ.rb +135 -0
- data/lib/ta/technical_analysis.rb +405 -0
- data/sig/DhanHQ.rbs +4 -0
- data/watchlist.csv +3 -0
- metadata +283 -0
@@ -0,0 +1,165 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "stringio"
|
4
|
+
|
5
|
+
require_relative "packets/header"
|
6
|
+
require_relative "packets/ticker_packet"
|
7
|
+
require_relative "packets/quote_packet"
|
8
|
+
require_relative "packets/full_packet"
|
9
|
+
require_relative "packets/oi_packet"
|
10
|
+
require_relative "packets/prev_close_packet"
|
11
|
+
require_relative "packets/disconnect_packet"
|
12
|
+
require_relative "packets/index_packet"
|
13
|
+
require_relative "packets/market_status_packet"
|
14
|
+
# optional:
|
15
|
+
require_relative "packets/depth_delta_packet"
|
16
|
+
|
17
|
+
module DhanHQ
|
18
|
+
module WS
|
19
|
+
# Parses raw WebSocket frames using the binary packet definitions.
|
20
|
+
class WebsocketPacketParser
|
21
|
+
# Numeric feed codes emitted by the streaming service.
|
22
|
+
RESPONSE_CODES = {
|
23
|
+
index: 1,
|
24
|
+
ticker: 2,
|
25
|
+
quote: 4,
|
26
|
+
oi: 5,
|
27
|
+
prev_close: 6,
|
28
|
+
full: 8,
|
29
|
+
depth_bid: 41,
|
30
|
+
depth_ask: 51,
|
31
|
+
disconnect: 50
|
32
|
+
}.freeze
|
33
|
+
|
34
|
+
attr_reader :binary_data, :binary_stream, :header
|
35
|
+
|
36
|
+
def initialize(binary_data)
|
37
|
+
@binary_data = binary_data
|
38
|
+
@header = Packets::Header.read(@binary_data) # 8 bytes header
|
39
|
+
@binary_stream = StringIO.new(@binary_data.byteslice(8..) || "".b) # payload only
|
40
|
+
end
|
41
|
+
|
42
|
+
# Parses the supplied binary frame and returns a normalized hash.
|
43
|
+
#
|
44
|
+
# @return [Hash]
|
45
|
+
def parse
|
46
|
+
body =
|
47
|
+
case header.feed_response_code
|
48
|
+
when RESPONSE_CODES[:index] then parse_index
|
49
|
+
when RESPONSE_CODES[:ticker] then parse_ticker
|
50
|
+
when RESPONSE_CODES[:quote] then parse_quote
|
51
|
+
when RESPONSE_CODES[:oi] then parse_oi
|
52
|
+
when RESPONSE_CODES[:prev_close] then parse_prev_close
|
53
|
+
when RESPONSE_CODES[:market_status] then parse_market_status
|
54
|
+
when RESPONSE_CODES[:full] then parse_full
|
55
|
+
when RESPONSE_CODES[:depth_bid] then parse_depth(:bid)
|
56
|
+
when RESPONSE_CODES[:depth_ask] then parse_depth(:ask)
|
57
|
+
when RESPONSE_CODES[:disconnect] then parse_disconnect
|
58
|
+
else
|
59
|
+
DhanHQ.logger&.debug("[WS::Parser] Unknown feed code=#{header.feed_response_code}")
|
60
|
+
{}
|
61
|
+
end
|
62
|
+
|
63
|
+
{
|
64
|
+
feed_response_code: header.feed_response_code,
|
65
|
+
message_length: header.message_length,
|
66
|
+
exchange_segment: header.exchange_segment, # numeric (0/1/2/…)
|
67
|
+
security_id: header.security_id
|
68
|
+
}.merge(body)
|
69
|
+
rescue StandardError => e
|
70
|
+
DhanHQ.logger.error "[WS::Parser] ❌ #{e.class}: #{e.message}"
|
71
|
+
{}
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def parse_index
|
77
|
+
rec = Packets::IndexPacket.new(@binary_stream.string)
|
78
|
+
{ index_raw: rec.raw } # keep raw until official layout is known
|
79
|
+
end
|
80
|
+
|
81
|
+
def parse_market_status
|
82
|
+
rec = Packets::MarketStatusPacket.new(@binary_stream.string)
|
83
|
+
{ market_status_raw: rec.raw } # keep raw until official layout is known
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_ticker
|
87
|
+
rec = Packets::TickerPacket.read(@binary_stream.string)
|
88
|
+
{ ltp: rec.ltp, ltt: rec.ltt }
|
89
|
+
end
|
90
|
+
|
91
|
+
def parse_quote
|
92
|
+
rec = Packets::QuotePacket.read(@binary_stream.string)
|
93
|
+
|
94
|
+
{
|
95
|
+
ltp: rec.ltp,
|
96
|
+
last_trade_qty: rec.last_trade_qty,
|
97
|
+
ltt: rec.ltt,
|
98
|
+
atp: rec.atp,
|
99
|
+
volume: rec.volume,
|
100
|
+
total_sell_qty: rec.total_sell_qty,
|
101
|
+
total_buy_qty: rec.total_buy_qty,
|
102
|
+
day_open: rec.day_open,
|
103
|
+
day_close: rec.day_close,
|
104
|
+
day_high: rec.day_high,
|
105
|
+
day_low: rec.day_low
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
def parse_full
|
110
|
+
rec = Packets::FullPacket.read(@binary_stream.string)
|
111
|
+
{
|
112
|
+
ltp: rec.ltp,
|
113
|
+
last_trade_qty: rec.last_trade_qty,
|
114
|
+
ltt: rec.ltt,
|
115
|
+
atp: rec.atp,
|
116
|
+
volume: rec.volume,
|
117
|
+
total_sell_qty: rec.total_sell_qty,
|
118
|
+
total_buy_qty: rec.total_buy_qty,
|
119
|
+
open_interest: rec.open_interest,
|
120
|
+
highest_open_interest: rec.highest_oi,
|
121
|
+
lowest_open_interest: rec.lowest_oi,
|
122
|
+
day_open: rec.day_open,
|
123
|
+
day_close: rec.day_close,
|
124
|
+
day_high: rec.day_high,
|
125
|
+
day_low: rec.day_low,
|
126
|
+
market_depth: rec.market_depth
|
127
|
+
}
|
128
|
+
end
|
129
|
+
|
130
|
+
def parse_oi
|
131
|
+
rec = Packets::OiPacket.read(@binary_stream.string)
|
132
|
+
{ open_interest: rec.open_interest }
|
133
|
+
end
|
134
|
+
|
135
|
+
def parse_prev_close
|
136
|
+
rec = Packets::PrevClosePacket.read(@binary_stream.string)
|
137
|
+
{ prev_close: rec.prev_close, oi_prev: rec.oi_prev }
|
138
|
+
end
|
139
|
+
|
140
|
+
# depth_bid / depth_ask incremental
|
141
|
+
def parse_depth(side)
|
142
|
+
rec = Packets::DepthDeltaPacket.read(@binary_stream.string)
|
143
|
+
{
|
144
|
+
depth_side: side,
|
145
|
+
bid_quantity: rec.bid_quantity,
|
146
|
+
ask_quantity: rec.ask_quantity,
|
147
|
+
no_of_bid_orders: rec.no_of_bid_orders,
|
148
|
+
no_of_ask_orders: rec.no_of_ask_orders,
|
149
|
+
bid_price: rec.bid_price,
|
150
|
+
ask_price: rec.ask_price
|
151
|
+
}
|
152
|
+
end
|
153
|
+
|
154
|
+
def parse_disconnect
|
155
|
+
{
|
156
|
+
disconnection_code: binary_stream.read(2).unpack1("s>")
|
157
|
+
}
|
158
|
+
end
|
159
|
+
|
160
|
+
def debug_log(data)
|
161
|
+
DhanHQ.logger.debug { "[WS::Parser] Parsed: #{data.inspect}" }
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/lib/DhanHQ/ws.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "ws/client"
|
4
|
+
require_relative "ws/orders"
|
5
|
+
|
6
|
+
module DhanHQ
|
7
|
+
# Namespace for the WebSocket streaming client helpers.
|
8
|
+
#
|
9
|
+
# The helpers provide a simple façade around {DhanHQ::WS::Client} so that
|
10
|
+
# applications can start streaming market data with a single method call.
|
11
|
+
module WS
|
12
|
+
# Establishes a WebSocket connection and yields decoded ticks.
|
13
|
+
#
|
14
|
+
# @example Subscribe to ticker updates
|
15
|
+
# DhanHQ::WS.connect(mode: :ticker) do |tick|
|
16
|
+
# puts tick.inspect
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# @param mode [Symbol] Desired feed mode (:ticker, :quote, :full).
|
20
|
+
# @yield [tick]
|
21
|
+
# @yieldparam tick [Hash] A decoded tick emitted by the streaming API.
|
22
|
+
# @return [DhanHQ::WS::Client] The underlying WebSocket client instance.
|
23
|
+
def self.connect(mode: :ticker, &on_tick)
|
24
|
+
Client.new(mode: mode).start.on(:tick, &on_tick)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Disconnects every WebSocket client created in the current process.
|
28
|
+
#
|
29
|
+
# Useful when a long running script needs to ensure all connections are
|
30
|
+
# closed (e.g., in signal handlers or +at_exit+ hooks).
|
31
|
+
#
|
32
|
+
# @return [void]
|
33
|
+
def self.disconnect_all_local!
|
34
|
+
Registry.stop_all
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/DhanHQ.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dotenv/load"
|
4
|
+
require "logger"
|
5
|
+
|
6
|
+
# Helper Methods
|
7
|
+
require_relative "DhanHQ/helpers/api_helper"
|
8
|
+
require_relative "DhanHQ/helpers/attribute_helper"
|
9
|
+
require_relative "DhanHQ/helpers/validation_helper"
|
10
|
+
require_relative "DhanHQ/helpers/request_helper"
|
11
|
+
require_relative "DhanHQ/helpers/response_helper"
|
12
|
+
require_relative "DhanHQ/json_loader"
|
13
|
+
|
14
|
+
require_relative "DhanHQ/core/base_api"
|
15
|
+
require_relative "DhanHQ/core/base_resource"
|
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
|
+
|
27
|
+
# Contracts
|
28
|
+
require_relative "DhanHQ/contracts/base_contract"
|
29
|
+
require_relative "DhanHQ/contracts/historical_data_contract"
|
30
|
+
require_relative "DhanHQ/contracts/margin_calculator_contract"
|
31
|
+
require_relative "DhanHQ/contracts/position_conversion_contract"
|
32
|
+
require_relative "DhanHQ/contracts/slice_order_contract"
|
33
|
+
|
34
|
+
# Resources
|
35
|
+
require_relative "DhanHQ/resources/option_chain"
|
36
|
+
require_relative "DhanHQ/resources/orders"
|
37
|
+
require_relative "DhanHQ/resources/forever_orders"
|
38
|
+
require_relative "DhanHQ/resources/super_orders"
|
39
|
+
require_relative "DhanHQ/resources/funds"
|
40
|
+
require_relative "DhanHQ/resources/holdings"
|
41
|
+
require_relative "DhanHQ/resources/positions"
|
42
|
+
require_relative "DhanHQ/resources/statements"
|
43
|
+
require_relative "DhanHQ/resources/trades"
|
44
|
+
require_relative "DhanHQ/resources/historical_data"
|
45
|
+
require_relative "DhanHQ/resources/margin_calculator"
|
46
|
+
require_relative "DhanHQ/resources/market_feed"
|
47
|
+
require_relative "DhanHQ/resources/edis"
|
48
|
+
require_relative "DhanHQ/resources/kill_switch"
|
49
|
+
require_relative "DhanHQ/resources/profile"
|
50
|
+
|
51
|
+
# Models
|
52
|
+
require_relative "DhanHQ/models/order"
|
53
|
+
require_relative "DhanHQ/models/funds"
|
54
|
+
require_relative "DhanHQ/models/option_chain"
|
55
|
+
require_relative "DhanHQ/models/forever_order"
|
56
|
+
require_relative "DhanHQ/models/super_order"
|
57
|
+
require_relative "DhanHQ/models/historical_data"
|
58
|
+
require_relative "DhanHQ/models/market_feed"
|
59
|
+
require_relative "DhanHQ/models/position"
|
60
|
+
require_relative "DhanHQ/models/holding"
|
61
|
+
require_relative "DhanHQ/models/ledger_entry"
|
62
|
+
require_relative "DhanHQ/models/trade"
|
63
|
+
require_relative "DhanHQ/models/margin"
|
64
|
+
require_relative "DhanHQ/models/edis"
|
65
|
+
require_relative "DhanHQ/models/kill_switch"
|
66
|
+
require_relative "DhanHQ/models/profile"
|
67
|
+
|
68
|
+
require_relative "DhanHQ/constants"
|
69
|
+
require_relative "DhanHQ/ws"
|
70
|
+
require_relative "DhanHQ/ws/singleton_lock"
|
71
|
+
|
72
|
+
# The top-level module for the DhanHQ client library.
|
73
|
+
#
|
74
|
+
# Provides configuration management for setting credentials and API-related settings.
|
75
|
+
module DhanHQ
|
76
|
+
class Error < StandardError; end
|
77
|
+
|
78
|
+
class << self
|
79
|
+
# Default REST API host used when no custom base URL is provided.
|
80
|
+
#
|
81
|
+
# @return [String]
|
82
|
+
BASE_URL = "https://api.dhan.co/v2"
|
83
|
+
# The current configuration instance.
|
84
|
+
#
|
85
|
+
# @return [DhanHQ::Configuration, nil] The current configuration or `nil` if not set.
|
86
|
+
attr_accessor :configuration
|
87
|
+
|
88
|
+
attr_writer :logger
|
89
|
+
|
90
|
+
# Configures the DhanHQ client with user-defined settings.
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# DhanHQ.configure do |config|
|
94
|
+
# config.access_token = 'your_access_token'
|
95
|
+
# config.client_id = 'your_client_id'
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# @yieldparam [DhanHQ::Configuration] configuration The configuration object.
|
99
|
+
# @return [void]
|
100
|
+
def configure
|
101
|
+
self.configuration ||= Configuration.new
|
102
|
+
yield(configuration)
|
103
|
+
self.logger ||= Logger.new($stdout, level: Logger::INFO)
|
104
|
+
end
|
105
|
+
|
106
|
+
# default logger so calls like DhanHQ.logger&.info never explode
|
107
|
+
# Accessor for the logger instance used by the SDK.
|
108
|
+
#
|
109
|
+
# @return [Logger] The configured logger, defaulting to STDOUT at INFO level.
|
110
|
+
def logger
|
111
|
+
@logger ||= Logger.new($stdout, level: Logger::INFO)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Configures the DhanHQ client using environment variables.
|
115
|
+
#
|
116
|
+
# When credentials are injected via `ACCESS_TOKEN` and `CLIENT_ID` this helper
|
117
|
+
# can be used to initialise a configuration without a block.
|
118
|
+
#
|
119
|
+
# @example
|
120
|
+
# DhanHQ.configure_with_env
|
121
|
+
#
|
122
|
+
# @return [void]
|
123
|
+
def configure_with_env
|
124
|
+
self.configuration ||= Configuration.new
|
125
|
+
configuration.access_token = ENV.fetch("ACCESS_TOKEN", nil)
|
126
|
+
configuration.client_id = ENV.fetch("CLIENT_ID", nil)
|
127
|
+
configuration.base_url = ENV.fetch("DHAN_BASE_URL", BASE_URL)
|
128
|
+
configuration.ws_version = ENV.fetch("DHAN_WS_VERSION", configuration.ws_version || 2).to_i
|
129
|
+
configuration.ws_order_url = ENV.fetch("DHAN_WS_ORDER_URL", configuration.ws_order_url)
|
130
|
+
configuration.ws_user_type = ENV.fetch("DHAN_WS_USER_TYPE", configuration.ws_user_type)
|
131
|
+
configuration.partner_id = ENV.fetch("DHAN_PARTNER_ID", configuration.partner_id)
|
132
|
+
configuration.partner_secret = ENV.fetch("DHAN_PARTNER_SECRET", configuration.partner_secret)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|