Dhan API - Java implementation of data apis

Hi There, has anyone successfully implemented the dhan api client using java programming tools. If yes, could you share the snippets of byte code that needs to be generated during the authentication and the response from the server after the successful auth.

I appreciate the auth and subscriptions are done in async mode but I am not entirely sure whether the ws connection is successful. @Hardik I appreciate you have responded on similar queries for python implementation. But any help on Java would be really appreciated. thanks.

Hello @pnsudesh

I am myself not very well versed with Java, but if you are facing any particular issue while integrating, let us know and we will be happy to assist in any way possible. Are you able to connect to Dhan Live Market Feed or even the connection is not getting established?

Hi @Hardik Thanks for the message.

I am trying to build the Java app (Spring framework) and I am utilizing the EndPoint class as below.

public class WSEndpoint extends Endpoint {
private Session session;

    @Override
    public void onOpen(Session session, EndpointConfig config) {
        this.session = session;
        System.out.println("onOpen");
        this.session.addMessageHandler(new MessageHandler.Whole<byte[]>() {
			@Override
			public void onMessage(byte[] message) {
				System.out.println("from server:" + message);	
			}
        });
    }
    
    @OnMessage
    public void connected(String msg){
        System.out.println("Message from DHAN server: " + msg);
    }
    @OnClose
    public void disconnected(Session session, CloseReason reason){
       // System.out.println("User "+ user + " disconnected as a result of "+ reason.getReasonPhrase());
    	System.out.println("onClose");
    }
    @OnError
    public void disconnected(Session session, Throwable error){
        System.out.println("Error communicating with DHAN server: " + error.getMessage());
    }
    
    public void connectToDhan(byte[] authMsg) throws EncodeException, IOException{
		System.out.println("connectToDhan");
		ByteBuffer buffer = ByteBuffer.wrap(authMsg);
		this.session.getBasicRemote().sendBinary(buffer);
		System.out.println("AFTER connectToDhan");
}

}

While I can see the connectToDhan method execution via System output, neither Onmessage not Onopen get triggered from Dhan server. It seems my auth message itself is incorrect. I am using byte arrays to generate the byte code to pass it on the endpoint call.

Do you have any Java working example of using the Dhan apis for getting the market data? May be I am not passing the right set of byte codes. Anything to help me solve this problem will be highly appreciated. thanks.

Hello @pnsudesh

We do not have any Java implementation samples, but if you can share the byte structure you are sending or the code snippet where you are converting it to byte array, we can look into that and assist you.

package com.tradingbot.dhan.component;

import java.net.URI;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.stereotype.Component;

import com.tradingbot.dhan.dto.Instrument;
import com.tradingbot.dhan.dto.MarketDepth;
import com.tradingbot.dhan.dto.MarketDepthData;
import com.tradingbot.dhan.dto.OIData;
import com.tradingbot.dhan.dto.PreviousCloseData;
import com.tradingbot.dhan.dto.QuoteData;
import com.tradingbot.dhan.dto.ResponseHeader;
import com.tradingbot.dhan.dto.TickerData;

@Component
public class DhanWebSocketClient extends WebSocketClient {

    private static final String SOCKET_URI = "wss://api-feed.dhan.co";
    private static final String CLIENT_ID = "XXXXXXXXXX";
    private static final String API_ACCESS_TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx";

    public DhanWebSocketClient() throws Exception {
        super(new URI(SOCKET_URI));
    }

    @PostConstruct
    public void start() {
        this.connect();
    }

    @Override
    public void onOpen(ServerHandshake handshakedata) {
        System.out.println("Connection opened");
        sendAuthorizationPacket();
        subscribeInstruments(); // Call the method to subscribe to instruments
    }

    @Override
    public void onMessage(String message) {
        System.out.println("message :"+message);
    }

    @Override
    public void onMessage(ByteBuffer bytes) {
        ResponseHeader header = new ResponseHeader();
        header.setFeedResponseCode(bytes.get());
        header.setMessageLength(bytes.getShort());
        header.setExchangeSegment(bytes.get());
        header.setSecurityId(bytes.getInt());

        System.out.println("header.getFeedResponseCode() : "+header.getFeedResponseCode());
        // Process based on response code
        switch (header.getFeedResponseCode()) {
            case 2:
                TickerData tickerData = new TickerData();
                tickerData.setHeader(header);
                tickerData.setLastTradedPrice(bytes.getFloat());
                tickerData.setLastTradeTime(bytes.getInt());
                System.out.println(tickerData);
                break;
            case 4:
                QuoteData quoteData = new QuoteData();
                quoteData.setHeader(header);
                quoteData.setLatestTradedPrice(bytes.getFloat());
                quoteData.setLastTradedQuantity(bytes.getShort());
                quoteData.setLastTradeTime(bytes.getInt());
                quoteData.setAverageTradePrice(bytes.getFloat());
                quoteData.setVolume(bytes.getInt());
                quoteData.setTotalSellQuantity(bytes.getInt());
                quoteData.setTotalBuyQuantity(bytes.getInt());
                quoteData.setDayOpenValue(bytes.getFloat());
                quoteData.setDayCloseValue(bytes.getFloat());
                quoteData.setDayHighValue(bytes.getFloat());
                quoteData.setDayLowValue(bytes.getFloat());
                System.out.println(quoteData);
                break;
            case 5:
                OIData oiData = new OIData();
                oiData.setHeader(header);
                oiData.setOpenInterest(bytes.getInt());
                System.out.println(oiData);
                break;
            case 3:
                MarketDepthData marketDepthData = new MarketDepthData();
                marketDepthData.setHeader(header);
                marketDepthData.setLatestTradedPrice(bytes.getFloat());
                List<MarketDepth> marketDepthList = new ArrayList<>();
                for (int i = 0; i < 5; i++) {
                    MarketDepth marketDepth = new MarketDepth();
                    marketDepth.setBidQuantity(bytes.getInt());
                    marketDepth.setAskQuantity(bytes.getInt());
                    marketDepth.setBidOrders(bytes.getShort());
                    marketDepth.setAskOrders(bytes.getShort());
                    marketDepth.setBidPrice(bytes.getFloat());
                    marketDepth.setAskPrice(bytes.getFloat());
                    marketDepthList.add(marketDepth);
                }
                marketDepthData.setMarketDepthList(marketDepthList);
                System.out.println(marketDepthData);
                break;
            case 6:
                PreviousCloseData previousCloseData = new PreviousCloseData();
                previousCloseData.setHeader(header);
                previousCloseData.setPreviousClosePrice(bytes.getInt());
                previousCloseData.setPreviousDayOI(bytes.getInt());
                System.out.println(previousCloseData);
                break;
            case 7:
                System.out.println("Market Status: Open/Close notification");
                break;
            default:
                System.out.println("Unknown response code: " + header.getFeedResponseCode());
        }
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        System.out.println("Connection closed with exit code " + code + " additional info: " + reason);
    }

    @Override
    public void onError(Exception ex) {
        ex.printStackTrace();
    }

    private void sendAuthorizationPacket() {
        ByteBuffer buffer = ByteBuffer.allocate(585);
        // Header
        buffer.put((byte) 11); // Feed Request Code for new feed
        buffer.putShort((short) 585); // Message Length
        buffer.put(CLIENT_ID.getBytes()); // Client ID
        buffer.position(34); // Skip to Dhan Auth
        buffer.put(new byte[50]); // Dhan Auth (zeroes)
        // Payload
        buffer.put(API_ACCESS_TOKEN.getBytes()); // API Access Token
        buffer.putShort((short) 2); // Authentication Type

        buffer.flip();
        send(buffer);
    }

    private void subscribeInstruments() {
        // Create a list of instruments to subscribe to
        List<Instrument> instruments = createInstrumentsList();

        // Subscribe to instruments
        ByteBuffer buffer = ByteBuffer.allocate(2188); // 88 bytes for header + 2100 bytes for instruments
        // Header
        buffer.put((byte) 11); // Feed Request Code for new feed
        buffer.putShort((short) 2187); // Message Length (88 + 2100 - 1)
        buffer.put(CLIENT_ID.getBytes()); // Client ID
        buffer.position(34); // Skip to Dhan Auth
        buffer.put(new byte[50]); // Dhan Auth (zeroes)
        // Payload
        buffer.putInt(instruments.size()); // Number of instruments to subscribe
        for (Instrument instrument : instruments) {
            buffer.put(instrument.getExchangeSegment().getBytes()); // Exchange Segment
            buffer.put(instrument.getSecurityId().getBytes()); // Security ID
            // Pad with zeroes if necessary
            for (int k = 0; k < 19; k++) {
                buffer.put((byte) 0);
            }
        }

        buffer.flip();
        send(buffer);
    }

    private List<Instrument> createInstrumentsList() {
        // Implement logic to create a list of instruments to subscribe to
        return List.of(
            //new Instrument("IDX_I", "13"),//NIFTY
            //new Instrument("Index", "25"),//BANKNIFTY
            //new Instrument("NSE", "10940") ,//DIVISLAB
            new Instrument("MCX", "426280") 
        );
    }
}

@Hardik ,

I tried with above code in java springboot. But i am getting response code 50 from dhan in public void onMessage(ByteBuffer bytes)() method. What does this error code mean?

default:
System.out.println("Unknown response code: " + header.getFeedResponseCode());
//the above line in onMessage() method prints
//Unknown response code: 50

Also what should be exchange segment given while subscribing? is it MCX, NSE etc in SEM_EXM_EXCH_ID column in api-scrip-master.csv?

What should be securityId while subscribing? is it the value in SEM_SMST_SECURITY_ID in api-scrip-master.csv?