Keep connection live
Follow these steps to maintain a live WebSocket connection with the Deriv API:
Import the Deriv API library
Import the DerivAPIBasic
library, which provides an interface to interact with the Deriv WebSocket API:
import DerivAPIBasic from 'https://cdn.skypack.dev/@deriv/deriv-api/dist/DerivAPIBasic';
Establish a WebSocket connection
Create a WebSocket connection using your app_id
and the API URL:
(
wss://ws.derivws.com/websockets/v3?app_id=${app_id}
).
This connection will be used to send and receive messages from the Deriv API.
const connection = new WebSocket(
wss://ws.derivws.com/websockets/v3?app_id=${app_id});
Create an API object
Create an instance of DerivAPIBasic
, passing the WebSocket connection as a parameter.
This object interacts with the API, such as subscribing to proposals and sending pings.
const api = new DerivAPIBasic({ connection });
Send a proposal subscription
The proposal()
function subscribes to a proposal and sends details such as the trade amount, currency, contract type, duration, and asset symbol.
After this subscription, the API will send real-time updates about the proposal (market data).
const proposal = () => {
api.subscribe({
proposal: 1,
subscribe: 1,
amount: 10,
basis: 'payout',
contract_type: 'CALL',
currency: 'USD',
duration: 1,
duration_unit: 'm',
symbol: 'R_100',
barrier: '+0.1',
});
};
Send ping to keep the connection alive
The ping()
function sends a "ping
" message every 30 seconds using setInterval
.
This ensures that the WebSocket connection remains active, as WebSocket servers may close idle connections.
const ping = () => {
setInterval(() => {
api.ping();
}, 30000);
};
Handle WebSocket responses
The wsResponse()
function processes incoming WebSocket messages and handles:
- Errors: Logs errors and disconnects the WebSocket if an error is received.
- Proposal Messages: Logs proposal details (e.g., ask price, payout).
- Ping Messages: Logs ping responses from the server.
const wsResponse = async (res) => {
const data = JSON.parse(res.data);
if (data.error !== undefined) {
console.log('Error: %s ', data.error.message);
connection.removeEventListener('message', wsResponse, false);
await api.disconnect();
} else if (data.msg_type === 'proposal') {
console.log('Details: %s', data.proposal.longcode);
console.log('Ask Price: %s', data.proposal.display_value);
console.log('Payout: %f', data.proposal.payout);
console.log('Spot: %f', data.proposal.spot);
} else if (data.msg_type === 'ping') {
console.log('ping');
}
};
Start the signal processing
The checkSignal()
function starts the signal processing by:
proposal()
: Subscribes to market data.ping()
: Starts sending pings.connection.addEventListener('message', wsResponse)
: Listens for messages from the WebSocket server and processing them usingwsResponse()
.
const checkSignal = () => {
proposal();
ping();
connection.addEventListener('message', wsResponse);
};
End the WebSocket subscription
The endCall()
function stops receiving proposal updates by:
- Removing the WebSocket message listener.
- Calling
unsubscribe()
on theproposal()
to stop the subscription.
const endCall = () => {
connection.removeEventListener('message', wsResponse, false);
proposal().unsubscribe();
};
These steps outline how the code works to establish a WebSocket connection, subscribe to proposals, keep the connection alive with pings, handle responses, and eventually unsubscribe from the proposals.
import DerivAPIBasic from 'https://cdn.skypack.dev/@deriv/deriv-api/dist/DerivAPIBasic';
const app_id = app_id; // Replace with your app_id.
const connection = new WebSocket(`wss://ws.derivws.com/websockets/v3?app_id=${app_id}`);
const api = new DerivAPIBasic({ connection });
const proposal = () => {
api.subscribe({
proposal: 1,
subscribe: 1,
amount: 10,
basis: 'payout',
contract_type: 'CALL',
currency: 'USD',
duration: 1,
duration_unit: 'm',
symbol: 'R_100',
barrier: '+0.1',
});
};
// Send a ping every 30 seconds to keep the connection alive
// Needs to use the same websocket connection as the one you want to maintain.
const ping = () => {
setInterval(() => {
api.ping();
}, 30000);
};
const wsResponse = async (res) => {
const data = JSON.parse(res.data);
if (data.error !== undefined) {
console.log('Error: %s ', data.error.message);
connection.removeEventListener('message', wsResponse, false);
await api.disconnect();
} else if (data.msg_type === 'proposal') {
console.log('Details: %s', data.proposal.longcode);
console.log('Ask Price: %s', data.proposal.display_value);
console.log('Payout: %f', data.proposal.payout);
console.log('Spot: %f', data.proposal.spot);
} else if (data.msg_type === 'ping') {
console.log('ping');
}
};
const checkSignal = () => {
proposal();
ping();
connection.addEventListener('message', wsResponse);
};
const endCall = () => {
connection.removeEventListener('message', wsResponse, false);
proposal().unsubscribe();
};
const keep_alive_button = document.querySelector('#keep_alive');
keep_alive_button.addEventListener('click', checkSignal);
const end_call_button = document.querySelector('#end_call');
end_call_button.addEventListener('click', endCall);
import json
import asyncio
import websockets
from deriv_api import DerivAPIBasic # Assuming you have DerivAPIBasic installed or available.
# Replace with your app_id.
app_id = 'your_app_id'
connection_url = f'wss://ws.derivws.com/websockets/v3?app_id={app_id}'
# Initialize the WebSocket connection
async def connect_to_deriv():
async with websockets.connect(connection_url) as websocket:
api = DerivAPIBasic(websocket) # Create Deriv API object using the websocket connection
# Function to send a proposal subscription request to the API
async def proposal():
await api.subscribe({
"proposal": 1,
"subscribe": 1,
"amount": 10,
"basis": "payout",
"contract_type": "CALL",
"currency": "USD",
"duration": 1,
"duration_unit": "m",
"symbol": "R_100",
"barrier": "+0.1"
})
# Function to send a ping every 30 seconds to keep the connection alive
async def ping():
while True:
await api.ping() # Send a ping
await asyncio.sleep(30) # Wait for 30 seconds before sending the next ping
# Function to handle WebSocket responses
async def ws_response(response):
data = json.loads(response)
if "error" in data:
print(f"Error: {data['error']['message']}")
await api.disconnect() # Disconnect if there's an error
elif data["msg_type"] == "proposal":
# Print proposal details if received
print(f"Details: {data['proposal']['longcode']}")
print(f"Ask Price: {data['proposal']['display_value']}")
print(f"Payout: {data['proposal']['payout']}")
print(f"Spot: {data['proposal']['spot']}")
elif data["msg_type"] == "ping":
print("ping")
# Function to manage the signal check and ping
async def check_signal():
await proposal() # Subscribe to proposal
asyncio.create_task(ping()) # Start the ping loop
async for message in websocket:
await ws_response(message) # Handle each WebSocket message
# Function to end the call
async def end_call():
await api.unsubscribe() # Unsubscribe from the proposal
await websocket.close() # Close the WebSocket connection
await check_signal() # Start the signal checking process
# Start the WebSocket connection
asyncio.get_event_loop().run_until_complete(connect_to_deriv())
use strict;
use warnings;
use IO::Socket::SSL;
use Protocol::WebSocket::Client;
use JSON;
use AnyEvent;
# Replace with your app_id
my $app_id = 'your_app_id';
my $connection_url = "wss://ws.derivws.com/websockets/v3?app_id=$app_id";
# Create a WebSocket client
my $client = Protocol::WebSocket::Client->new(url => $connection_url);
# Initialize the AnyEvent loop to handle asynchronous operations
my $cv = AnyEvent->condvar;
# WebSocket connection setup
$client->on(connect => sub {
print "Connected to Deriv API\n";
# Send the proposal subscription
proposal();
# Set up a ping interval every 30 seconds to keep the connection alive
my $ping_watcher = AnyEvent->timer(
after => 0,
interval => 30,
cb => sub {
ping();
}
);
});
# WebSocket message handler
$client->on(read => sub {
my ($client, $message) = @_;
ws_response($message);
});
# Error handling
$client->on(error => sub {
my ($client, $error) = @_;
print "Error: $error\n";
$client->disconnect();
});
# Close WebSocket on disconnect
$client->on(finish => sub {
print "Connection closed\n";
$cv->send;
});
# Function to send the proposal subscription request
sub proposal {
my $message = encode_json({
proposal => 1,
subscribe => 1,
amount => 10,
basis => 'payout',
contract_type => 'CALL',
currency => 'USD',
duration => 1,
duration_unit => 'm',
symbol => 'R_100',
barrier => '+0.1'
});
$client->write($message);
}
# Function to send a ping request to keep the connection alive
sub ping {
my $message = encode_json({
ping => 1
});
$client->write($message);
print "Ping sent\n";
}
# Function to handle WebSocket responses
sub ws_response {
my ($message) = @_;
my $data = decode_json($message);
if (exists $data->{error}) {
print "Error: $data->{error}->{message}\n";
$client->disconnect();
} elsif ($data->{msg_type} eq 'proposal') {
# Print proposal details if received
print "Details: $data->{proposal}->{longcode}\n";
print "Ask Price: $data->{proposal}->{display_value}\n";
print "Payout: $data->{proposal}->{payout}\n";
print "Spot: $data->{proposal}->{spot}\n";
} elsif ($data->{msg_type} eq 'ping') {
print "Ping response received\n";
}
}
# Function to unsubscribe from the proposal and close connection
sub end_call {
my $message = encode_json({ unsubscribe => 1 });
$client->write($message);
$client->disconnect();
}
# Start WebSocket connection
$client->connect;
# Wait for the connection to finish
$cv->recv;
import Foundation
// Define the app_id for Deriv API
let app_id = "your_app_id"
let connectionUrl = URL(string: "wss://ws.derivws.com/websockets/v3?app_id=\(app_id)")!
// WebSocket delegate class to handle WebSocket events
class WebSocketDelegate: NSObject, URLSessionWebSocketDelegate {
var webSocketTask: URLSessionWebSocketTask?
// Function to initiate a WebSocket connection
func connectToDeriv() {
let session = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())
webSocketTask = session.webSocketTask(with: connectionUrl)
webSocketTask?.resume()
// Subscribe to the proposal and start sending pings
subscribeToProposal()
sendPingPeriodically()
receiveMessage() // Start receiving messages
}
// Function to subscribe to the proposal
func subscribeToProposal() {
let proposalRequest: [String: Any] = [
"proposal": 1,
"subscribe": 1,
"amount": 10,
"basis": "payout",
"contract_type": "CALL",
"currency": "USD",
"duration": 1,
"duration_unit": "m",
"symbol": "R_100",
"barrier": "+0.1"
]
send(jsonData: proposalRequest)
}
// Function to send a ping every 30 seconds to keep the connection alive
func sendPingPeriodically() {
Timer.scheduledTimer(withTimeInterval: 30, repeats: true) { _ in
self.sendPing()
}
}
// Function to send a ping message
func sendPing() {
let pingMessage: [String: Any] = ["ping": 1]
send(jsonData: pingMessage)
print("Ping sent")
}
// Function to send a message (JSON format) through the WebSocket
func send(jsonData: [String: Any]) {
do {
let data = try JSONSerialization.data(withJSONObject: jsonData, options: [])
let jsonString = String(data: data, encoding: .utf8) ?? ""
let message = URLSessionWebSocketTask.Message.string(jsonString)
webSocketTask?.send(message) { error in
if let error = error {
print("WebSocket sending error: \(error)")
}
}
} catch {
print("JSON serialization error: \(error)")
}
}
// Function to receive messages from the WebSocket
func receiveMessage() {
webSocketTask?.receive { [weak self] result in
switch result {
case .failure(let error):
print("WebSocket receiving error: \(error)")
case .success(let message):
switch message {
case .string(let text):
self?.handleMessage(text: text)
default:
break
}
self?.receiveMessage() // Continue listening for more messages
}
}
}
// Function to handle incoming messages from the WebSocket
func handleMessage(text: String) {
guard let data = text.data(using: .utf8),
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
print("Invalid message received")
return
}
if let error = json["error"] as? [String: Any] {
print("Error: \(error["message"] ?? "Unknown error")")
disconnect()
} else if let msgType = json["msg_type"] as? String, msgType == "proposal" {
if let proposal = json["proposal"] as? [String: Any] {
print("Details: \(proposal["longcode"] ?? "")")
print("Ask Price: \(proposal["display_value"] ?? "")")
print("Payout: \(proposal["payout"] ?? "")")
print("Spot: \(proposal["spot"] ?? "")")
}
} else if let msgType = json["msg_type"] as? String, msgType == "ping" {
print("Ping response received")
}
}
// Function to disconnect the WebSocket
func disconnect() {
webSocketTask?.cancel(with: .goingAway, reason: nil)
}
}
// Create an instance of WebSocketDelegate and connect
let webSocketDelegate = WebSocketDelegate()
webSocketDelegate.connectToDeriv()
// Keep the run loop alive to keep the WebSocket connection active
RunLoop.main.run()
use futures_util::{StreamExt, SinkExt};
use serde_json::json;
use std::time::Duration;
use tokio::time;
use tokio_tungstenite::{connect_async, tungstenite::protocol::Message};
use url::Url;
// The app_id for the Deriv API
const APP_ID: &str = "your_app_id";
const WS_URL: &str = "wss://ws.derivws.com/websockets/v3";
#[tokio::main]
async fn main() {
// Establish WebSocket connection
let url = format!("{}?app_id={}", WS_URL, APP_ID);
let (mut ws_stream, _) = connect_async(Url::parse(&url).unwrap()).await.expect("Failed to connect");
println!("Connected to Deriv API");
// Subscribe to proposal and send pings periodically
tokio::spawn(send_proposal(&mut ws_stream));
tokio::spawn(send_ping_periodically(&mut ws_stream));
// Handle incoming WebSocket messages
while let Some(message) = ws_stream.next().await {
match message {
Ok(Message::Text(text)) => handle_message(text).await,
Ok(_) => (),
Err(e) => {
println!("Error receiving message: {}", e);
break;
}
}
}
println!("Connection closed");
}
// Function to send a proposal subscription request
async fn send_proposal(ws_stream: &mut tokio_tungstenite::WebSocketStream<tokio::net::TcpStream>) {
let proposal_request = json!({
"proposal": 1,
"subscribe": 1,
"amount": 10,
"basis": "payout",
"contract_type": "CALL",
"currency": "USD",
"duration": 1,
"duration_unit": "m",
"symbol": "R_100",
"barrier": "+0.1"
});
let request_text = proposal_request.to_string();
ws_stream.send(Message::Text(request_text)).await.expect("Failed to send proposal request");
println!("Proposal request sent");
}
// Function to send a ping every 30 seconds to keep the connection alive
async fn send_ping_periodically(ws_stream: &mut tokio_tungstenite::WebSocketStream<tokio::net::TcpStream>) {
let ping_message = json!({
"ping": 1
});
loop {
ws_stream.send(Message::Text(ping_message.to_string())).await.expect("Failed to send ping");
println!("Ping sent");
time::sleep(Duration::from_secs(30)).await; // Wait for 30 seconds before sending the next ping
}
}
// Function to handle incoming WebSocket messages
async fn handle_message(message: String) {
let data: serde_json::Value = serde_json::from_str(&message).unwrap();
if let Some(error) = data.get("error") {
println!("Error: {}", error["message"]);
} else if let Some(proposal) = data.get("proposal") {
println!("Details: {}", proposal["longcode"]);
println!("Ask Price: {}", proposal["display_value"]);
println!("Payout: {}", proposal["payout"]);
println!("Spot: {}", proposal["spot"]);
} else if data.get("msg_type") == Some(&serde_json::Value::String("ping".to_string())) {
println!("Ping response received");
}
}
//[dependencies]
//tokio = { version = "1", features = ["full"] }
//tokio-tungstenite = "0.16"
//tungstenite = "0.16"
//serde_json = "1.0"
//futures-util = "0.3"
//url = "2.2"
<?php
// Set the app_id for Deriv API
$app_id = 'your_app_id';
$connection_url = "wss://ws.derivws.com/websockets/v3?app_id=$app_id";
// Function to establish WebSocket connection
function connect_to_deriv() {
global $connection_url;
// Create a WebSocket connection using the Ratchet library
$client = new WebSocket\Client($connection_url);
// Send the proposal request
proposal($client);
// Set up the ping to keep the connection alive every 30 seconds
ping($client);
// Handle incoming messages from the WebSocket
while ($message = $client->receive()) {
ws_response($client, $message);
}
// Close the connection
$client->close();
}
// Function to send the proposal subscription request
function proposal($client) {
$request = [
"proposal" => 1,
"subscribe" => 1,
"amount" => 10,
"basis" => "payout",
"contract_type" => "CALL",
"currency" => "USD",
"duration" => 1,
"duration_unit" => "m",
"symbol" => "R_100",
"barrier" => "+0.1"
];
// Send the subscription request to the WebSocket
$client->send(json_encode($request));
}
// Function to send a ping request every 30 seconds to keep the connection alive
function ping($client) {
$ping_interval = 30;
// Start an infinite loop
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.net.http.WebSocket.Listener;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import org.json.JSONObject;
public class DerivWebSocketClient {
// Define your app_id for Deriv API
private static final String APP_ID = "your_app_id";
private static final String WS_URL = "wss://ws.derivws.com/websockets/v3?app_id=" + APP_ID;
private WebSocket webSocket;
public static void main(String[] args) {
DerivWebSocketClient client = new DerivWebSocketClient();
client.connectToDeriv();
}
// Function to establish a WebSocket connection
public void connectToDeriv() {
HttpClient client = HttpClient.newHttpClient();
webSocket = client.newWebSocketBuilder()
.buildAsync(URI.create(WS_URL), new DerivWebSocketListener())
.join();
// Subscribe to the proposal
subscribeToProposal();
// Schedule a ping every 30 seconds
schedulePing();
}
// Function to send a proposal subscription request
private void subscribeToProposal() {
JSONObject proposalRequest = new JSONObject();
proposalRequest.put("proposal", 1);
proposalRequest.put("subscribe", 1);
proposalRequest.put("amount", 10);
proposalRequest.put("basis", "payout");
proposalRequest.put("contract_type", "CALL");
proposalRequest.put("currency", "USD");
proposalRequest.put("duration", 1);
proposalRequest.put("duration_unit", "m");
proposalRequest.put("symbol", "R_100");
proposalRequest.put("barrier", "+0.1");
webSocket.sendText(proposalRequest.toString(), true);
System.out.println("Proposal subscription sent");
}
// Function to send a ping message every 30 seconds to keep the connection alive
private void schedulePing() {
Runnable pingTask = () -> {
JSONObject pingMessage = new JSONObject();
pingMessage.put("ping", 1);
webSocket.sendText(pingMessage.toString(), true);
System.out.println("Ping sent");
};
// Schedule ping task to run every 30 seconds
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(pingTask, 0, 30, TimeUnit.SECONDS);
}
// Listener class to handle WebSocket events
private static class DerivWebSocketListener implements Listener {
@Override
public void onOpen(WebSocket webSocket) {
System.out.println("WebSocket opened");
Listener.super.onOpen(webSocket);
}
@Override
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
handleMessage(data.toString());
return Listener.super.onText(webSocket, data, last);
}
@Override
public void onError(WebSocket webSocket, Throwable error) {
System.out.println("Error occurred: " + error.getMessage());
Listener.super.onError(webSocket, error);
}
@Override
public CompletionStage<?> onClose(WebSocket webSocket, int statusCode, String reason) {
System.out.println("WebSocket closed: " + reason);
return Listener.super.onClose(webSocket, statusCode, reason);
}
// Function to handle incoming WebSocket messages
private void handleMessage(String message) {
JSONObject json = new JSONObject(message);
if (json.has("error")) {
System.out.println("Error: " + json.getJSONObject("error").getString("message"));
} else if (json.has("proposal")) {
JSONObject proposal = json.getJSONObject("proposal");
System.out.println("Details: " + proposal.getString("longcode"));
System.out.println("Ask Price: " + proposal.getString("display_value"));
System.out.println("Payout: " + proposal.getDouble("payout"));
System.out.println("Spot: " + proposal.getDouble("spot"));
} else if ("ping".equals(json.optString("msg_type"))) {
System.out.println("Ping response received");
}
}
}
}
package main
import (
"encoding/json"
"fmt"
"log"
"net/url"
"os"
"os/signal"
"time"
"github.com/gorilla/websocket"
)
// Constants for WebSocket connection and app ID
const appID = "your_app_id"
const wsURL = "wss://ws.derivws.com/websockets/v3"
// Struct for WebSocket messages (proposal request and ping)
type ProposalRequest struct {
Proposal int `json:"proposal"`
Subscribe int `json:"subscribe"`
Amount int `json:"amount"`
Basis string `json:"basis"`
ContractType string `json:"contract_type"`
Currency string `json:"currency"`
Duration int `json:"duration"`
DurationUnit string `json:"duration_unit"`
Symbol string `json:"symbol"`
Barrier string `json:"barrier"`
}
type PingMessage struct {
Ping int `json:"ping"`
}
func main() {
// Parse the WebSocket URL
u := url.URL{Scheme: "wss", Host: "ws.derivws.com", Path: "/websockets/v3", RawQuery: "app_id=" + appID}
log.Printf("Connecting to %s", u.String())
// Establish WebSocket connection
conn, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
log.Fatal("Error while connecting to WebSocket:", err)
}
defer conn.Close()
// Channel to listen for interruptions
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)
// Send a proposal subscription
go sendProposal(conn)
// Send ping every 30 seconds
go sendPing(conn)
// Handle incoming WebSocket messages
go func() {
for {
_, message, err := conn.ReadMessage()
if err != nil {
log.Println("Error reading WebSocket message:", err)
return
}
handleMessage(message)
}
}()
// Wait for interrupt signal to gracefully shut down
<-interrupt
log.Println("Interrupt received, closing connection")
err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
log.Println("Error closing WebSocket connection:", err)
}
}
// Function to send a proposal subscription request
func sendProposal(conn *websocket.Conn) {
proposalRequest := ProposalRequest{
Proposal: 1,
Subscribe: 1,
Amount: 10,
Basis: "payout",
ContractType: "CALL",
Currency: "USD",
Duration: 1,
DurationUnit: "m",
Symbol: "R_100",
Barrier: "+0.1",
}
message, err := json.Marshal(proposalRequest)
if err != nil {
log.Println("Error marshaling proposal request:", err)
return
}
err = conn.WriteMessage(websocket.TextMessage, message)
if err != nil {
log.Println("Error sending proposal request:", err)
} else {
log.Println("Proposal subscription sent")
}
}
// Function to send a ping every 30 seconds to keep the connection alive
func sendPing(conn *websocket.Conn) {
pingMessage := PingMessage{Ping: 1}
for {
message, err := json.Marshal(pingMessage)
if err != nil {
log.Println("Error marshaling ping message:", err)
return
}
err = conn.WriteMessage(websocket.TextMessage, message)
if err != nil {
log.Println("Error sending ping message:", err)
} else {
log.Println("Ping sent")
}
// Wait for 30 seconds before sending the next ping
time.Sleep(30 * time.Second)
}
}
// Function to handle incoming WebSocket messages
func handleMessage(message []byte) {
var data map[string]interface{}
err := json.Unmarshal(message, &data)
if err != nil {
log.Println("Error unmarshaling WebSocket message:", err)
return
}
// Check for errors in the message
if errorData, exists := data["error"]; exists {
errorMap := errorData.(map[string]interface{})
log.Printf("Error: %s", errorMap["message"])
} else if proposal, exists := data["proposal"]; exists {
// If it's a proposal, print details
proposalMap := proposal.(map[string]interface{})
log.Printf("Details: %s", proposalMap["longcode"])
log.Printf("Ask Price: %s", proposalMap["display_value"])
log.Printf("Payout: %v", proposalMap["payout"])
log.Printf("Spot: %v", proposalMap["spot"])
} else if data["msg_type"] == "ping" {
// If it's a ping response, log it
log.Println("Ping response received")
}
}
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DerivWebSocketClient
{
class Program
{
private static readonly string appId = "your_app_id"; // Replace with your app_id
private static readonly Uri wsUri = new Uri($"wss://ws.derivws.com/websockets/v3?app_id={appId}");
private static ClientWebSocket webSocket;
static async Task Main(string[] args)
{
webSocket = new ClientWebSocket();
try
{
// Connect to the WebSocket server
await webSocket.ConnectAsync(wsUri, CancellationToken.None);
Console.WriteLine("Connected to WebSocket server.");
// Send proposal subscription
await SendProposal();
// Start the ping task to send pings every 30 seconds
_ = Task.Run(SendPingPeriodically);
// Handle incoming WebSocket messages
await ReceiveMessages();
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
// Close the WebSocket connection when done
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
webSocket.Dispose();
Console.WriteLine("WebSocket closed.");
}
}
// Function to send a proposal subscription request
private static async Task SendProposal()
{
var proposalRequest = new
{
proposal = 1,
subscribe = 1,
amount = 10,
basis = "payout",
contract_type = "CALL",
currency = "USD",
duration = 1,
duration_unit = "m",
symbol = "R_100",
barrier = "+0.1"
};
string jsonRequest = JsonConvert.SerializeObject(proposalRequest);
await SendMessage(jsonRequest);
Console.WriteLine("Proposal subscription sent.");
}
// Function to send a ping message every 30 seconds to keep the connection alive
private static async Task SendPingPeriodically()
{
var pingMessage = new { ping = 1 };
while (webSocket.State == WebSocketState.Open)
{
string jsonPing = JsonConvert.SerializeObject(pingMessage);
await SendMessage(jsonPing);
Console.WriteLine("Ping sent.");
await Task.Delay(30000); // Wait for 30 seconds before sending the next ping
}
}
// Function to handle receiving messages from the WebSocket
private static async Task ReceiveMessages()
{
var buffer = new byte[1024 * 4];
while (webSocket.State == WebSocketState.Open)
{
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
break;
}
var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
HandleMessage(message);
}
}
// Function to handle incoming WebSocket messages
private static void HandleMessage(string message)
{
JObject data = JObject.Parse(message);
if (data.ContainsKey("error"))
{
Console.WriteLine("Error: " + data["error"]["message"]);
}
else if (data.ContainsKey("proposal"))
{
Console.WriteLine("Details: " + data["proposal"]["longcode"]);
Console.WriteLine("Ask Price: " + data["proposal"]["display_value"]);
Console.WriteLine("Payout: " + data["proposal"]["payout"]);
Console.WriteLine("Spot: " + data["proposal"]["spot"]);
}
else if (data.ContainsKey("msg_type") && data["msg_type"].ToString() == "ping")
{
Console.WriteLine("Ping response received.");
}
}
// Function to send a message through the WebSocket
private static async Task SendMessage(string message)
{
var messageBytes = Encoding.UTF8.GetBytes(message);
var buffer = new ArraySegment<byte>(messageBytes);
await webSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
}
}
}
#include <libwebsockets.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include "cJSON.h"
static int interrupted;
static struct lws_context *context;
static struct lws *wsi;
#define PING_INTERVAL 30
// WebSocket message type
enum protocol_demo {
PROTOCOL_DEMO,
PROTOCOL_COUNT
};
// JSON proposal request function
void send_proposal(struct lws *wsi) {
// Build JSON message
cJSON *proposal = cJSON_CreateObject();
cJSON_AddNumberToObject(proposal, "proposal", 1);
cJSON_AddNumberToObject(proposal, "subscribe", 1);
cJSON_AddNumberToObject(proposal, "amount", 10);
cJSON_AddStringToObject(proposal, "basis", "payout");
cJSON_AddStringToObject(proposal, "contract_type", "CALL");
cJSON_AddStringToObject(proposal, "currency", "USD");
cJSON_AddNumberToObject(proposal, "duration", 1);
cJSON_AddStringToObject(proposal, "duration_unit", "m");
cJSON_AddStringToObject(proposal, "symbol", "R_100");
cJSON_AddStringToObject(proposal, "barrier", "+0.1");
char *proposal_string = cJSON_PrintUnformatted(proposal);
lws_write(wsi, (unsigned char *)proposal_string, strlen(proposal_string), LWS_WRITE_TEXT);
free(proposal_string);
cJSON_Delete(proposal);
printf("Proposal subscription sent.\n");
}
// Ping function to keep the WebSocket connection alive
void send_ping(struct lws *wsi) {
cJSON *ping = cJSON_CreateObject();
cJSON_AddNumberToObject(ping, "ping", 1);
char *ping_string = cJSON_PrintUnformatted(ping);
lws_write(wsi, (unsigned char *)ping_string, strlen(ping_string), LWS_WRITE_TEXT);
free(ping_string);
cJSON_Delete(ping);
printf("Ping sent.\n");
}
// Callback function for handling events
static int callback_demo(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len) {
switch (reason) {
case LWS_CALLBACK_CLIENT_ESTABLISHED:
printf("WebSocket connection established\n");
send_proposal(wsi); // Send proposal on connection
break;
case LWS_CALLBACK_CLIENT_RECEIVE: {
char *message = (char *)in;
cJSON *data = cJSON_Parse(message);
if (!data) {
printf("Error parsing JSON message\n");
break;
}
cJSON *error = cJSON_GetObjectItem(data, "error");
if (error) {
printf("Error: %s\n", cJSON_GetObjectItem(error, "message")->valuestring);
} else if (cJSON_GetObjectItem(data, "proposal")) {
cJSON *proposal = cJSON_GetObjectItem(data, "proposal");
printf("Details: %s\n", cJSON_GetObjectItem(proposal, "longcode")->valuestring);
printf("Ask Price: %s\n", cJSON_GetObjectItem(proposal, "display_value")->valuestring);
printf("Payout: %f\n", cJSON_GetObjectItem(proposal, "payout")->valuedouble);
printf("Spot: %f\n", cJSON_GetObjectItem(proposal, "spot")->valuedouble);
} else if (strcmp(cJSON_GetObjectItem(data, "msg_type")->valuestring, "ping") == 0) {
printf("Ping response received\n");
}
cJSON_Delete(data);
break;
}
case LWS_CALLBACK_CLIENT_CLOSED:
printf("WebSocket connection closed\n");
interrupted = 1;
break;
default:
break;
}
return 0;
}
// Structure for WebSocket protocols
static const struct lws_protocols protocols[] = {
{
"example-protocol",
callback_demo,
0,
4096,
},
{NULL, NULL, 0, 0}
};
// Timer function for sending pings periodically
static void *ping_timer(void *arg) {
while (!interrupted) {
sleep(PING_INTERVAL);
if (wsi) {
send_ping(wsi);
}
}
return NULL;
}
// Main function
int main(void) {
struct lws_client_connect_info ccinfo = {0};
struct lws_context_creation_info ctx_creation_info = {0};
ctx_creation_info.port = CONTEXT_PORT_NO_LISTEN;
ctx_creation_info.protocols = protocols;
context = lws_create_context(&ctx_creation_info);
if (!context) {
printf("Failed to create context\n");
return 1;
}
ccinfo.context = context;
ccinfo.address = "ws.derivws.com";
ccinfo.port = 443;
ccinfo.path = "/websockets/v3?app_id=your_app_id"; // Replace with your app_id
ccinfo.host = lws_canonical_hostname(context);
ccinfo.origin = ccinfo.host;
ccinfo.ssl_connection = LCCSCF_USE_SSL;
ccinfo.protocol = protocols[0].name;
ccinfo.pwsi = &wsi;
// Establish WebSocket connection
wsi = lws_client_connect_via_info(&ccinfo);
if (!wsi) {
printf("WebSocket connection failed\n");
lws_context_destroy(context);
return 1;
}
// Create a thread to send ping messages periodically
pthread_t ping_thread;
pthread_create(&ping_thread, NULL, ping_timer, NULL);
// Main loop to handle WebSocket events
while (!interrupted) {
lws_service(context, 1000);
}
// Clean up
pthread_join(ping_thread, NULL);
lws_context_destroy(context);
return 0;
}
Updated 10 days ago