Reorganisation + Electron fixes (#118)

* Updates package versions

* Updating versions with RCs

* Updated landing page with stock images

* Begins refactoring of websocket
Adds Help component

* Dark theme for charts

* event Event

* Adds cryptocurrency font
Updates wallet to use it

* Rejigs the location of assets

* rxjs update
wallet font correction

* renaming websocket service

* Refactors websocket use
Destroys and subscribes appropriately
Also handles when websocket is not available with intervals

* Fixes issues with electron by rebasing with Maxime GRIS electron builder

* License change

* Readme update

* Parses available and enabled currencies to create an object {Name:X, Enabled:Y}

* Adds methods to convert from string arrays to objects with enabled status for all currencies

* Uses a localstorage cache for config for 15 minutes

* Moves handling of settings to config object

* Fix typescripting

* Fixes issue with saving and loading

* Slows websocket repeats
Adds cool new dictionary style item and iterable.
Updatres currency-list.component to list all enabled currencies and exchanges (still doesn't do anything)

* Updates selected-currency.component to display all currencies ticker updates if there is no selected currency
Will display only selected currency results once it is set
Sets a new property to ensure all currency names are consistent for currency list plans

* Fixes issue where only one component could listen to the websocket at once
Allows you to select a currency in exchange grid mode

* Adds selected currency support to buy & sell components
Updates selected currency ticker to update on change faster

* Adds Online status indicator

* Removal of console.logs for working features

* Allows currency-list.component to aggregate on currency and list exchanges that match it

* Highlights selected currency in currency-list.component
Allows you to select a currency
This commit is contained in:
Scott
2018-05-04 15:07:11 +10:00
committed by Adrian Gallagher
parent 1a473fb59c
commit d882c1dff4
141 changed files with 15572 additions and 7927 deletions

View File

@@ -1,15 +0,0 @@
import { TestBed, inject } from '@angular/core/testing';
import { WebsocketHandlerService } from './websocket-handler.service';
describe('WebsocketHandlerService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [WebsocketHandlerService]
});
});
it('should be created', inject([WebsocketHandlerService], (service: WebsocketHandlerService) => {
expect(service).toBeTruthy();
}));
});

View File

@@ -1,44 +0,0 @@
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs/Rx';
import { WebsocketService } from './../../services/websocket/websocket.service';
const WEBSOCKET_URL = 'ws://localhost:9050/ws';
export interface Message {
Event: string,
data:any,
Exchange:string,
AssetType:string
}
@Injectable()
export class WebsocketHandlerService {
public messages: Subject<any>;
private authenticateMessage = {
Event:'auth',
data:{"username":"admin","password":"e7cf3ef4f17c3999a94f2c6f612e8a888e5b1026878e4e19398b23bd38ec221a"},
}
public authenticate() {
this.messages.next(this.authenticateMessage);
}
constructor(wsService: WebsocketService) {
this.messages = <Subject<Message>>wsService
.connect(WEBSOCKET_URL)
.map((response: MessageEvent): Message => {
let data = JSON.parse(response.data);
// variables aren't consistent yet. Here's a hack!
var dataData = data.Data === undefined ? data.data : data.Data;
var eventEvent = data.Event === undefined ? data.event : data.Event;
return {
Event: eventEvent,
data: dataData,
Exchange: data.exchange,
AssetType: data.assetType
}
});
}
}

View File

@@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { WebsocketResponseHandlerService } from './websocket-response-handler.service';
describe('WebsocketHandlerService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [WebsocketResponseHandlerService]
});
});
it('should be created', inject([WebsocketResponseHandlerService], (service: WebsocketResponseHandlerService) => {
expect(service).toBeTruthy();
}));
});

View File

@@ -0,0 +1,37 @@
import { NgModule, Injectable, Optional, SkipSelf } from '@angular/core';
import { Observable, Subject } from 'rxjs/Rx';
import { WebsocketService } from './../../services/websocket/websocket.service';
import { WebSocketMessage } from './../../shared/classes/websocket';
const WEBSOCKET_URL = 'ws://localhost:9050/ws';
@NgModule({
})
export class WebsocketResponseHandlerService {
public messages: Subject<any>;
public shared: Observable<WebSocketMessage>;
public isConnected :boolean = false;
constructor(@Optional() @SkipSelf() parentModule: WebsocketResponseHandlerService, wsService: WebsocketService) {
this.messages = <Subject<WebSocketMessage>>wsService
.connect(WEBSOCKET_URL)
.map((response: MessageEvent): WebSocketMessage => {
this.isConnected = wsService.isConnected;
let websocketResponseMessage = JSON.parse(response.data);
var websocketResponseData = websocketResponseMessage.Data === undefined ? websocketResponseMessage.data : websocketResponseMessage.Data;
var websocketResponseEvent = websocketResponseMessage.Event === undefined ? websocketResponseMessage.event : websocketResponseMessage.Event;
let responseMessage = new WebSocketMessage();
responseMessage.event = websocketResponseEvent;
responseMessage.data = websocketResponseData;
responseMessage.exchange = websocketResponseMessage.exchange;
responseMessage.assetType = websocketResponseMessage.assetType;
return responseMessage;
});
this.isConnected = wsService.isConnected;
this.shared = this.messages.share(); //multicast
}
}

View File

@@ -1,45 +1,62 @@
import { Injectable } from '@angular/core';
import {Subject, Observable, Observer } from 'rxjs/Rx';
import { Injectable, Optional, SkipSelf, NgModule } from '@angular/core';
import { Subject, Observable, Observer } from 'rxjs/Rx';
import { WebSocketMessage } from './../../shared/classes/websocket';
@Injectable()
@NgModule()
export class WebsocketService {
constructor() { }
public isConnected :boolean = false;
constructor (@Optional() @SkipSelf() parentModule: WebsocketService) {
if (parentModule) {
throw new Error(
'WebsocketService is already loaded. Import it in the AppModule only');
}
}
private subject: Subject<MessageEvent>;
public connect(url): Subject<MessageEvent> {
if (!this.subject) {
this.subject = this.create(url);
}
}
return this.subject;
}
private authenticateMessage = {
Event:'auth',
data:{"username":"admin","password":"e7cf3ef4f17c3999a94f2c6f612e8a888e5b1026878e4e19398b23bd38ec221a"},
}
private isAuth = false;
private create(url): Subject<MessageEvent> {
let ws = new WebSocket(url);
let observable = Observable.create(
(obs: Observer<MessageEvent>) => {
ws.onmessage = obs.next.bind(obs);
ws.onerror = obs.error.bind(obs);
ws.onclose = obs.complete.bind(obs);
return ws.close.bind(ws);
})
let observer = {
next: (data: any) => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(this.authenticateMessage));
ws.send(JSON.stringify(data));
(obs: Observer<MessageEvent>) => {
ws.onmessage = obs.next.bind(obs);
ws.onerror = obs.error.bind(obs);
ws.onclose = () => {
this.isConnected = false;
obs.complete.bind(obs) };
ws.onopen = () => {
this.isConnected = true;
ws.send(JSON.stringify(WebSocketMessage.CreateAuthenticationMessage()));
};
return ws.close.bind(ws);
})
let observer = {
next: (data: any) => {
var counter = 0;
var interval = setInterval(() => {
if (counter == 10) {
clearInterval(interval);
}
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(data));
clearInterval(interval);
this.isConnected = true;
}
counter++;
}, 400);
if (ws.readyState !== WebSocket.OPEN) {
new Error("Failed to send message to websocket after 10 attempts");
this.isConnected = false;
}
}
}
}
return Subject.create(observer, observable);
}
return Subject.create(observer, observable);
}
}