MT5 JavaScript TypeScript grpc client from browser (Webpack)
npm install -g npx
npm install typescript --save-dev
You need protoc tool be installed
Install protoc plugins
npm install -g protoc-gen-js
npm install -g protoc-gen-grpc-web
You can find ready to run example here.
Run example steps:
Step 1. Generate client files. JS and TS files generation by mt5.proto.
protoc proto/*.proto --js_out=import_style=commonjs,binary:./grpc --grpc-web_out=import_style=typescript,mode=grpcwebtext:./grpc
where ./grpc is a output folder
This script generates client's files to the "grpc" folder.
Step 2. Insert your ceredentials in the example
Step 3. Install all dependencies
npm install
Step 4. Compile typescript to js files.
tsc -p .
This script generates client.js file from client.ts file.
Step 5. Bild browser bundle.
npx webpack ./client.js
This script creates main.js file in the dist folder. This file could be consumed by a browser.
Step 6. Create a developer http server. Which would provide bundle files to a browser, by GET request.
For the purpose of prototype demonstration, I would like to recommend using lightweigt developer http server.
npm install --global http-server
Step 7. Finally, you can run a developer server
http-server
You can use any presented link.
The example:
import {ConnectionClient, MT5Client, StreamsClient, SubscriptionsClient} from './grpc/proto/Mt5ServiceClientPb';
import {
AccountSummaryRequest,
ConnectReply,
ConnectRequest,
OnQuoteRequest,
SubscribeRequest
} from "./grpc/proto/mt5_pb";
import {RpcError} from "grpc-web";
const currencyPair = `BTCUSD`;
const serverAddress = 'https://mt5grpcweb.mtapi.io:443';
console.log(`Server:${serverAddress}`)
const sessionId = generateUUID();
const mt5Client = new MT5Client(serverAddress);
const connectionClient = new ConnectionClient(serverAddress);
const subscriptionClient = new SubscriptionsClient(serverAddress);
const streamClient = new StreamsClient(serverAddress);
ConnectToTheServer();
function ConnectToTheServer() {
const connectRequest = new ConnectRequest()
.setHost("") // TODO
.setUser(1) // TODO
.setPort(443) // TODO
.setPassword(""); // TODO
connectionClient.connect(connectRequest, { "mt5-sticky-session-header" : sessionId}, (err:RpcError, value: ConnectReply) => {
if (err) {
console.error(`RPC error message: ${err.message}`);
} else {
if (value?.getError())
console.error(`Internal server error: ${value?.getError()?.getMessage()}`);
else {
console.log(`Successful response`);
if (value?.getResult()) {
console.log(`Connection id: ${value?.getResult()}`);
let clientConnectionId = value?.getResult();
if (clientConnectionId)
{
OnConnectedGetAccountSummary(clientConnectionId);
OnConnectedSubscribe(clientConnectionId);
}
}
}
}
})
}
function OnConnectedGetAccountSummary(connectionId: string ) {
const sumReq = new AccountSummaryRequest();
sumReq.setId(connectionId);
mt5Client.accountSummary(sumReq,{"mt5-sticky-session-header": sessionId}, (err:RpcError, reply) => {
if (err) {
console.error(`RPC error message: ${err.message}`);
} else {
if (reply?.getError())
console.error(`Internal server error: ${reply?.getError()?.getMessage()}`);
else {
console.log(`Successful response`);
let accountSummary = reply?.getResult();
if (accountSummary) {
let balance = accountSummary.getBalance();
let profit = accountSummary.getProfit();
let credit = accountSummary.getCredit();
console.log(`Balance: ${balance}, profit ${profit}, credit ${credit}`);
}
}
}
} )
}
function OnConnectedSubscribe(clientConnectionId: string ) {
const subscriptionRequest = new SubscribeRequest();
subscriptionRequest.setId(clientConnectionId);
subscriptionRequest.setSymbol(currencyPair);
subscriptionClient.subscribe(subscriptionRequest,{"mt5-sticky-session-header": sessionId}, (err:RpcError, reply) => {
if (err) {
console.error(`RPC error message: ${err.message}`);
} else {
if (reply?.getError())
console.error(`Internal server error: ${reply?.getError()?.getMessage()}`);
else {
console.log(`Successful response`);
let responseObject = reply?.getResult();
if (responseObject)
{
console.log(`Subscribed: ${responseObject}`)
OnSubscribed(clientConnectionId);
}
}
}
});
}
function OnSubscribed(clientConnectionId: string) {
const onQuoteReq = new OnQuoteRequest();
onQuoteReq.setId(clientConnectionId);
let stream = streamClient.onQuote(onQuoteReq, {"mt5-sticky-session-header": sessionId});
stream.on('data', function (quoteReply) {
let errorFromServer = quoteReply?.getError();
if (errorFromServer)
{
console.error(`Internal server error: ${errorFromServer?.getMessage()}`);
}
else
{
console.log(`Successful quote response`);
let quoteFromServer = quoteReply?.getResult();
if (quoteFromServer)
{
let bid = quoteFromServer.getBid();
let ask = quoteFromServer.getAsk();
let last = quoteFromServer.getLast();
let symbol = quoteFromServer.getSymbol();
let time = quoteFromServer.getTime();
let volume = quoteFromServer.getVolume();
console.log(`Bid ${bid}. Ask ${ask}. Last ${last}. Symbol ${symbol}. Time ${time}. Volume ${volume}`)
}
}
});
stream.on('status', function (status) : void {
console.log(`Status received`);
console.log(`Status code: ${status.code}`);
console.log(`Status details: ${status.details}`);
console.log(`Status metadata: ${status.metadata}`);
});
stream.on("error", err => {
console.error(`Stream error code: ${err.code}. Message: ${err.message}`);
})
stream.on("end", function () {
console.log(`End received`);
})
}
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
let r = Math.random() * 16 | 0,
v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}