Guides

Get contracts for a symbol

Follow these steps to retrieve the list of available contracts, along with the latest barrier and duration limits for each contract, for a given symbol using the Deriv API:

  1. Import Deriv API: Import the DerivAPIBasic library from Skypack CDN.
  2. WebSocket connection: Create a WebSocket connection to the Deriv API using your app_id.
  3. API initialization: Initialize the DerivAPIBasic instance with the WebSocket connection.
  4. Request object: Define a request object to fetch contracts for a specific symbol (e.g., R_50).
  5. Response handling: Handle the API response:
    1. Parse the data and log any errors.
    2. If the response contains contract data, log it.
    3. Remove the event listener after the response is received.
  6. Trigger request: On a button click, the function sends the request to the API to get the contracts for the symbol.
// Import DerivAPIBasic from the Deriv API package
import DerivAPIBasic from '@deriv/deriv-api/dist/DerivAPIBasic.js';

// Set the app ID for API authentication. Use 1089 for testing or replace it with your app's ID.
const app_id = 1089;

// Create a WebSocket connection to the Deriv server using the app_id for authentication
const connection = new WebSocket(`wss://ws.derivws.com/websockets/v3?app_id=${app_id}`);

// Initialize the API using the WebSocket connection
const api = new DerivAPIBasic({ connection });

// Function to handle the contracts for symbol response
const handleContractsForSymbolResponse = async (response) => {
  const data = JSON.parse(response.data);

  // Check for errors in the response
  if (data.error) {
    console.error('Error:', data.error.message);
    await api.disconnect();
    return;
  }

  // If the message type is 'contracts_for', log the contracts information
  if (data.msg_type === 'contracts_for') {
    const contractsInfo = data.contracts_for;
    console.log('Contracts for Symbol:', contractsInfo);
  }

  // Remove the event listener after processing the response
  connection.removeEventListener('message', handleContractsForSymbolResponse);
};

// Function to request contracts for a specific symbol
const getContractsForSymbol = async () => {
  const contracts_for_symbol_request = {
    contracts_for: 'R_50',   // Specify the symbol
    currency: 'USD',
    landing_company: 'svg',
    product_type: 'basic',
  };

  connection.addEventListener('message', handleContractsForSymbolResponse); // Add event listener
  await api.contractsFor(contracts_for_symbol_request); // Send the contracts request
};

// Check if running in a browser or Node.js environment
if (typeof document !== 'undefined') {
  // Add a button event listener in the browser environment
  const contracts_for_symbol_button = document.querySelector('#contractsForSymbol');
  if (contracts_for_symbol_button) {
    contracts_for_symbol_button.addEventListener('click', getContractsForSymbol);
  }
} else {
  // If running in Node.js, directly call the function
  getContractsForSymbol();
}

/*
 * Instructions to Run the Code on a Local Machine:
 * 1. Ensure Node.js is installed on your machine. Download it from https://nodejs.org/ if needed.
 * 2. Install required dependencies:
 *      - Run: `npm install @deriv/deriv-api ws`
 * 3. Save this code to a file, e.g., `contracts_for_symbol.js`.
 * 4. Open a terminal and navigate to the directory where the file is saved.
 * 5. Run the code using Node.js:
 *      - Run: `node contracts_for_symbol.js`
 *
 * In a browser environment:
 * - Save this code to a JavaScript file and link it to an HTML page with a button element:
 *   `<button id="contractsForSymbol">Get Contracts for Symbol</button>`
 * - Open the HTML file in a browser, and click the button to retrieve contracts for the symbol.
 */
package src.main.java;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Timer;
import java.util.TimerTask;
import com.google.gson.JsonObject;

public class WebSocketExample {

    public static void main(String[] args) {
        try {
            // Replace with your app_id
            int app_id = 1089;
            String serverUri = "wss://ws.derivws.com/websockets/v3?app_id=" + app_id;

            // Initialize the WebSocket client
            WebSocketClient client = new WebSocketClient(new URI(serverUri)) {

                @Override
                public void onOpen(ServerHandshake handshakedata) {
                    System.out.println("[open] Connection established");

                    // Send contracts for symbol request
                    JsonObject contractsForSymbolRequest = new JsonObject();
                    contractsForSymbolRequest.addProperty("contracts_for", "R_50"); // Specify symbol here
                    contractsForSymbolRequest.addProperty("currency", "USD");
                    contractsForSymbolRequest.addProperty("landing_company", "svg");
                    contractsForSymbolRequest.addProperty("product_type", "basic");
                    send(contractsForSymbolRequest.toString());
                    System.out.println("[sent] Contracts for symbol request sent");

                    // Schedule a ping every 30 seconds
                    Timer timer = new Timer();
                    timer.scheduleAtFixedRate(new TimerTask() {
                        @Override
                        public void run() {
                            JsonObject pingMessage = new JsonObject();
                            pingMessage.addProperty("ping", 1);
                            send(pingMessage.toString());
                            System.out.println("[ping] Ping sent to keep connection alive");
                        }
                    }, 0, 30000);
                }

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

                    JsonObject data = new com.google.gson.JsonParser().parse(message).getAsJsonObject();
                    if (data.has("error")) {
                        System.out.println("[error] " + data.getAsJsonObject("error").get("message").getAsString());
                    } else if ("contracts_for".equals(data.get("msg_type").getAsString())) {
                        JsonObject contractsFor = data.getAsJsonObject("contracts_for");
                        System.out.println("Contracts for Symbol: " + contractsFor);
                    } else if ("ping".equals(data.get("msg_type").getAsString())) {
                        System.out.println("[ping] Ping response received.");
                    }
                }

                @Override
                public void onClose(int code, String reason, boolean remote) {
                    System.out.println("[close] Connection closed by " + (remote ? "server" : "client") + ": " + reason);
                }

                @Override
                public void onError(Exception ex) {
                    System.out.println("[error] " + ex.getMessage());
                }
            };

            client.connect();

        } catch (URISyntaxException e) {
            System.out.println("[error] Invalid URI: " + e.getMessage());
        }
    }
}

/*
Instructions to run the code:

1. Ensure that Java is installed on your machine. You can download it from https://www.oracle.com/java/technologies/javase-jdk11-downloads.html.
2. Add the following dependencies to your project:
   - `java-websocket` for WebSocket functionality
   - `gson` for JSON handling

   If you are using Maven, add these dependencies to your `pom.xml`:

   <dependency>
       <groupId>org.java-websocket</groupId>
       <artifactId>Java-WebSocket</artifactId>
       <version>1.5.2</version>
   </dependency>
   <dependency>
       <groupId>com.google.code.gson</groupId>
       <artifactId>gson</artifactId>
       <version>2.8.8</version>
   </dependency>

3. Compile the code:
   javac WebSocketExample.java

4. Run the code:
   java WebSocketExample

Note: Replace `app_id` with your actual app_id if needed.
 */
#!/usr/bin/env perl
use strict;
use warnings;
use v5.014;
use AnyEvent;
use AnyEvent::WebSocket::Client;
use JSON;

# WebSocket URL and app_id
my $app_id = 1089;
my $url = "wss://ws.derivws.com/websockets/v3?app_id=$app_id";

# Create WebSocket client and connection
my $client = AnyEvent::WebSocket::Client->new;
$| = 1;  # Flush output immediately for real-time logging

# Function to send a contracts for symbol request
sub send_contracts_for_symbol {
    my $connection = shift;
    my $contracts_for_request = encode_json({
        contracts_for => 'R_50',    # Symbol for which contracts are requested
        currency => 'USD',          # Set currency to USD
        landing_company => 'svg',   # Landing company (e.g., svg)
        product_type => 'basic'     # Product type is set to 'basic'
    });
    $connection->send($contracts_for_request);
    say "[request] Contracts for symbol request sent.";
}

# Establish WebSocket connection
$client->connect($url)->cb(sub {
    my $connection = eval { shift->recv };
    if (!$connection) {
        die "Connection error: $@";
    }
    say "[status] WebSocket connection established.";

    # Send the contracts for symbol request
    send_contracts_for_symbol($connection);

    # Set a timeout for receiving a response
    my $timeout = AnyEvent->timer(
        after => 10,
        cb    => sub {
            say "[error] No response received within 10 seconds. Closing connection.";
            $connection->close;
        }
    );

    # Handle incoming messages
    $connection->on(each_message => sub {
        my ($connection, $message) = @_;

        # Cancel timeout upon receiving a message
        undef $timeout;

        my $data = eval { decode_json($message->body) };
        if ($@) {
            say "[error] Failed to decode JSON: $@";
            return;
        }

        # Handle errors
        if ($data->{error}) {
            say "[error] " . $data->{error}{message};
            $connection->close;
            return;
        }

        # Process contracts_for response
        if ($data->{msg_type} && $data->{msg_type} eq 'contracts_for') {
            say "[contracts] Contracts for Symbol (R_50):";
            foreach my $contract (@{$data->{contracts_for}{available}}) {
                my $contract_type            = $contract->{contract_type} // "N/A";
                my $contract_display         = $contract->{contract_display} // "N/A";
                my $contract_category_display = $contract->{contract_category_display} // "N/A";
                my $market                   = $contract->{market} // "N/A";
                my $submarket                = $contract->{submarket} // "N/A";
                my $expiry_type              = $contract->{expiry_type} // "N/A";
                my $min_duration             = $contract->{min_contract_duration} // "N/A";
                my $max_duration             = $contract->{max_contract_duration} // "N/A";
                my $barrier                  = $contract->{barrier} // "N/A";
                my $sentiment                = $contract->{sentiment} // "N/A";

                # Print contract details
                say "  - Contract Type: $contract_type";
                say "    - Display Name: $contract_display";
                say "    - Category: $contract_category_display";
                say "    - Market: $market";
                say "    - Submarket: $submarket";
                say "    - Expiry Type: $expiry_type";
                say "    - Min Duration: $min_duration";
                say "    - Max Duration: $max_duration";
                say "    - Barrier: $barrier";
                say "    - Sentiment: $sentiment";
                say "    --------------------";
            }
            say "[contracts] End of Contracts Response.";
            $connection->close;  # Close connection after processing the response
        }
    });

    # Handle connection close
    $connection->on(finish => sub {
        say "[status] WebSocket connection closed.";
    });
});

# Start the AnyEvent event loop
AnyEvent->condvar->recv;

# Instructions to run the code on a local machine:
# 1. Ensure you have Perl installed on your machine.
# 2. Install the necessary Perl modules using the following commands:
#      cpanm AnyEvent AnyEvent::WebSocket::Client JSON
#    If `cpanm` is not installed, install it using `cpan App::cpanminus`.
# 3. Save this script to a file, e.g., `contracts_for_symbol.pl`.
# 4. Run the script using the command:
#      perl contracts_for_symbol.pl
# This script will connect to the Deriv WebSocket API, request contracts for a specific symbol, and print the details.
<?php
// Include necessary libraries (you may need to install Ratchet via Composer)
require 'vendor/autoload.php';

use Ratchet\Client\WebSocket;
use Ratchet\Client\Connector;
use React\EventLoop\Factory as LoopFactory;
use React\Socket\Connector as ReactConnector;

// Define the app_id (replace 'your_app_id' with your actual app_id)
$app_id = 'your_app_id';

// Create an event loop to handle WebSocket events
$loop = LoopFactory::create();
$reactConnector = new ReactConnector($loop);
$connector = new Connector($loop, $reactConnector);

// Define the request object for contracts_for API call
$contracts_for_symbol_request = [
    'contracts_for'   => 'R_50',  // Symbol for which contracts are requested
    'currency'        => 'USD',   // Set currency to USD
    'landing_company' => 'svg',   // Landing company
    'product_type'    => 'basic', // Product type is set to 'basic'
];

// Connect to the Deriv WebSocket API
$connector("wss://ws.derivws.com/websockets/v3?app_id=$app_id")
    ->then(function(WebSocket $conn) use ($contracts_for_symbol_request, $loop) {
        // Send the contracts_for request to the WebSocket server
        $conn->send(json_encode($contracts_for_symbol_request));
        echo "Request sent: " . json_encode($contracts_for_symbol_request) . PHP_EOL;

        // Handle messages received from the server
        $conn->on('message', function($message) use ($conn, $loop) {
            // Decode the received message (JSON format)
            $data = json_decode($message, true);

            // Check if there is an error in the response
            if (isset($data['error'])) {
                echo "Error: " . $data['error']['message'] . PHP_EOL;
                $conn->close();
                $loop->stop(); // Stop the event loop
            }

            // If the response is for 'contracts_for', print the contract information
            if (isset($data['msg_type']) && $data['msg_type'] === 'contracts_for') {
                echo "Contracts for symbol: " . json_encode($data['contracts_for'], JSON_PRETTY_PRINT) . PHP_EOL;
                $conn->close(); // Close the WebSocket connection
                $loop->stop();  // Stop the event loop
            }
        });

        // Handle WebSocket connection closing
        $conn->on('close', function($code = null, $reason = null) use ($loop) {
            echo "Connection closed ({$code} - {$reason})" . PHP_EOL;
            $loop->stop(); // Stop the event loop when the connection is closed
        });
    }, function($e) use ($loop) {
        // Handle connection errors
        echo "Could not connect: {$e->getMessage()}" . PHP_EOL;
        $loop->stop();
    });

// Run the event loop to keep the connection alive
$loop->run();

import asyncio
from deriv_api import DerivAPI

# Replace with your actual app_id
app_id = 1089

async def main():
    # Initialize the DerivAPI instance
    api = DerivAPI(app_id=app_id)

    try:
        # Send a contracts for symbol request
        contracts_for_symbol_request = {
            "contracts_for": "R_50",
            "currency": "USD",
            "landing_company": "svg",
            "product_type": "basic"
        }
        response = await api.send(contracts_for_symbol_request)
        print("Contracts for symbol request sent")

        # Process the response and print contract details
        print_contracts_for_symbol(response)

        # Function to send a ping every 30 seconds to keep the connection alive
        async def keep_alive():
            while True:
                await api.ping()  # Send a ping message
                print("Sent ping to keep connection alive")
                await asyncio.sleep(30)  # Ping every 30 seconds

        # Run the keep-alive ping loop
        await asyncio.gather(keep_alive())

    except Exception as e:
        print(f"An error occurred: {e}")

    finally:
        # Disconnect from the API
        await api.disconnect()
        print("Disconnected from Deriv API")

# Helper function to format and print contract details for a symbol
def print_contracts_for_symbol(response):
    data = response.get("contracts_for", {})
    if data:
        print("Contracts for Symbol (R_50):")
        contracts = data.get("available", [])
        for contract in contracts:
            print(f"  - Contract Type: {contract.get('contract_type')}")
            print(f"    - Display Name: {contract.get('contract_display')}")
            print(f"    - Category: {contract.get('contract_category_display')}")
            print(f"    - Market: {contract.get('market')}")
            print(f"    - Submarket: {contract.get('submarket')}")
            print(f"    - Expiry Type: {contract.get('expiry_type')}")
            print(f"    - Min Duration: {contract.get('min_contract_duration')}")
            print(f"    - Max Duration: {contract.get('max_contract_duration')}")
            print(f"    - Barrier: {contract.get('barrier')}")
            print(f"    - Sentiment: {contract.get('sentiment')}")
            print("    --------------------")
    print("[End of Contracts for Symbol Response]")

# Run the main function
if __name__ == "__main__":
    asyncio.run(main())

# Instructions to run the code:
# 1. Ensure Python is installed on your machine (https://www.python.org/downloads/).
# 2. Install the Deriv API package by running:
#      pip install deriv_api
# 3. Save this code to a file, e.g., `contracts_for_symbol_client.py`.
# 4. Run the code from the command line:
#      python contracts_for_symbol_client.py
#
# This script will connect to Deriv’s WebSocket API, request contract details for the symbol "R_50", and send pings every 30 seconds to keep the connection alive.
# The response includes important contract details such as contract type, category, market, durations, and barriers.
use tokio_tungstenite::connect_async;
use tokio_tungstenite::tungstenite::protocol::Message;
use futures_util::{SinkExt, StreamExt};
use tokio::{sync::Mutex, task::spawn};
use std::sync::Arc;
use serde_json::json;
use url::Url;

#[tokio::main]
async fn main() {
    let app_id = 1089;
    let url = format!("wss://ws.derivws.com/websockets/v3?app_id={}", app_id);
    let url = Url::parse(&url).expect("Invalid URL");

    // Connect to the WebSocket server and wrap `socket` in Arc<Mutex<_>>
    let (socket, _) = connect_async(url).await.expect("Failed to connect");
    let socket = Arc::new(Mutex::new(socket));

    println!("[status] WebSocket connection established");

    // Contracts for symbol request JSON
    let contracts_for_symbol_request = json!({
        "contracts_for": "R_50",
        "currency": "USD",
        "landing_company": "svg",
        "product_type": "basic"
    });

    // Clone `socket` to send the contracts for symbol request
    let send_socket = Arc::clone(&socket);
    let send_task = spawn(async move {
        let mut socket = send_socket.lock().await;
        if socket.send(Message::Text(contracts_for_symbol_request.to_string())).await.is_ok() {
            println!("[request] Contracts for symbol request sent.");
        }
    });

    // Task to handle incoming messages
    let receive_socket = Arc::clone(&socket);
    let receive_task = spawn(async move {
        let mut socket = receive_socket.lock().await;
        while let Some(Ok(msg)) = socket.next().await {
            match msg {
                Message::Text(text) => {
                    let data: serde_json::Value = serde_json::from_str(&text).unwrap_or_else(|_| json!({}));
                    if data.get("msg_type").unwrap_or(&json!("")) == "contracts_for" {
                        println!("Contracts for Symbol (R_50):");
                        if let Some(contracts) = data["contracts_for"]["available"].as_array() {
                            for contract in contracts {
                                println!("  - Contract Type: {}", contract["contract_type"]);
                                println!("    - Display Name: {}", contract["contract_display"]);
                                println!("    - Category: {}", contract["contract_category_display"]);
                                println!("    - Market: {}", contract["market"]);
                                println!("    - Submarket: {}", contract["submarket"]);
                                println!("    - Expiry Type: {}", contract["expiry_type"]);
                                println!("    - Min Duration: {}", contract["min_contract_duration"]);
                                println!("    - Max Duration: {}", contract["max_contract_duration"]);
                                println!("    - Barrier: {}", contract["barrier"]);
                                println!("    - Sentiment: {}", contract["sentiment"]);
                                println!("    --------------------");
                            }
                        }
                    } else if let Some(error) = data.get("error") {
                        println!("[Error] {}", error["message"]);
                    }
                }
                _ => {}
            }
        }
    });

    // Await all tasks to complete
    let _ = tokio::try_join!(send_task, receive_task);

    // Close the WebSocket connection
    let mut socket = socket.lock().await;
    socket.close(None).await.expect("Failed to close connection");
    println!("[close] Connection closed.");
}

/*
Instructions to run the code:

1. Ensure Rust and Cargo are installed on your machine. You can download them from https://www.rust-lang.org/.
2. Add the necessary dependencies to `Cargo.toml`:

   [dependencies]
   tokio = { version = "1", features = ["full"] }
   tokio-tungstenite = "0.16"
   futures-util = "0.3"
   serde_json = "1.0"
   url = "2.2"

3. Build the project:

   cargo build --release

4. Run the project:

   cargo run --release

This code will connect to the Deriv WebSocket API, request contract details for the symbol "R_50", and print out important contract details such as type, category, market, submarket, expiry type, duration, and barrier information.
*/

import Foundation

// Make webSocketTask a global variable to keep the connection open
var webSocketTask: URLSessionWebSocketTask?

// Function to create and handle WebSocket connection
func connectWebSocket() {
    let appID = 1089 // Replace with your app_id.
    let url = URL(string: "wss://ws.derivws.com/websockets/v3?app_id=\(appID)")! // WebSocket URL with the app_id
    let request = URLRequest(url: url)
    
    // Initialize webSocketTask with URLSession
    webSocketTask = URLSession.shared.webSocketTask(with: request)
    
    // Start the WebSocket connection
    webSocketTask?.resume()
    print("[status] WebSocket connection established.")
    
    // Function to send website status request
    func sendWebsiteStatusRequest() {
        let websiteStatusRequest = ["website_status": 1] as [String: Any]
        
        if let requestData = try? JSONSerialization.data(withJSONObject: websiteStatusRequest, options: []) {
            let message = URLSessionWebSocketTask.Message.data(requestData)
            webSocketTask?.send(message) { error in
                if let error = error {
                    print("[error] Failed to send website status request: \(error.localizedDescription)")
                } else {
                    print("[status] Website status request sent.")
                }
            }
        }
    }
    
    // Function to receive messages from the server
    func receiveMessage() {
        webSocketTask?.receive { result in
            switch result {
            case .success(let message):
                switch message {
                case .string(let text):
                    if let data = text.data(using: .utf8),
                       let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
                        handleServerMessage(json)
                    }
                case .data(let data):
                    print("[message] Binary data received: \(data)")
                @unknown default:
                    print("[message] Received unknown message type")
                }
                
                // Continue to receive messages
                receiveMessage()
                
            case .failure(let error):
                print("[error] Failed to receive message: \(error.localizedDescription)")
            }
        }
    }
    
    // Function to handle the website status response from server
    func handleServerMessage(_ data: [String: Any]) {
        if let error = data["error"] as? [String: Any], let message = error["message"] as? String {
            print("[Error] \(message)")
        } else if data["msg_type"] as? String == "website_status", let websiteStatus = data["website_status"] as? [String: Any] {
            let siteStatus = websiteStatus["site_status"] as? String ?? "Unknown"
            let supportedLanguages = websiteStatus["supported_languages"] as? [String] ?? []
            
            print("[Website Status] Site Status: \(siteStatus)")
            print("[Website Status] Supported Languages: \(supportedLanguages.joined(separator: ", "))")
        }
    }
    
    // Send the website status request and start receiving messages
    sendWebsiteStatusRequest()
    receiveMessage()
}

// Function to close the WebSocket connection
func closeWebSocketConnection() {
    webSocketTask?.cancel(with: .normalClosure, reason: nil)
    print("[close] Connection closed cleanly")
}

// Start WebSocket connection
connectWebSocket()

// Keep the program running to wait for messages
RunLoop.main.run()
#include <libwebsockets.h>
#include <jansson.h>  // For JSON parsing
#include <string.h>
#include <signal.h>
#include <time.h>
#include <stdlib.h>

// Set up WebSocket context and connection details
static struct lws_context *context;
static int interrupted = 0, port = 443, ssl_connection = LCCSCF_USE_SSL;
static const char *server_address = "ws.derivws.com";
static const char *path = "/websockets/v3?app_id=1089";
static const char *pro = "lws-minimal-client";

// Interval for the ping in seconds
static const int ping_interval = 30;
static time_t last_ping_time = 0;

// Buffer to accumulate received message fragments
static char message_buffer[16384];
static size_t message_length = 0;

// Signal handler for graceful shutdown
static void sigint_handler(int sig) {
    interrupted = 1;
}

// Function to send a ping message
void send_ping(struct lws *wsi) {
    const char *ping_msg = "{\"ping\": 1}";
    unsigned char buf[LWS_PRE + 20];
    memcpy(&buf[LWS_PRE], ping_msg, strlen(ping_msg));
    lws_write(wsi, &buf[LWS_PRE], strlen(ping_msg), LWS_WRITE_TEXT);
    lwsl_user("Ping sent\n");
}

// Function to send a contracts for symbol request
void send_contracts_for_symbol_request(struct lws *wsi) {
    const char *contracts_for_symbol_msg = "{\"contracts_for\": \"R_50\", \"currency\": \"USD\", \"landing_company\": \"svg\", \"product_type\": \"basic\"}";
    unsigned char buf[LWS_PRE + 256];
    memcpy(&buf[LWS_PRE], contracts_for_symbol_msg, strlen(contracts_for_symbol_msg));
    lws_write(wsi, &buf[LWS_PRE], strlen(contracts_for_symbol_msg), LWS_WRITE_TEXT);
    lwsl_user("Contracts for symbol request sent\n");
}

// Function to check if JSON is complete based on braces balance
int is_json_complete(const char *json) {
    int brace_count = 0;
    for (size_t i = 0; json[i] != '\0'; i++) {
        if (json[i] == '{') brace_count++;
        else if (json[i] == '}') brace_count--;
    }
    return brace_count == 0;
}

// Function to handle the JSON response once fully received
static void handle_contracts_for_response(const char *response) {
    json_t *root;
    json_error_t error;

    // Parse the JSON response
    root = json_loads(response, 0, &error);
    if (!root) {
        printf("Error parsing JSON: %s at line %d, column %d\n", error.text, error.line, error.column);
        return;
    }

    // Check if the response contains an error
    json_t *error_obj = json_object_get(root, "error");
    if (error_obj) {
        const char *error_message = json_string_value(json_object_get(error_obj, "message"));
        printf("Error: %s\n", error_message);
        json_decref(root);
        return;
    }

    // Check if the message type is "contracts_for"
    const char *msg_type = json_string_value(json_object_get(root, "msg_type"));
    if (msg_type && strcmp(msg_type, "contracts_for") == 0) {
        json_t *contracts_for = json_object_get(root, "contracts_for");
        json_t *available_contracts = json_object_get(contracts_for, "available");

        printf("Contracts for Symbol (R_50):\n");
        size_t index;
        json_t *contract;
        json_array_foreach(available_contracts, index, contract) {
            const char *contract_type = json_string_value(json_object_get(contract, "contract_type"));
            const char *display_name = json_string_value(json_object_get(contract, "contract_display"));
            const char *category = json_string_value(json_object_get(contract, "contract_category_display"));
            const char *market = json_string_value(json_object_get(contract, "market"));
            const char *submarket = json_string_value(json_object_get(contract, "submarket"));
            const char *expiry_type = json_string_value(json_object_get(contract, "expiry_type"));
            const char *min_duration = json_string_value(json_object_get(contract, "min_contract_duration"));
            const char *max_duration = json_string_value(json_object_get(contract, "max_contract_duration"));

            printf("  - Contract Type: %s\n", contract_type);
            printf("    - Display Name: %s\n", display_name);
            printf("    - Category: %s\n", category);
            printf("    - Market: %s\n", market);
            printf("    - Submarket: %s\n", submarket);
            printf("    - Expiry Type: %s\n", expiry_type);
            printf("    - Min Duration: %s\n", min_duration);
            printf("    - Max Duration: %s\n", max_duration);
            printf("    --------------------\n");
        }
    }

    json_decref(root);
}

// Callback function for WebSocket events
static int callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,
                            void *user, void *in, size_t len) {
    switch (reason) {
    case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
        lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)");
        interrupted = 1;
        break;

    case LWS_CALLBACK_CLIENT_ESTABLISHED:
        lwsl_user("Connection established\n");
        send_contracts_for_symbol_request(wsi);  // Send contracts for symbol request on connection
        lws_callback_on_writable(wsi); // Request writable callback
        break;

    case LWS_CALLBACK_CLIENT_WRITEABLE:
        if (time(NULL) - last_ping_time >= ping_interval) {
            send_ping(wsi);  // Send periodic ping
            last_ping_time = time(NULL);
            send_contracts_for_symbol_request(wsi);  // Periodically request contracts
        }
        break;

    case LWS_CALLBACK_CLIENT_RECEIVE:
        // Accumulate incoming message chunks into the buffer
        if (message_length + len < sizeof(message_buffer) - 1) {
            memcpy(&message_buffer[message_length], in, len);
            message_length += len;
            message_buffer[message_length] = '\0';  // Null-terminate

            // Check if we have a complete JSON message
            if (is_json_complete(message_buffer)) {
                printf("Received complete JSON message: %s\n", message_buffer);
                handle_contracts_for_response(message_buffer); // Process JSON response
                message_length = 0;  // Reset the buffer after parsing
            }
        } else {
            printf("Warning: Message buffer overflow. Clearing buffer.\n");
            message_length = 0;  // Clear the buffer on overflow
        }
        break;

    case LWS_CALLBACK_CLIENT_CLOSED:
        lwsl_user("Connection closed\n");
        interrupted = 1;
        break;

    default:
        break;
    }

    return 0;
}

// Define supported protocols for the WebSocket
static const struct lws_protocols protocols[] = {
    { "lws-minimal-client", callback_minimal, 0, 0, 0, NULL, 0 },
    LWS_PROTOCOL_LIST_TERM
};

// Main function to set up and manage the WebSocket client
int main(int argc, const char **argv) {
    struct lws_context_creation_info info;
    struct lws_client_connect_info i;

    // Handle Ctrl+C interrupt for graceful shutdown
    signal(SIGINT, sigint_handler);
    memset(&info, 0, sizeof info);
    memset(&i, 0, sizeof(i));

    lwsl_user("Initializing Deriv WebSocket client...\n");

    info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
    info.port = CONTEXT_PORT_NO_LISTEN;
    info.protocols = protocols;
    info.fd_limit_per_thread = 1 + 1 + 1;

    context = lws_create_context(&info);
    if (!context) {
        lwsl_err("lws init failed\n");
        return 1;
    }

    i.context = context;
    i.port = port;
    i.address = server_address;
    i.path = path;
    i.host = i.address;
    i.origin = i.address;
    i.ssl_connection = ssl_connection;
    i.protocol = pro;
    i.local_protocol_name = "lws-minimal-client";

    if (!lws_client_connect_via_info(&i)) {
        lwsl_err("Failed to initiate connection\n");
        return 1;
    }

    // Run the WebSocket client event loop
    while (!interrupted)
        lws_service(context, 0);

    lws_context_destroy(context);
    lwsl_user("WebSocket client terminated.\n");

    return 0;
}

/*
 * Instructions:
 * 1. Install the required libraries if they are not already installed:
 *    - On Ubuntu:
 *        sudo apt-get install libwebsockets-dev libjansson-dev
 *    - On macOS:
 *        brew install libwebsockets jansson
 * 2. Compile the code using the following command:
 *      gcc -o connect connect.c -lwebsockets -ljansson -lssl -lcrypto -lm
 * 3. Run the compiled executable:
 *      ./connect
 * 4. Ensure you have internet connectivity as the WebSocket will attempt to connect to `ws.derivws.com`.
 * 5. Replace "app_id=1089" in the `path` variable with your actual app_id if required.
using System;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

class WebSocketExample
{
    private static readonly Uri uri = new Uri("wss://ws.derivws.com/websockets/v3?app_id=1089"); // Replace with your app_id if needed

    public static async Task Main(string[] args)
    {
        using (ClientWebSocket webSocket = new ClientWebSocket())
        {
            Console.WriteLine("Attempting to connect to WebSocket...");

            await webSocket.ConnectAsync(uri, CancellationToken.None);
            Console.WriteLine("[status] WebSocket connection established.");

            // Send contracts for symbol request
            await SendContractsForSymbolRequest(webSocket);

            // Handle responses from the server
            await HandleResponses(webSocket);
        }
    }

    private static async Task SendContractsForSymbolRequest(ClientWebSocket webSocket)
    {
        var contractsForSymbolRequest = new
        {
            contracts_for = "R_50",
            currency = "USD",
            landing_company = "svg",
            product_type = "basic"
        };

        string requestJson = JsonSerializer.Serialize(contractsForSymbolRequest);
        var bytes = Encoding.UTF8.GetBytes(requestJson);
        await webSocket.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, CancellationToken.None);
        Console.WriteLine("[request] Contracts for symbol request sent.");
    }

private static async Task HandleResponses(ClientWebSocket webSocket)
{
    var buffer = new byte[8192];
    var messageBuilder = new StringBuilder();

    while (webSocket.State == WebSocketState.Open)
    {
        var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

        if (result.MessageType == WebSocketMessageType.Close)
        {
            Console.WriteLine("WebSocket connection closed by server.");
            await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
            break;
        }

        messageBuilder.Append(Encoding.UTF8.GetString(buffer, 0, result.Count));

        if (result.EndOfMessage)
        {
            try
            {
                var data = JsonDocument.Parse(messageBuilder.ToString()).RootElement;
                if (data.TryGetProperty("error", out var error))
                {
                    Console.WriteLine($"[Error] {error.GetProperty("message").GetString()}");
                    await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing due to error", CancellationToken.None);
                    break;
                }

                if (data.TryGetProperty("msg_type", out var msgType) && msgType.GetString() == "contracts_for")
                {
                    Console.WriteLine("Contracts for Symbol (R_50):");
                    foreach (var contract in data.GetProperty("contracts_for").GetProperty("available").EnumerateArray())
                    {
                        Console.WriteLine($"  - Contract Type: {contract.GetProperty("contract_type").GetString()}");
                        Console.WriteLine($"    - Display Name: {contract.GetProperty("contract_display").GetString()}");
                        Console.WriteLine($"    - Category: {contract.GetProperty("contract_category_display").GetString()}");
                        Console.WriteLine($"    - Market: {contract.GetProperty("market").GetString()}");
                        Console.WriteLine($"    - Submarket: {contract.GetProperty("submarket").GetString()}");
                        Console.WriteLine($"    - Expiry Type: {contract.GetProperty("expiry_type").GetString()}");

                        // Check for optional properties with safe access
                        Console.WriteLine($"    - Min Duration: {(contract.TryGetProperty("min_contract_duration", out var minDuration) ? minDuration.GetString() : "N/A")}");
                        Console.WriteLine($"    - Max Duration: {(contract.TryGetProperty("max_contract_duration", out var maxDuration) ? maxDuration.GetString() : "N/A")}");
                        Console.WriteLine($"    - Barrier: {(contract.TryGetProperty("barrier", out var barrier) ? barrier.GetString() : "N/A")}");
                        Console.WriteLine($"    - Sentiment: {(contract.TryGetProperty("sentiment", out var sentiment) ? sentiment.GetString() : "N/A")}");
                        Console.WriteLine("    --------------------");
                    }
                }

                messageBuilder.Clear();
            }
            catch (JsonException ex)
            {
                Console.WriteLine($"[Error] Failed to parse JSON message: {ex.Message}");
            }
        }
    }
}


}

/*
Instructions to run the code locally:

1. Ensure you have .NET SDK installed. You can download it from https://dotnet.microsoft.com/download.

2. Save the code to a file named `WebSocketExample.cs`.

3. Open a terminal in the directory containing `WebSocketExample.cs`.

4. If using the .NET CLI, you can run the code with:
   - `dotnet new console -o WebSocketExample` (if creating a new project)
   - Move `WebSocketExample.cs` into the project directory `WebSocketExample`.
   - Navigate to the project directory: `cd WebSocketExample`.
   - Run `dotnet add package System.Net.WebSockets.Client` to add the WebSocket client dependency.
   - Run the code: `dotnet run`.

5. Alternatively, you can use an IDE like Visual Studio to create a console application, add the `System.Net.WebSockets.Client` package, and then run the application.

6. Replace `app_id=1089` in the URL with your actual app_id if needed.
*/
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"nhooyr.io/websocket"
	"nhooyr.io/websocket/wsjson"
)

const (
	webSocketURL = "wss://ws.derivws.com/websockets/v3?app_id=1089"
	readLimit    = 65536 // Set a higher read limit, e.g., 64 KB
)

type ContractsForRequest struct {
	ContractsFor   string `json:"contracts_for"`
	Currency       string `json:"currency"`
	LandingCompany string `json:"landing_company"`
	ProductType    string `json:"product_type"`
}

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// Establish WebSocket connection
	conn, _, err := websocket.Dial(ctx, webSocketURL, nil)
	if err != nil {
		log.Fatalf("Failed to connect to WebSocket: %v", err)
	}
	defer conn.Close(websocket.StatusNormalClosure, "normal closure")
	fmt.Println("[status] WebSocket connection established.")

	// Set a higher read limit
	conn.SetReadLimit(readLimit)

	// Send contracts for symbol request
	err = sendContractsForSymbolRequest(ctx, conn)
	if err != nil {
		log.Fatalf("Failed to send contracts for symbol request: %v", err)
	}

	// Handle incoming messages
	handleResponses(ctx, conn)
}

func sendContractsForSymbolRequest(ctx context.Context, conn *websocket.Conn) error {
	contractsRequest := ContractsForRequest{
		ContractsFor:   "R_50",
		Currency:       "USD",
		LandingCompany: "svg",
		ProductType:    "basic",
	}
	fmt.Println("[request] Sending contracts for symbol request...")
	return wsjson.Write(ctx, conn, contractsRequest)
}

func handleResponses(ctx context.Context, conn *websocket.Conn) {
	for {
		var response map[string]interface{}

		err := wsjson.Read(ctx, conn, &response)
		if err != nil {
			log.Fatalf("Error reading message: %v", err)
		}

		msgType := response["msg_type"]
		if msgType == "contracts_for" {
			contracts := response["contracts_for"].(map[string]interface{})["available"].([]interface{})
			fmt.Println("Contracts for Symbol (R_50):")
			for _, contract := range contracts {
				contractMap := contract.(map[string]interface{})
				fmt.Printf("  - Contract Type: %v\n", contractMap["contract_type"])
				fmt.Printf("    - Display Name: %v\n", contractMap["contract_display"])
				fmt.Printf("    - Category: %v\n", contractMap["contract_category_display"])
				fmt.Printf("    - Market: %v\n", contractMap["market"])
				fmt.Printf("    - Submarket: %v\n", contractMap["submarket"])
				fmt.Printf("    - Expiry Type: %v\n", contractMap["expiry_type"])
				fmt.Printf("    - Min Duration: %v\n", contractMap["min_contract_duration"])
				fmt.Printf("    - Max Duration: %v\n", contractMap["max_contract_duration"])
				fmt.Printf("    - Barrier: %v\n", contractMap["barrier"])
				fmt.Printf("    - Sentiment: %v\n", contractMap["sentiment"])
				fmt.Println("    --------------------")
			}
		} else {
			fmt.Printf("Received message: %v\n", response)
		}
	}
}