1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const ilp_compat_plugin_1 = require("ilp-compat-plugin");
|
4 | const store_1 = require("../services/store");
|
5 | const config_1 = require("./config");
|
6 | const events_1 = require("events");
|
7 | const ILDCP = require("ilp-protocol-ildcp");
|
8 | const log_1 = require("../common/log");
|
9 | const log = log_1.create('accounts');
|
10 | class Accounts extends events_1.EventEmitter {
|
11 | constructor(deps) {
|
12 | super();
|
13 | this.config = deps(config_1.default);
|
14 | this.store = deps(store_1.default);
|
15 | this.address = this.config.ilpAddress || 'unknown';
|
16 | this.accounts = new Map();
|
17 | }
|
18 | async loadIlpAddress() {
|
19 | const inheritFrom = this.config.ilpAddressInheritFrom ||
|
20 | [...this.accounts]
|
21 | .filter(([key, value]) => value.info.relation === 'parent')
|
22 | .map(([key]) => key)[0];
|
23 | if (this.config.ilpAddress === 'unknown' && !inheritFrom) {
|
24 | throw new Error('When there is no parent, ILP address must be specified in configuration.');
|
25 | }
|
26 | else if (this.config.ilpAddress === 'unknown' && inheritFrom) {
|
27 | const parent = this.getPlugin(inheritFrom);
|
28 | log.trace('connecting to parent. accountId=%s', inheritFrom);
|
29 | await parent.connect({});
|
30 | const ildcpInfo = await ILDCP.fetch(parent.sendData.bind(parent));
|
31 | this.setOwnAddress(ildcpInfo.clientAddress);
|
32 | if (this.address === 'unknown') {
|
33 | log.error('could not get ilp address from parent.');
|
34 | throw new Error('no ilp address configured.');
|
35 | }
|
36 | }
|
37 | }
|
38 | async connect(options) {
|
39 | const unconnectedAccounts = Array.from(this.accounts.values())
|
40 | .filter(account => !account.plugin.isConnected());
|
41 | return Promise.all(unconnectedAccounts.map(account => account.plugin.connect(options)));
|
42 | }
|
43 | async disconnect() {
|
44 | const connectedAccounts = Array.from(this.accounts.values())
|
45 | .filter(account => account.plugin.isConnected());
|
46 | return Promise.all(connectedAccounts.map(account => account.plugin.disconnect()));
|
47 | }
|
48 | getOwnAddress() {
|
49 | return this.address;
|
50 | }
|
51 | setOwnAddress(newAddress) {
|
52 | log.trace('setting ilp address. oldAddress=%s newAddress=%s', this.address, newAddress);
|
53 | this.address = newAddress;
|
54 | }
|
55 | getPlugin(accountId) {
|
56 | const account = this.accounts.get(accountId);
|
57 | if (!account) {
|
58 | log.error('could not find plugin for account id. accountId=%s', accountId);
|
59 | throw new Error('unknown account id. accountId=' + accountId);
|
60 | }
|
61 | return account.plugin;
|
62 | }
|
63 | exists(accountId) {
|
64 | return this.accounts.has(accountId);
|
65 | }
|
66 | getAccountIds() {
|
67 | return Array.from(this.accounts.keys());
|
68 | }
|
69 | getAssetCode(accountId) {
|
70 | const account = this.accounts.get(accountId);
|
71 | if (!account) {
|
72 | log.error('no currency found. account=%s', accountId);
|
73 | return undefined;
|
74 | }
|
75 | return account.info.assetCode;
|
76 | }
|
77 | add(accountId, creds) {
|
78 | log.info('add account. accountId=%s', accountId);
|
79 | try {
|
80 | this.config.validateAccount(accountId, creds);
|
81 | }
|
82 | catch (err) {
|
83 | if (err.name === 'InvalidJsonBodyError') {
|
84 | log.error('validation error in account config. id=%s', accountId);
|
85 | err.debugPrint(log.warn.bind(log));
|
86 | throw new Error('error while adding account, see error log for details.');
|
87 | }
|
88 | throw err;
|
89 | }
|
90 | const plugin = this.getPluginFromCreds(accountId, creds);
|
91 | this.accounts.set(accountId, {
|
92 | info: creds,
|
93 | plugin
|
94 | });
|
95 | this.emit('add', accountId, plugin);
|
96 | }
|
97 | remove(accountId) {
|
98 | const plugin = this.getPlugin(accountId);
|
99 | if (!plugin) {
|
100 | return undefined;
|
101 | }
|
102 | log.info('remove account. accountId=' + accountId);
|
103 | this.emit('remove', accountId, plugin);
|
104 | this.accounts.delete(accountId);
|
105 | return plugin;
|
106 | }
|
107 | getInfo(accountId) {
|
108 | const account = this.accounts.get(accountId);
|
109 | if (!account) {
|
110 | throw new Error('unknown account id. accountId=' + accountId);
|
111 | }
|
112 | return account.info;
|
113 | }
|
114 | getChildAddress(accountId) {
|
115 | const info = this.getInfo(accountId);
|
116 | if (info.relation !== 'child') {
|
117 | throw new Error('Can\'t generate child address for account that is isn\'t a child');
|
118 | }
|
119 | const ilpAddressSegment = info.ilpAddressSegment || accountId;
|
120 | return this.address + '.' + ilpAddressSegment;
|
121 | }
|
122 | getStatus() {
|
123 | const accounts = {};
|
124 | this.accounts.forEach((account, accountId) => {
|
125 | accounts[accountId] = {
|
126 | info: Object.assign({}, account.info, { options: undefined }),
|
127 | connected: account.plugin.isConnected(),
|
128 | adminInfo: !!account.plugin.getAdminInfo
|
129 | };
|
130 | });
|
131 | return {
|
132 | address: this.address,
|
133 | accounts
|
134 | };
|
135 | }
|
136 | getPluginFromCreds(accountId, creds) {
|
137 | if (typeof creds.plugin === 'object')
|
138 | return creds.plugin;
|
139 | const Plugin = require(creds.plugin);
|
140 | const api = {
|
141 | store: this.store.getPluginStore(accountId),
|
142 | log: log_1.create(`${creds.plugin}[${accountId}]`)
|
143 | };
|
144 | const opts = Object.assign({
|
145 | _store: api.store,
|
146 | _log: api.log
|
147 | }, creds.options);
|
148 | return ilp_compat_plugin_1.default(new Plugin(opts, api));
|
149 | }
|
150 | }
|
151 | exports.default = Accounts;
|
152 |
|
\ | No newline at end of file |