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:
- Import Deriv API: Import the
DerivAPIBasic
library from Skypack CDN. - WebSocket connection: Create a WebSocket connection to the Deriv API using your
app_id
. - API initialization: Initialize the
DerivAPIBasic
instance with the WebSocket connection. - Request object: Define a request object to fetch contracts for a specific symbol (e.g.,
R_50
). - Response handling: Handle the API response:
- Parse the data and log any errors.
- If the response contains contract data, log it.
- Remove the event listener after the response is received.
- 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)
}
}
}
Updated 11 days ago