summaryrefslogtreecommitdiffhomepage
path: root/app/lib/ipc-facade.js
blob: 19daf71b97c2d71a4be9435b3626343ae60d68b2 (plain)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// @flow

import JsonRpcWs, { InvalidReply } from './jsonrpc-ws-ipc';
import { object, string, number, arrayOf } from 'validated/schema';
import { validate } from 'validated/object';

export type AccountData = {paid_until: string};
export type AccountNumber = string;
export type Ip = string;
export type Location = {
  latlong: Array<number>,
  country: string,
  city: string,
};
const LocationSchema = object({
  latlong: arrayOf(number),
  country: string,
  city: string,
});

export type BackendState = 'secured' | 'unsecured';

export interface IpcFacade {
  getAccountData(AccountNumber): Promise<AccountData>,
  setAccount(accountNumber: AccountNumber): Promise<void>,
  setCountry(address: string): Promise<void>,
  connect(): Promise<void>,
  disconnect(): Promise<void>,
  getIp(): Promise<Ip>,
  getLocation(): Promise<Location>,
  getState(): Promise<BackendState>,
  registerStateListener((BackendState) => void): void,
}

export class RealIpc implements IpcFacade {

  _ipc: JsonRpcWs;

  constructor(connectionString: string) {
    this._ipc = new JsonRpcWs(connectionString);
  }

  getAccountData(accountNumber: AccountNumber): Promise<AccountData> {
    return this._ipc.send('get_account_data', accountNumber)
      .then(raw => {
        if (typeof raw === 'object' && raw && raw.paid_until) {
          return raw;
        } else {
          throw new InvalidReply(raw, 'Expected an object with paid_until');
        }
      });
  }

  setAccount(accountNumber: AccountNumber): Promise<void> {
    return this._ipc.send('set_account', accountNumber)
      .then(this._ignoreResponse);
  }

  _ignoreResponse(_response: mixed): void {
    return;
  }

  setCountry(address: string): Promise<void> {
    return this._ipc.send('set_country', address)
      .then(this._ignoreResponse);
  }

  connect(): Promise<void> {
    return this._ipc.send('connect')
      .then(this._ignoreResponse);
  }

  disconnect(): Promise<void> {
    return this._ipc.send('disconnect')
      .then(this._ignoreResponse);
  }

  getIp(): Promise<Ip> {
    return this._ipc.send('get_ip')
      .then(raw => {
        if (typeof raw === 'string' && raw) {
          return raw;
        } else {
          throw new InvalidReply(raw, 'Expected a string');
        }
      });
  }

  getLocation(): Promise<Location> {
    return this._ipc.send('get_location')
      .then(raw => {
        try {
          return validate(LocationSchema, raw);
        } catch (e) {
          throw new InvalidReply(raw, e);
        }
      });
  }

  getState(): Promise<BackendState> {
    return this._ipc.send('get_state')
      .then(raw => {
        return this._parseBackendState(raw);
      });
  }

  _parseBackendState(raw: mixed): BackendState {
    if (raw === 'secured' || raw === 'unsecured') {
      return raw;
    } else {
      throw new InvalidReply(raw);
    }
  }

  registerStateListener(listener: (BackendState) => void) {
    this._ipc.on('new_state', (rawEvent) => {
      const parsedEvent : BackendState = this._parseBackendState(rawEvent);

      listener(parsedEvent);
    });
  }
}