Skip to content

WebView plugin SDK basics

To support user data retrieval, trade execution, event handling and more, a WebView plugin (client) must establish reliable communication with the cTrader application (host). The WebView plugin SDK facilitates these interactions with cTrader, and this guide explains the communication pipeline between the client and the host.

Installation

Install the WebView plugin SDK, external API and other critical packages via NPM. Navigate to your project directory in a terminal window, then run this command:

npm install @spotware-web-team/sdk @spotware-web-team/sdk-external-api rxjs @veksa/logger

Note

In addition to the SDK, developers must also install and use the external API, as it facilitates messaging between the plugin and the host application using postMessage or CustomEvent.

Client-host synchronisation

Note

The relevant protocols are available as reference messages.

Before any message can be exchanged, a communication channel must be established. Use the adapter synchronisation logic below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// imports
import { createClientAdapter, IExternalTransportAdapter } from "@spotware-web-team/sdk-external-api";
import { handleConfirmEvent, registerEvent } from '@spotware-web-team/sdk';
import { createLogger } from "@veksa/logger";

// Actual code
let connectedToHost = false;

const logger = createLogger(isLogEnabled);
const adapter = createClientAdapter({ logger });

// Send confirmation on adapter initialisation
handleConfirmEvent(adapter, {}).pipe(take(1)).subscribe();

// Send register plugin event to host 
registerEvent(adapter).pipe(
    take(1),
    tap(() => {
        handleConfirmEvent(adapter, {}).pipe(take(1)).subscribe();

        // Set connection status
        connectedToHost = true;
    }),
    catchError(() => {
        console.warn('Error host connection');
        return [];
    }),
).subscribe();

Requests

Once synchronisation is complete, the plugin can interact with cTrader services by calling SDK methods. The plugin sends requests using the same adapter pattern as the handshake but with the required payload.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import { getLightSymbolList } from '@spotware-web-team/sdk';

// Use previously created adapter
getLightSymbolList(adapter, {}).pipe(
    take(1),
    tap(result => {
        // Response logged to console
        console.log(result);
})
).subscribe();

Note

SDK methods for sending requests and receiving responses are available as reference server messages, while details on the repeated fields within requests and responses are provided as models.

Responses

The SDK routes these responses through the previously created adapter to the plugin that sent a request.

Events and subscriptions

WebView plugins can subscribe to real-time data such as quotes, deal updates, execution events and more.

  1. Subscribe to quote data by sending a request:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import { subscribeQuotes } from '@spotware-web-team/sdk';
    
    // Use previously created adapter
    subscribeQuotes(adapter, {symbolId: [quotesSymbolId]}).pipe(
        take(1),
        tap(result => {
            console.log(JSON.stringify(result, null, 2));
        })
    ).subscribe();
    
  2. The subscription triggers the host to send periodic responses:

    1
    2
    3
    4
    5
    6
    7
    8
    import { quoteEvent } from '@spotware-web-team/sdk';
    
    // Use previously created adapter
    quoteEvent(adapter).pipe(
        tap(result => {
            console.log(JSON.stringify(result, null, 2));
        }),
    ).subscribe();
    

Note

WebView plugin operations involving deeplinks work only on cTrader Mobile.

A plugin can ask cTrader to open a deeplink (internal URL) using an SDK method as demonstrated below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import { openInternalUrl } from '@spotware-web-team/sdk';

// Use previously created adapter
const url = '/symbols/EURUSD/info';

openInternalUrl(adapter, {url}).pipe(
    tap(() => {
        console.log('url opened');
    }),
).subscribe();

Domain restrictions

For security reasons and compliance with cTrader rules, WebView plugins should load content only from the domain specified in the URL field during the build process. Any redirect or navigation attempt to a different domain is blocked inside the WebView in cTrader Web.

If your plugin must open or send users to a different domain, you must code your website to explicitly open the link in a new browser tab. Consider the examples below.

1
2
// Window
window.open('https://external-domain.com', '_blank', 'noopener');
1
2
// Standard HTML anchor tag
<a href="https://external-domain.com" target="_blank" rel="noopener">Open link</a>

Summary of messages

The table below summarises key operations.

Method Accepted arguments Returned type Description
openInternalUrl { url } ProtoOpenInternalUrlRes Opens a cTrader internal URL or screen inside the platform environment.
registerEvent { uuid } ProtoPublicRegisterEvent (event) Registers the plugin instance so it can receive events; part of the handshake sequence.
confirmEvent { } ProtoPublicConfirmEvent Confirms an event during the connect → confirm → register flow required by the protocol.
getAccountInformation { } ProtoGetAccountInformationRes Retrieves the authenticated trader’s complete account details, including balance, equity, margin and permissions.
getAccountGroupInformation { } ProtoGetAccountGroupInformationRes Retrieves the group configuration governing the account (fees, commissions, margin rules, restrictions and legal entity mappings).
getLightSymbolList { includeArchivedSymbols? } ProtoGetLightSymbolListRes Returns a lightweight list of symbols with essential tradability attributes.
getSymbol { symbolId: number[] } ProtoGetSymbolRes Retrieves detailed symbol information such as precision, swap data, leverage profiles and trading rules.
subscribeQuotes { symbolId: number[], enableStaleQuotesFiltering?, subscribeToSpotTimestamp? } ProtoSubscribeQuotesRes Subscribes the plugin to live quotes for one or more symbols.
unsubscribeQuotes { symbolId: number[] } ProtoUnsubscribeQuotesRes Unsubscribes from live quote streaming for the supplied symbol IDs.
getDynamicLeverage { leverageId } ProtoGetDynamicLeverageRes Retrieves dynamic leverage tiers based on the symbol’s leverage profile.
getDealList { fromTimestamp, toTimestamp } ProtoGetDealListRes Returns closing deals occurring within the specified timestamp range.
getTrendbarList { symbolId, period, fromTimestamp, toTimestamp, count, type } ProtoGetTrendbarListRes
quoteEvent — Stream of ProtoQuoteEvent Emits live quote data including bid, ask, highs, lows, trendbars, tickbars and depth if enabled.
executionEvent — Stream of ProtoExecutionEvent Emits trading events: order acceptance, fills, amendments, cancellations, rejections, stop-outs, deposits and withdrawals.
createNewOrder { symbolId, orderType, tradeSide, volume, …optional fields… } ProtoExecutionEvent (event response) Submits a new trade order (market, limit, stop, stop-limit, market-range). The result arrives through an execution event.
modifyOrder { orderId, limitPrice?, stopPrice?, volume?, expirationTimestamp?, stopLoss?, takeProfit?, … } ProtoExecutionEvent Modifies an existing pending order.
modifyOrderProtection { positionId, stopLoss?, takeProfit?, guaranteedStopLoss?, trailingStopLoss?, stopLossTriggerMethod? } ProtoExecutionEvent Modifies stop-loss and take-profit protections on an open position. Removing both protections may generate an ORDER_CANCELLED event.
cancelOrder { orderId, originalClientOrderId?, clientOrderId? } ProtoExecutionEvent (ORDER_CANCELLED) Cancels an existing pending order.
closePosition { positionId, volume, stake?, desiredVWAP?, closeWithPID? } ProtoExecutionEvent (ORDER_ACCEPTED) Closes all or part of an existing open position.