Performing Login
Overview
The login process is necessary to authenticate and create a session before performing any other commands with the FCLite API.
The login process can be done using either credentials (username and password) or a token, which can be obtained using the methods described in the getting access section.
The login process can be implemented using different programming languages, such as Node TypeScript, Node JavaScript, JavaScript, Swift, and Java, as shown in the code examples on the current page.
The steps in the login process involve creating a session, a status change listener, and a login callback
This article also mentions the logout operation.
How to Log into the System
Once you have determined which of the access methods you will use, and obtained your access details, be they token or login details, you can now authenticate and create a session.
First, you should add the library and connect your application to it as described in How to add the API to your project.
In order to end your session, you should perform the logout operation.
To log into the system, you need to follow these steps:
-
Creating a session.
-
Creating a Status Change Listener.
-
a. Logging in with credentials.
b. Logging in with a token.
-
Creating a session.
-
Creating a Status Change Listener.
-
a. Logging in with credentials.
b. Logging in with a token.
The JavaScript version explained here will be used as the basis for all future functions explained in this documentation, so it will be explained in detail with each individual file explained.
-
Creating a session.
-
Creating a Status Change Listener.
-
a. Logging in with credentials.
b. Logging in with a token.
-
Printing the results.
-
The main html file.
-
Change the main JavaScript file.
-
Creating a session.
-
Creating a Status Change Listener.
-
a. Logging in with credentials.
-
Creating a session.
-
Creating a Status Change Listener.
-
a. Logging in with credentials.
Step 1: Creating a Session
let session = sessionFactory.create("LoginSample"); //LoginSample - any name
let session = FXConnectLiteSessionFactory.create('LoginSample');
In our index.js file we add the line
const sessionFactory = FXConnectLite.FXConnectLiteSessionFactory
const LoginError = FXConnectLite.LoginError
const LoggerFactory = FXConnectLite.LoggerFactory
document.addEventListener('DOMContentLoaded', () => {
let session = sessionFactory.create('LoginSample');
session.setLogger(LoggerFactory.createLogger(LoggerFactory.LEVEL_DEBUG));
session.subscribeConnectionStatusChange(new ConnectionStatusChangeListener(session));
bindConnectionRelatedEvents(session);
});
final IFXConnectLiteSession session = FXConnectLiteSessionFactory.create("JavaLoginSample");
let session: IFXConnectLiteSession? = FXConnectLiteSessionFactory.createWithCustomParameters("SwiftLoginSample", connectionParametersBuilder.build())
See also: FXConnectLiteSessionFactory, create().
The next step is to create a listener to monitor the connection status and subscribe to it.
Step 2: Creating a Status Change Listener
This listener is used to monitor the users logged in status.
class ConnectionStatusChangeListener implements FXConnectLite.IConnectionStatusChangeListener {
onConnectionStatusChange(status: FXConnectLite.IConnectionStatus) {
Printer.print("Connection status changed. " + this.getStatusString(status))
}
getStatusString(status: FXConnectLite.IConnectionStatus): string {
return (status.isConnected() ? "Connected" : "") +
(status.isConnecting() ? "Connecting" : "") +
(status.isReconnecting() ? "Reconnecting" : "") +
(status.isDisconnected() ? "Disconnected" : "");
}
}
session.subscribeConnectionStatusChange(new ConnectionStatusChangeListener());
class CompleteLoginConnectionStatusChangeListener {
constructor(resolve, reject, session) {
this.resolve = resolve;
this.reject = reject;
this.session = session;
}
onConnectionStatusChange(status) {
if (status.isConnected()) {
this.session.unsubscribeConnectionStatusChange(this);
this.resolve();
} else if (status.isDisconnected()) {
this.session.unsubscribeConnectionStatusChange(this);
this.resolve();
}
}
}
export default CompleteLoginConnectionStatusChangeListener;
In order to keep our code clean and modular, we are creating the separate file connection-management\connection-status-change-listener.js.
The following example shows a lot of validation and error checking code in the class too.
class ConnectionStatusChangeListener {
constructor(session) {
this.session = session;
}
#getConnectionStatusName(status) {
if (status.isConnected())
return 'Connected';
if (status.isConnecting())
return 'Connecting';
if (status.isReconnecting())
return 'Reconnecting';
return 'Disconnected';
}
#showLoginSection() {
document.getElementById('workspace-section')
.style.display = 'none';
document.getElementById('login-section')
.style.display = 'block';
}
#showWorkspaceSection(session) {
document.getElementById('login-section')
.style.display = 'none';
document.getElementById('workspace-section')
.style.display = 'block';
document.getElementById('password-expired')
.textContent = session.getSystemSettingsProvider().isPasswordExpired();
}
onConnectionStatusChange(status) {
document.getElementById('connection-status')
.textContent = this.#getConnectionStatusName(status);
if (status.isConnected())
this.#showWorkspaceSection(this.session);
if (status.isDisconnected())
this.#showLoginSection();
}
}
ConnectionStatusChangeListener. As you can see in Step 1, this was done as soon as the document had finished loading.
session.subscribeConnectionStatusChange(new ConnectionStatusChangeListener(session));
internal class ConnectionStatusChangeListener: NSObject, IConnectionStatusChangeListener {
internal var session: IFXConnectLiteSession? = nil;
init(_ session: IFXConnectLiteSession) {
super.init();
self.session = session;
}
open func onConnectionStatusChange(_ status : IConnectionStatus?) -> Void {
print("Connection status changed: ", getStringName(status!));
if(status!.isConnected()) {
try? session!.getInstrumentsManager()!.subscribeStateChange(InstrumentsDataManagerStateChangeListener(session!));
try? session!.getInstrumentsManager()!.refresh();
}
if(status!.isDisconnected()) {
exit(0);
}
}
private func getStringName(_ connectionStatus: IConnectionStatus) -> String {
return (connectionStatus.isConnected() ? "Connected" : "") +
(connectionStatus.isConnecting() ? "Connecting" : "") +
(connectionStatus.isReconnecting() ? "Reconnecting" : "") +
(connectionStatus.isDisconnected() ? "Disconnected" : "");
}
}
private static class ConnectionStatusChangeListener implements IConnectionStatusChangeListener {
private final CompletableFuture<Boolean> connectedFuture;
public ConnectionStatusChangeListener(CompletableFuture<Boolean> connectedFuture) {
this.connectedFuture = connectedFuture;
}
public void onConnectionStatusChange(IConnectionStatus connectionStatus) {
System.out.println("Connection status changed: " + getStringName(connectionStatus));
if(connectionStatus.isConnected()) {
connectedFuture.complete(true);
}
if(connectionStatus.isDisconnected()) {
System.exit(0);
}
}
private String getStringName(IConnectionStatus connectionStatus) {
return (connectionStatus.isConnected() ? "Connected" : "") +
(connectionStatus.isConnecting() ? "Connecting" : "") +
(connectionStatus.isReconnecting() ? "Reconnecting" : "") +
(connectionStatus.isDisconnected() ? "Disconnected" : "");
}
}
try? session!.subscribeConnectionStatusChange(ConnectionStatusChangeListener(session!));
session.subscribeConnectionStatusChange(new ConnectionStatusChangeListener());
See also IConnectionStatusChangeListener, subscribeConnectionStatusChange.
Step 3a: Logging with Credentials
For logging with credentials, you first need to have obtained them as in the Getting Access article.
session.login(session, user, password, tradingSystemUrl, connectionName, new LoginCallback());
Step 3b: Log in with a Token
To login using a JWT token you first need to perform the steps in the Getting Access article in order to obtain the token needed.
Once you have the token, you can use the same code as in step 3a above with a small change.
The only difference will be to replace the login function in connection-management\connection-management.js with new processing.
This processing will attach your login to the current session.
function attach(JWT, tradingSystemUrl, connectionName);
session.login(user, password, tradingSystemUrl, connectionName, new loginCallback());
Step 3b: Log in with a Token
To login using a JWT token you first need to perform the steps in the Getting Access article in order to obtain the token needed.
Once you have the token, you can use the same code as in step 3a above with a small change.
The only difference will be to replace the login function in connection-management\connection-management.js with new processing.
This processing will attach your login to the current session.
function attach(JWT, tradingSystemUrl, connectionName);
We need to add a little JavaScript to start the processing when we click on the login forms submit button of your login form, which we will show you in a future step.
To keep our code clean, we are going to create the file connection-management\connection-management.js
Here we are creating JavaScript events that link methods to onClick actions.
function bindConnectionRelatedEvents(session, refreshFunc) {
document.getElementById('btn-submit')
.onclick = () => login(session);
document.getElementById('btn-logout')
.onclick = () => session.logout();
document.getElementById('btn-refresh')
.onclick = () => refreshFunc();
}
function hideErrorAlert() {
document.getElementById('error-alert')
.style.display = 'none';
}
function showErrorAlert(message) {
let errowAlert = document.getElementById('error-alert');
errowAlert.textContent = message;
errowAlert.style.display = 'block';
}
function login(session) {
hideErrorAlert();
let user = document.getElementById('user').value;
let password = document.getElementById('password').value;
let tradingSystemUrl = document.getElementById('url').value;
let connectionName = document.getElementById('connection').value;
session.login(user, password, tradingSystemUrl, connectionName, new LoginCallback())
}
The first two parameters are the login and password that you obtained when you registered your demo account, or signing up for a real account.
For the connection name and url, you should use the one relavent to your account type from the table below.
| Connection Name | URL |
|---|---|
| Demo | https://www.fxcorporate.com |
| Real | https://www.fxcorporate.com |
The loginCallback is the final parameter. As you can see from the code below, loginCallback is declared as an instance of the class ILoginCallback that is part of the installed library.
You, as the developer, must extend this class, as in the examples, and declare your own functions: onLoginError, onTradingTerminalRequest, so that your application can handle these as you need.
With this code executed, you should now have both a session, and your user logged in.
The following is an example of the loginCallBack function:
To keep our code clean we are creating the file connection-management\login-callback.js
class LoginCallback {
onLoginError(error) {
let message = `${error.getMessage()} (${LoginCallback.errorCodeToString(error)})`;
showErrorAlert(message);
}
static errorCodeToString(error) {
switch (error.getCode()) {
case LoginError.CODE_EMPTY_PARAMETER:
return 'EMPTY_PARAMETER';
case LoginError.CODE_INCORRECT_PIN:
return 'INCORRECT_PIN';
case LoginError.CODE_WRONG_USERNAME_OR_PASSWORD:
return 'WRONG_USERNAME_OR_PASSWORD';
case LoginError.CODE_LOCKED_USER:
return 'LOCKED_USER';
case LoginError.CODE_SERVER_ERROR:
return 'SERVER_ERROR';
case LoginError.CODE_INCORRECT_TRADING_SYSTEM_URL:
return 'INCORRECT_TRADING_SYSTEM_URL';
case LoginError.CODE_INCORRECT_CONNECTION_NAME:
return 'INCORRECT_CONNECTION_NAME';
case LoginError.CODE_TIMEOUT:
return 'TIMEOUT';
default:
return 'NOT_SPECIFIED';
}
}
}
connections state change listener has a method onConnectionStatusChange which is called automatically and it injects the new connection status into our html.
Step 3b: Log in with a Token
To login using a JWT token you first need to perform the steps in the Getting Access article in order to obtain the token needed.
Once you have the token, you can use the same code as in step 3a above with a small change.
The only difference will be to replace the login function in connection-management\connection-management.js with new processing.
This processing will attach your login to the current session.
function login(session) {
hideErrorAlert();
let JWT = 'access_token' ;
let tradingSystemUrl = document.getElementById('url').value;
let connectionName = document.getElementById('connection').value;
session.attach(JWT, tradingSystemUrl, connectionName);
}
Step 4: Printing the Results
As you can see from our connection-managemnt\connection-status-change-listener.js file on line 42, we have JavaScript method onConnectionStatusChange that injects the connection status into our html that has a span with this same id="connection-status".
document.getElementById('connection-status')
.textContent = this.#getConnectionStatusName(status);
<span id="connection-status"></span>
Step 5: The Main HTML File
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>ForexConnect API Login</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous" >
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
crossorigin="anonymous" >
</script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
crossorigin="anonymous" >
<link href="style.css" rel="stylesheet"/>
<script src="fclite/forex-connect-lite.js"></script>
<!-- The scripts below are belong to this particular sample. Make sure they aren't copied from another samples. -->
<script src="connection_management/connection-management.js"></script>
<script src="connection_management/connection-status-change-listener.js"></script>
<script src="connection_management/login-callback.js"></script>
<script src="index.js"></script>
</head>
<body>
<div class="container">
<div class="row" id="connection-container">
<div class="offset-sm-3 col-sm-3 mt-5 mb-5 text-start">
<span id="connection-status"></span>
</div>
<div class="col-sm-3 mt-5 text-end">
<button type="button" class="btn btn-outline-danger" id="btn-logout">Logout</button>
</div>
</div>
<section class="row" id="login-section">
<div class="offset-sm-3 col-sm-6 border pt-3 pb-3 mt-5 mb-5">
<div class="alert alert-danger" role="alert" id="error-alert"></div>
<form id="login-form" class="p-3">
<div class="row mb-3">
<div class="col-sm-2">
<label for="user" class="form-label">Username:</label>
</div>
<div class="col-sm-7 px-4">
<input type="text" id="user" value="" />
</div>
</div>
<div class="row mb-3">
<div class="col-sm-2">
<label for="password" class="form-label">Password:</label>
</div>
<div class="col-sm-7 px-4">
<input type="text" id="password" value="" />
</div>
</div>
<div class="row mb-3">
<div class="col-sm-2">
<label for="url" class="form-label">Server:</label>
</div>
<div class="col-sm-7 px-4">
<select class="form-select" id="url">
<option value="http://www.fxcorporate.com">http://www.fxcorporate.com</option>
</select>
</div>
</div>
<div class="row mb-3">
<div class="col-sm-2">
<label for="connection" class="form-label">Connection:</label>
</div>
<div class="col-sm-7 px-4">
<input type="text" id="connection" value="Demo" />
</div>
</div>
<button type="button" class="btn btn-primary" id="btn-submit">Submit</button>
</form>
</div>
</section>
<section id="workspace-section">
<div class="row" id="authorized-container">
<div class="offset-sm-3 col-sm-6 border pt-3 pb-3 mt-5">
Authorized<br />
Is password expired: <span id="password-expired"></span>
</div>
</div>
<div id="items-state-container">
<div class="d-flex">
<div class="d-inline-block offset-sm-3 col-sm-4 mt-5 text-start">
Items state:
<span id="state"></span>
</div>
<div class="d-inline-block col-sm-2 mt-5 text-end">
<button type="button" id="btn-refresh" class="btn btn-outline-secondary">Refresh</button>
</div>
</div>
</div>
<div class="row" id="items-container">
<div id="items" class="offset-sm-3 col-sm-6 border pt-0 pb-3 mt-3"></div>
</div>
</section>
</div>
</body>
</html>
Step 6: The Main JavaScript File
index.js
const sessionFactory = FXConnectLite.FXConnectLiteSessionFactory
const LoginError = FXConnectLite.LoginError
const LoggerFactory = FXConnectLite.LoggerFactory
document.addEventListener('DOMContentLoaded', () => {
let session = sessionFactory.create('LoginSample');
session.setLogger(LoggerFactory.createLogger(LoggerFactory.LEVEL_DEBUG));
session.subscribeConnectionStatusChange(new ConnectionStatusChangeListener(session));
bindConnectionRelatedEvents(session);
});
try? session!.login(login, pass, url, conn, LoginCallback())
session.login(user, password, tradingSystemUrl, connectionName, new LoginCallback());
How to Log Out of the System
session.logout();
session.logout();
session.logout();
Table Builder
For printing the results of the command, we have first created a common\table-builder.js file which will contain our TableBuilder class. This class will be used in all of our samples in JavaScript.
class TableBuilder {
constructor() {
this.#items = document.getElementById('items');
this.lastSelectedId = '';
}
appendColumn(row, className, value) {
let column = document.createElement('div');
column.className = className;
column.textContent = value;
row.appendChild(column);
}
createDataSubtable(parentId, columns, className) {
let subtableRow = this.createDataTableRow(columns, className);
let parentRow = document.getElementById('item-' + parentId);
parentRow.style.backgroundColor = '#dce0e4';
parentRow.after(subtableRow);
return subtableRow;
}
createDataTableRow(columns, className) {
if (className === undefined)
className = 'row mb-0 pb-0 item';
let row = document.createElement('div');
row.className = className;
row.style.cursor = 'pointer';
columns.forEach(column => {
this.appendColumn(row, column.className, column.value);
});
row.id = 'item-' + columns[0].value;
this.items.appendChild(row);
return row;
}
createHeaderTableRow(columns) {
let row = document.createElement('div');
row.className = 'row mb-3';
row.style.backgroundColor = '#adb5bd';
columns.forEach(column => {
this.appendColumn(row, column.className, column.value);
});
this.items.replaceChildren();
this.items.appendChild(row);
return row;
}
onRowClick(id, func) {
if (this.lastSelectedId !== id) {
this.lastSelectedId = id;
func();
} else {
this.removeSubtable();
this.lastSelectedId = '';
}
}
removeSubtable() {
this.lastSelectedId = '';
let subtable = document.querySelector('#items > div.row.mb-3.details');
if (subtable !== null)
subtable.remove();
let parentRows = document.getElementsByClassName('row mb-0 pb-0 item');
for (let row of parentRows)
row.style.backgroundColor = '';
}
showContainer() {
document.getElementById('itemsContainer').style.display = 'block';
}
get items() {
return this.#items;
}
#items;
}
try session!.logout()
session.logout();
Download the sample Node TypeScript, Node Javascript, Javascript.
When the session is created, you can:
- Get available instruments.
- Subscribe and Unsubscribe to instruments.
- Get price updates for an instrument.
- Get historical prices for an instrument.
- Create a market order.
- Create an entry order.
- Get open positions.
Note
Questions and answers
-
What is the correct way to handle disconnects of
IFXConnectLiteSession?After changing state to disconnected, there is no need to create a new session. You can perform the login operation on the old session object.
-
Why offer updates are enabled even without calling
instrumentsManager.subscribeInstruments()?You may have subscribed instruments on the server (profile subscription). You can check it execute after successful login:
session.getInstrumentsManager().getAllInstrumentDescriptors().filter(item => item.getSubscriptionStatus() == 'T');OffersManager.refresh()sends a MDT subscription request for all profile subscribed instruments (initialization of subscription).
| Table of Contents | |
|---|---|