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 '@deriv/deriv-api/dist/DerivAPIBasic.js';
const app_id = 1089; // Replace with your app_id if different.
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',
});
};
const ping = () => {
setInterval(() => {
api.ping();
}, 30000); // Sends a ping message every 30 seconds
};
const wsResponse = async (res) => {
const data = JSON.parse(res.data);
if (data.error !== undefined) {
console.log('Error:', data.error.message);
connection.removeEventListener('message', wsResponse);
await api.disconnect();
} else if (data.msg_type === 'proposal') {
console.log('Details:', data.proposal.longcode);
console.log('Ask Price:', data.proposal.display_value);
console.log('Payout:', data.proposal.payout);
console.log('Spot:', data.proposal.spot);
} else if (data.msg_type === 'ping') {
console.log('ping');
}
};
const checkSignal = () => {
proposal();
ping();
connection.addEventListener('message', wsResponse);
};
// Browser-specific functionality
if (typeof document !== 'undefined') {
const keep_alive_button = document.querySelector('#keep_alive');
const end_call_button = document.querySelector('#end_call');
keep_alive_button.addEventListener('click', checkSignal);
end_call_button.addEventListener('click', () => {
connection.removeEventListener('message', wsResponse);
proposal().unsubscribe();
});
} else {
// For Node.js environment: start the signal check immediately
checkSignal();
}
/*
Instructions:
1. **Install Node.js**: Ensure you have Node.js installed from https://nodejs.org/.
2. **Install Deriv API Package**: Use npm to install the Deriv API package by running:
npm install @deriv/deriv-api
3. **Save the Code**: Save the code in a file, e.g., `websocket_example.js`.
4. **Run in Node.js**:
- In your terminal, navigate to the directory where you saved the file.
- Run the script using:
```
node websocket_example.js
```
5. **Run in a Browser**:
- Include the script in your HTML page, and ensure there are two buttons with IDs `keep_alive` and `end_call`.
- Use the `keep_alive` button to start the signal check and the `end_call` button to unsubscribe from the proposal and stop receiving messages.
Replace the `app_id` in the URL if you have a different app ID.
*/
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("[open] Connection established")
// Function to send a proposal subscription request
func sendProposalSubscription() {
let proposalRequest = [
"proposal": 1,
"subscribe": 1,
"amount": 10,
"basis": "payout",
"contract_type": "CALL",
"currency": "USD",
"duration": 1,
"duration_unit": "m",
"symbol": "R_100",
"barrier": "+0.1"
] as [String: Any]
if let proposalData = try? JSONSerialization.data(withJSONObject: proposalRequest, options: []) {
let message = URLSessionWebSocketTask.Message.data(proposalData)
webSocketTask?.send(message) { error in
if let error = error {
print("[error] Failed to send proposal subscription: \(error.localizedDescription)")
} else {
print("Proposal subscription sent.")
}
}
}
}
// Function to send a ping message every 30 seconds
func startPing() {
Timer.scheduledTimer(withTimeInterval: 30.0, repeats: true) { _ in
let pingMessage = URLSessionWebSocketTask.Message.string("{\"ping\": 1}")
webSocketTask?.send(pingMessage) { error in
if let error = error {
print("[error] Failed to send ping: \(error.localizedDescription)")
} else {
print("Ping sent to keep connection alive.")
}
}
}
}
// 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 proposal and ping 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 == "proposal", let proposal = data["proposal"] as? [String: Any] {
print("Details: \(proposal["longcode"] ?? "")")
print("Ask Price: \(proposal["display_value"] ?? "")")
print("Payout: \(proposal["payout"] ?? "")")
print("Spot: \(proposal["spot"] ?? "")")
} else if data["msg_type"] as? String == "ping" {
print("[Ping] Ping response received.")
}
}
// Start sending the proposal subscription and pinging the server
sendProposalSubscription()
startPing()
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()
/*
* Instructions to Run:
* 1. Ensure Swift is installed on your machine.
* 2. Save this code in a file, for example, `WebSocketClient.swift`.
* 3. Open a terminal, navigate to the directory where you saved the file, and run:
* swift WebSocketClient.swift
* 4. The script connects to the WebSocket server, sends a proposal subscription, and sends a ping every 30 seconds to keep the connection alive.
*/
use tokio_tungstenite::connect_async;
use tokio_tungstenite::tungstenite::protocol::Message;
use futures_util::{SinkExt, StreamExt};
use tokio::{time::interval, sync::Mutex, task::spawn};
use std::sync::Arc;
use serde_json::json;
use url::Url;
use std::time::Duration;
#[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!("[open] Connection established");
// Proposal request JSON
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"
});
// Clone `socket` for the ping task and start pinging every 30 seconds
let ping_socket = Arc::clone(&socket);
let ping_task = spawn(async move {
let mut interval = interval(Duration::from_secs(30));
loop {
interval.tick().await;
let mut socket = ping_socket.lock().await;
if socket.send(Message::Text(json!({ "ping": 1 }).to_string())).await.is_ok() {
println!("[ping] Ping sent to keep connection alive.");
}
}
});
// Clone `socket` for sending the proposal
let send_socket = Arc::clone(&socket);
let send_task = spawn(async move {
let mut socket = send_socket.lock().await;
if socket.send(Message::Text(proposal_request.to_string())).await.is_ok() {
println!("Proposal subscription 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 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").unwrap_or(&json!("")) == "ping" {
println!("[Ping] Ping response received.");
} else if let Some(error) = data.get("error") {
println!("[Error] {}", error["message"]);
}
}
_ => {}
}
}
});
// Await all tasks to complete
let _ = tokio::try_join!(ping_task, 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
Note: Replace `app_id` with your actual app_id if needed.
*/
<?php
require 'vendor/autoload.php';
use WebSocket\Client;
// Replace with your app_id
$app_id = 1089;
$uri = "wss://ws.derivws.com/websockets/v3?app_id=$app_id";
// Create a new WebSocket client
$client = new Client($uri);
try {
echo "[open] WebSocket connection established.\n";
// Send a proposal subscription request
$proposal_request = json_encode([
"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->send($proposal_request);
echo "[sent] Proposal subscription sent.\n";
// Ping function to keep connection alive
$ping_interval = 30; // in seconds
$last_ping_time = time();
// Main loop to handle responses and send ping messages
while (true) {
// Check if it's time to send a ping
if (time() - $last_ping_time >= $ping_interval) {
$client->send(json_encode(["ping" => 1]));
echo "[ping] Ping sent to keep connection alive.\n";
$last_ping_time = time();
}
// Receive response from WebSocket
$response = $client->receive();
$data = json_decode($response, true);
if (isset($data["error"])) {
echo "[error] " . $data["error"]["message"] . "\n";
break;
} elseif ($data["msg_type"] === "proposal") {
$proposal = $data["proposal"];
echo "[proposal] Details: {$proposal['longcode']}\n";
echo "[proposal] Ask Price: {$proposal['display_value']}\n";
echo "[proposal] Payout: {$proposal['payout']}\n";
echo "[proposal] Spot: {$proposal['spot']}\n";
} elseif ($data["msg_type"] === "ping") {
echo "[ping] Ping response received.\n";
}
// Sleep briefly to prevent continuous loop
usleep(500000); // 500ms
}
// Close the WebSocket connection
$client->close();
echo "[close] WebSocket connection closed.\n";
} catch (Exception $e) {
echo "[error] " . $e->getMessage() . "\n";
}
/*
Instructions to run the code:
1. Ensure PHP is installed on your machine. You can download it from https://www.php.net/.
2. Install Composer if you haven't already, by downloading it from https://getcomposer.org/.
3. Create a `composer.json` file in the same directory as your PHP script with the following content:
{
"require": {
"textalk/websocket": "^1.5"
}
}
4. Run the following command to install the WebSocket library:
composer install
5. Save the code above to a PHP file, e.g., `websocket_client.php`.
6. Run the code from the command line:
php websocket_client.php
Note: Replace `app_id` with your actual app_id if needed.
*/
package main
import (
"context"
"fmt"
"log"
"time"
"nhooyr.io/websocket"
"nhooyr.io/websocket/wsjson"
)
// Define constants
const (
webSocketURL = "wss://ws.derivws.com/websockets/v3?app_id=1089"
)
// ProposalRequest defines the structure of the proposal subscription request
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"`
}
func main() {
// Set up WebSocket connection context
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Establish a 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("WebSocket connection established.")
// Send initial proposal subscription request
err = sendProposalRequest(ctx, conn)
if err != nil {
log.Fatalf("Failed to send proposal request: %v", err)
}
// Start keep-alive ping
go keepAlivePing(ctx, conn)
// Handle incoming messages
handleResponses(ctx, conn)
}
// sendProposalRequest sends a proposal subscription request to the WebSocket server
func sendProposalRequest(ctx context.Context, conn *websocket.Conn) error {
// Construct proposal subscription request
proposal := ProposalRequest{
Proposal: 1,
Subscribe: 1,
Amount: 10,
Basis: "payout",
ContractType: "CALL",
Currency: "USD",
Duration: 1,
DurationUnit: "m",
Symbol: "R_100",
Barrier: "+0.1",
}
fmt.Println("Sending proposal subscription...")
return wsjson.Write(ctx, conn, proposal)
}
// keepAlivePing sends a ping message every 30 seconds to keep the connection alive
func keepAlivePing(ctx context.Context, conn *websocket.Conn) {
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
// Send ping message
pingMsg := map[string]int{"ping": 1}
err := wsjson.Write(ctx, conn, pingMsg)
if err != nil {
log.Printf("Ping failed: %v", err)
return
}
fmt.Println("Ping sent.")
case <-ctx.Done():
return
}
}
}
// handleResponses listens for and processes messages received from the WebSocket server
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)
}
// Process response messages
msgType := response["msg_type"]
switch msgType {
case "proposal":
// Print proposal details
proposal := response["proposal"].(map[string]interface{})
fmt.Printf("Details: %v\n", proposal["longcode"])
fmt.Printf("Ask Price: %v\n", proposal["display_value"])
fmt.Printf("Payout: %v\n", proposal["payout"])
fmt.Printf("Spot: %v\n", proposal["spot"])
case "ping":
fmt.Println("[Ping] Ping response received.")
default:
fmt.Printf("Received message: %v\n", response)
}
}
}
/*
Instructions to run the code locally:
1. Install Go: Ensure you have Go installed on your machine. You can download it from https://golang.org/dl/.
2. Save the code:
- Save this code into a file named `connect.go`.
3. Initialize a Go module:
- Open a terminal in the directory containing `connect.go`.
- Run `go mod init app` to initialize a new Go module.
- Run `go get nhooyr.io/websocket` to install the WebSocket package dependency.
4. Run the code:
- Execute the code using the command `go run connect.go`.
- Alternatively, you can build and run the executable:
```
go build -o connect connect.go
./connect
```
5. Replace `app_id=1089` with your actual app_id if needed.
*/
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
private static readonly int pingInterval = 30000; // Ping every 30 seconds
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("WebSocket connection established.");
// Send initial proposal subscription request
await SendProposalSubscription(webSocket);
// Start a task to send pings to keep connection alive
Task keepAlivePingTask = KeepAlivePing(webSocket);
// Handle responses from the server
await HandleResponses(webSocket);
// Ensure the keep-alive ping task finishes
await keepAlivePingTask;
}
}
private static async Task SendProposalSubscription(ClientWebSocket webSocket)
{
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 requestJson = JsonSerializer.Serialize(proposalRequest);
var bytes = Encoding.UTF8.GetBytes(requestJson);
await webSocket.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, CancellationToken.None);
Console.WriteLine("Proposal subscription sent.");
}
private static async Task KeepAlivePing(ClientWebSocket webSocket)
{
while (webSocket.State == WebSocketState.Open)
{
await Task.Delay(pingInterval);
var pingRequest = new { ping = 1 };
string pingJson = JsonSerializer.Serialize(pingRequest);
var pingBytes = Encoding.UTF8.GetBytes(pingJson);
await webSocket.SendAsync(new ArraySegment<byte>(pingBytes), WebSocketMessageType.Text, true, CancellationToken.None);
Console.WriteLine("Ping sent to keep connection alive.");
}
}
private static async Task HandleResponses(ClientWebSocket webSocket)
{
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)
{
Console.WriteLine("WebSocket connection closed by server.");
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
}
else
{
string response = Encoding.UTF8.GetString(buffer, 0, result.Count);
var data = JsonSerializer.Deserialize<JsonElement>(response);
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))
{
if (msgType.GetString() == "proposal")
{
var proposal = data.GetProperty("proposal");
// Extract proposal details with type-checking
string longcode = proposal.GetProperty("longcode").GetString();
Console.WriteLine($"Details: {longcode}");
string displayValue = proposal.GetProperty("display_value").GetRawText();
Console.WriteLine($"Ask Price: {displayValue}");
string payout = proposal.GetProperty("payout").GetRawText();
Console.WriteLine($"Payout: {payout}");
string spot = proposal.GetProperty("spot").GetRawText();
Console.WriteLine($"Spot: {spot}");
}
else if (msgType.GetString() == "ping")
{
Console.WriteLine("[Ping] Ping response received.");
}
}
}
}
}
}
/*
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.
*/
#include <libwebsockets.h>
#include <string.h>
#include <signal.h>
#include <time.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;
// 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 proposal subscription message
void send_proposal(struct lws *wsi) {
const char *proposal_msg = "{\"proposal\": 1, \"subscribe\": 1, \"amount\": 10, \"basis\": \"payout\", \"contract_type\": \"CALL\", \"currency\": \"USD\", \"duration\": 1, \"duration_unit\": \"m\", \"symbol\": \"R_100\", \"barrier\": \"+0.1\"}";
unsigned char buf[LWS_PRE + 256];
memcpy(&buf[LWS_PRE], proposal_msg, strlen(proposal_msg));
lws_write(wsi, &buf[LWS_PRE], strlen(proposal_msg), LWS_WRITE_TEXT);
lwsl_user("Proposal subscription sent\n");
}
// 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_proposal(wsi); // Send proposal 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);
}
break;
case LWS_CALLBACK_CLIENT_RECEIVE:
lwsl_hexdump_notice(in, len); // Log received message
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("LWS Deriv ws 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("Completed\n");
return 0;
}
/*
* Instructions:
* 1. Install the libwebsockets library on your system if it's not already installed.
* - On Ubuntu, you can install it by running:
* sudo apt-get install libwebsockets-dev
* - On macOS, you can use Homebrew:
* brew install libwebsockets
* - For other operating systems, refer to the libwebsockets documentation for installation details.
* 2. Compile the code using the following command:
* gcc -o connect connect.c -lwebsockets -lssl -lcrypto -lm
* - This command links the required libraries: `libwebsockets`, `ssl`, `crypto`, and `m`.
* 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.
*/
import asyncio
from deriv_api import DerivAPI
from deriv_api.subscription_manager import SubscriptionManager
# Replace with your actual app_id
app_id = 1089
async def main():
# Initialize the DerivAPI instance
api = DerivAPI(app_id=app_id)
# Initialize the SubscriptionManager
subscription_manager = SubscriptionManager(api)
# Define the proposal request
proposal_request = {
"proposal": 1,
"amount": 10,
"basis": "payout",
"contract_type": "CALL",
"currency": "USD",
"duration": 1,
"duration_unit": "m",
"symbol": "R_100",
"barrier": "+0.1"
}
# Subscribe to the proposal stream
try:
proposal_stream = await subscription_manager.subscribe(proposal_request)
print("Subscribed to proposal stream")
# Handle incoming messages and print formatted proposal details
proposal_stream.subscribe(
on_next=lambda message: print_proposal_details(message),
on_error=lambda e: print(f"Error: {e}"),
on_completed=lambda: print("Subscription completed")
)
# Function to send a ping every 30 seconds
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 and proposal subscription concurrently
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 proposal details
def print_proposal_details(message):
data = message.get("proposal", {})
if data:
print(f"Details: {data.get('longcode', 'N/A')}")
print(f"Ask Price: {data.get('display_value', 'N/A')}")
print(f"Payout: {data.get('payout', 'N/A')}")
print(f"Spot: {data.get('spot', 'N/A')}")
# Run the main function
if __name__ == "__main__":
asyncio.run(main())
"""
Instructions to run this code:
1. **Install the Required Library**:
- Ensure that `python-deriv-api` is installed. If not, install it using:
```
pip install python-deriv-api
```
2. **Save and Run the Code**:
- Save this code to a file, e.g., `connect.py`.
- Run the script using:
```
python connect.py
```
3. **Configuration**:
- Replace the `app_id` variable with your actual Deriv app ID if needed.
This script will connect to the Deriv API WebSocket, subscribe to a proposal stream, print proposal details, and send a ping every 30 seconds to keep the connection active.
"""
#!/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
# Define a ping interval in seconds
my $ping_interval = 30;
# Function to send a proposal subscription request
sub send_proposal {
my $connection = shift;
my $proposal_request = 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'
});
$connection->send($proposal_request);
say "Proposal subscription sent.";
}
# Establish WebSocket connection
$client->connect($url)->cb(sub {
my $connection = eval { shift->recv };
if (!$connection) {
die "Connection error: $@";
}
say "WebSocket connection established.";
# Set up a repeating timer to send ping every 30 seconds
my $ping_timer = AnyEvent->timer(
after => $ping_interval,
interval => $ping_interval,
cb => sub {
$connection->send(encode_json({ ping => 1 }));
say "Ping sent to keep connection alive.";
}
);
# Send the initial proposal subscription
send_proposal($connection);
# Handle incoming messages
$connection->on(each_message => sub {
my ($connection, $message) = @_;
my $data = decode_json($message->body);
# Handle errors
if ($data->{error}) {
say "[Error] " . $data->{error}{message};
$connection->close;
return;
}
# Handle proposal messages
if ($data->{msg_type} && $data->{msg_type} eq 'proposal') {
my $proposal = $data->{proposal};
say "Details: $proposal->{longcode}";
say "Ask Price: $proposal->{display_value}";
say "Payout: $proposal->{payout}";
say "Spot: $proposal->{spot}";
} elsif ($data->{msg_type} && $data->{msg_type} eq 'ping') {
say "[Ping] Ping response received.";
}
});
# Handle connection close
$connection->on(finish => sub {
say "WebSocket connection closed.";
$ping_timer = undef; # Stop the ping timer
});
});
# 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., `connect.pl`.
# 4. Run the script using the command:
# perl connect.pl
# This script will connect to the Deriv WebSocket API, subscribe to a proposal, and send a ping every 30 seconds to keep the connection alive.
Updated 11 days ago