blob: 24279f5d2d52e622bdd37346e12808940d068195 (
plain) (
blame)
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
import * as _ from 'lodash';
import Web3 = require('web3');
import BigNumber from 'bignumber.js';
import promisify = require('es6-promisify');
import {Dispatcher} from 'ts/redux/dispatcher';
export class Web3Wrapper {
private dispatcher: Dispatcher;
private web3: Web3;
private prevNetworkId: number;
private shouldPollUserAddress: boolean;
private watchNetworkAndBalanceIntervalId: number;
private prevUserEtherBalanceInEth: BigNumber;
private prevUserAddress: string;
constructor(dispatcher: Dispatcher, provider: Web3.Provider, networkIdIfExists: number,
shouldPollUserAddress: boolean) {
this.dispatcher = dispatcher;
this.prevNetworkId = networkIdIfExists;
this.shouldPollUserAddress = shouldPollUserAddress;
this.web3 = new Web3();
this.web3.setProvider(provider);
this.startEmittingNetworkConnectionAndUserBalanceStateAsync();
}
public isAddress(address: string) {
return this.web3.isAddress(address);
}
public async getAccountsAsync(): Promise<string[]> {
const addresses = await promisify(this.web3.eth.getAccounts)();
return addresses;
}
public async getFirstAccountIfExistsAsync() {
const addresses = await this.getAccountsAsync();
if (_.isEmpty(addresses)) {
return '';
}
return (addresses as string[])[0];
}
public async getNodeVersionAsync() {
const nodeVersion = await promisify(this.web3.version.getNode)();
return nodeVersion;
}
public getProviderObj() {
return this.web3.currentProvider;
}
public async getNetworkIdIfExists() {
try {
const networkId = await this.getNetworkAsync();
return Number(networkId);
} catch (err) {
return undefined;
}
}
public async getBalanceInEthAsync(owner: string): Promise<BigNumber> {
const balanceInWei: BigNumber = await promisify(this.web3.eth.getBalance)(owner);
const balanceEthOldBigNumber = this.web3.fromWei(balanceInWei, 'ether');
const balanceEth = new BigNumber(balanceEthOldBigNumber);
return balanceEth;
}
public async doesContractExistAtAddressAsync(address: string): Promise<boolean> {
const code = await promisify(this.web3.eth.getCode)(address);
// Regex matches 0x0, 0x00, 0x in order to accomodate poorly implemented clients
const zeroHexAddressRegex = /^0[xX][0]*$/;
const didFindCode = _.isNull(code.match(zeroHexAddressRegex));
return didFindCode;
}
public async signTransactionAsync(address: string, message: string): Promise<string> {
const signData = await promisify(this.web3.eth.sign)(address, message);
return signData;
}
public async getBlockTimestampAsync(blockHash: string): Promise<number> {
const {timestamp} = await promisify(this.web3.eth.getBlock)(blockHash);
return timestamp;
}
public destroy() {
this.stopEmittingNetworkConnectionAndUserBalanceStateAsync();
// HACK: stop() is only available on providerEngine instances
const provider = this.web3.currentProvider;
if (!_.isUndefined((provider as any).stop)) {
(provider as any).stop();
}
}
// This should only be called from the LedgerConfigDialog
public updatePrevUserAddress(userAddress: string) {
this.prevUserAddress = userAddress;
}
private async getNetworkAsync() {
const networkId = await promisify(this.web3.version.getNetwork)();
return networkId;
}
private async startEmittingNetworkConnectionAndUserBalanceStateAsync() {
if (!_.isUndefined(this.watchNetworkAndBalanceIntervalId)) {
return; // we are already emitting the state
}
let prevNodeVersion: string;
this.prevUserEtherBalanceInEth = new BigNumber(0);
this.dispatcher.updateNetworkId(this.prevNetworkId);
this.watchNetworkAndBalanceIntervalId = window.setInterval(async () => {
// Check for network state changes
const currentNetworkId = await this.getNetworkIdIfExists();
if (currentNetworkId !== this.prevNetworkId) {
this.prevNetworkId = currentNetworkId;
this.dispatcher.updateNetworkId(currentNetworkId);
}
// Check for node version changes
const currentNodeVersion = await this.getNodeVersionAsync();
if (currentNodeVersion !== prevNodeVersion) {
prevNodeVersion = currentNodeVersion;
this.dispatcher.updateNodeVersion(currentNodeVersion);
}
if (this.shouldPollUserAddress) {
const userAddressIfExists = await this.getFirstAccountIfExistsAsync();
// Update makerAddress on network change
if (this.prevUserAddress !== userAddressIfExists) {
this.prevUserAddress = userAddressIfExists;
this.dispatcher.updateUserAddress(userAddressIfExists);
}
// Check for user ether balance changes
if (userAddressIfExists !== '') {
await this.updateUserEtherBalanceAsync(userAddressIfExists);
}
} else {
// This logic is primarily for the Ledger, since we don't regularly poll for the address
// we simply update the balance for the last fetched address.
if (!_.isEmpty(this.prevUserAddress)) {
await this.updateUserEtherBalanceAsync(this.prevUserAddress);
}
}
}, 5000);
}
private async updateUserEtherBalanceAsync(userAddress: string) {
const balance = await this.getBalanceInEthAsync(userAddress);
if (!balance.eq(this.prevUserEtherBalanceInEth)) {
this.prevUserEtherBalanceInEth = balance;
this.dispatcher.updateUserEtherBalance(balance);
}
}
private stopEmittingNetworkConnectionAndUserBalanceStateAsync() {
clearInterval(this.watchNetworkAndBalanceIntervalId);
}
}
|