Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
KO-9 committed Feb 24, 2021
1 parent 0753ad3 commit 263a7b6
Show file tree
Hide file tree
Showing 4 changed files with 282 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/*
228 changes: 228 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
var websocketClient = require('ws');
const EventEmitter = require('events');
const axios = require('axios')


var baseUrl = '.trading212.com';
var availableEquitiesUrl = '/rest/instruments/EQUITY/900781274'
var orderUrl = '/rest/public/v2/equity/order';
var priceUrl = '/charting/prices?withFakes=false'
var hotListUrl = 'https://live.trading212.com/rest/positions-tracker/deltas/';

/*
Old
var statsUrl = '/rest/v1/customer/accounts/stats'
var fundsUrl = '/rest/customer/accounts/funds';
var openPositionsUrl = '/rest/v2/trading/open-positions';
var initInfoUrl = '/rest/v3/init-info';
var instrumentsUrl = '/rest/v1/instruments/';
*/

var transport = null;

var ws = null;

const wssUrl = 'wss://live.trading212.com/streaming/events/?app=WC4&appVersion=5.119.2&EIO=3&transport=websocket';

class Trading212 extends EventEmitter {
constructor(ENV, CUSTOMER_SESSION, TRADING212_SESSION_LIVE) {
super();

baseUrl = "https://" + ENV + baseUrl;

var headers = {
"Accept": "application/json",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"Sec-GPC": 1,
"Referer": "https://live.trading212.com/",
"Content-Type": "application/json",
Cookie: `CUSTOMER_SESSION=${CUSTOMER_SESSION}; TRADING212_SESSION_LIVE=${TRADING212_SESSION_LIVE}`
}

transport = axios.create({
withCredentials: true,
headers: headers
});

var opts = { headers: headers };
ws = new websocketClient(wssUrl, opts);

ws.on('open', () => {

});

ws.on('close', () => {
console.log("ws closed");
this.emit('trading212-ws-closed');
})

ws.on('sid', (data) => {
//sid received
});

ws.on('message', (data) => {
if(data == 3) {
ws.send(2);
}

if(data.substring(0, '42["platform-message-sync"'.length) == '42["platform-message-sync"') {
this.subscribeRoute('WEBPLATFORM');
this.subscribeRoute('ACCOUNT');
ws.send('42["acc"]');
this.emit('platform-subscribed');
} else if(data.substring(0, '42["q"'.length) == '42["q"') {
data = data.substring('42["q"'.length);
data = data.substring(2, data.length - 1);
data = data.split("|");
data = {
ticker: data[0],
bid: data[1],
ask: data[2],
}
this.emit('price', data);
} else if(data.substring(0, '42["q-sync"'.length) == '42["q-sync"') {
data = data.substring('42["q-sync"'.length);
data = data.substring(2, data.length - 1);
data = data.split("|");
data = {
ticker: data[0],
bid: data[1],
ask: data[2],
}
this.emit('price', data);
} else if(data.substring(0, '42["working-schedule-sync"'.length) == '42["working-schedule-sync"') {

} else if(data.substring(0, 9) == '42["acc",') {
data = data.substring(9);
data = data.substring(0, data.length - 1);
data = JSON.parse(data);
this.emit('account', data);
} else if(data.substring(0, 12) == '42["acc-re",') {
data = data.substring(12);
data = data.substring(0, data.length - 1);
data = JSON.parse(data);
this.emit('reaccount', data);
} else {
//console.log(data);
}
});

this.getExchangeRate();

}

subscribeRoute(route) {
ws.send('42["subscribe","/'+route+'"]');
}

bulkSubscribe(ticker_symbols) {
ticker_symbols = ticker_symbols.map(el => {
return '"'+el+'"';
});
ws.send('42["s-qbulk",['+ticker_symbols+']]');
}

bulkUnsubscribe(ticker_symbols) {
ticker_symbols = ticker_symbols.map(el => {
return '"'+el+'"';
});
ws.send('42["us-qbulk",['+ticker_symbols+']]');
}

getCurrentPrice(instruments) {
transport
.post(baseUrl + priceUrl, instruments).then(res => {
res.data.ticker = res.data.instrumentCode;
this.emit('price', res.data);
}).catch(err => {
console.log(err);
})
}

getAvailableEquities() {
transport
.get(baseUrl + availableEquitiesUrl)
.then(res => { this.emit('equity-data', res.data.items); } )
.catch(err => { console.log(err) })
}

getHotlist(period, delta) {
transport
.get(hotListUrl + "/" + period + "/" + delta)
.then(res => { this.emit('hotlist', period, delta, res.data); } )
.catch(err => { console.log(err) })
}

getExchangeRate() {
axios.get('https://api.exchangeratesapi.io/latest?base=GBP&symbols=USD')
.then(res => {
this.emit('forex', res.data);
}).catch(err => {
console.log(err);
});
//
}

placeOrder(instrumentCode, orderType, stopPrice, limitPrice, quantity, timeValidity) {
transport
.post(baseUrl + orderUrl, {
instrumentCode: instrumentCode,
orderType: orderType,
stopPrice: stopPrice,
limitPrice: limitPrice,
quantity: quantity,
timeValidity: timeValidity,

}).then(res => {
if(res.hasOwnProperty("data") && res.data.hasOwnProperty("account")) {
this.emit('account', res.data.account);
} else {
this.emit('order-failure', res.data);
}
}).catch(err => {
console.log(err);
})
}

modifyOrder(orderId, orderType, stopPrice, limitPrice, quantity, timeValidity) {
transport
.put(baseUrl + orderUrl + "/" + orderId, {
orderType: orderType,
stopPrice: stopPrice,
limitPrice: limitPrice,
quantity: quantity,
timeValidity: timeValidity,

}).then(res => {
if(res.hasOwnProperty("data") && res.data.hasOwnProperty("account")) {
this.emit('account', res.data.account);
} else {
console.log(res.data);
this.emit('order-failure', res.data);
}
}).catch(err => {
console.log(err);
})
}

deleteOrder(orderId) {
console.log('trying to delete order');
transport
.delete(baseUrl + orderUrl + '/' + orderId).then(res => {
if(res.hasOwnProperty("data") && res.data.hasOwnProperty("account")) {
this.emit('account', res.data);
} else {
this.emit('order-failure', res.data);
}
}).catch(err => {
console.log(err);
})
}
}


module.exports = Trading212;
28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "trading212",
"version": "1.0.0",
"description": "Trading212 unofficial api",
"main": "index.js",
"scripts": {
"run": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"trading212"
],
"author": "Konijntje",
"license": "MIT",
"dependencies": {
"axios": "^0.21.1",
"events": "^3.2.0",
"ws": "^7.4.3"
},
"repository": {
"type": "git",
"url": "git+https://github.com/KO-9/node-trading212.git"
},
"bugs": {
"url": "https://github.com/KO-9/node-trading212/issues",
},
"homepage": "https://github.com/KO-9/node-trading212/blob/main/README.md",
}
25 changes: 25 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


axios@^0.21.1:
version "0.21.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
dependencies:
follow-redirects "^1.10.0"

events@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379"
integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==

follow-redirects@^1.10.0:
version "1.13.2"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.2.tgz#dd73c8effc12728ba5cf4259d760ea5fb83e3147"
integrity sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==

ws@^7.4.3:
version "7.4.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.3.tgz#1f9643de34a543b8edb124bdcbc457ae55a6e5cd"
integrity sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==

0 comments on commit 263a7b6

Please sign in to comment.