diff --git a/src/js/actions/Web3Actions.js b/src/js/actions/Web3Actions.js index e36387e7..e970c85d 100644 --- a/src/js/actions/Web3Actions.js +++ b/src/js/actions/Web3Actions.js @@ -21,6 +21,7 @@ import type { } from '../flowtype'; import type { ContractFactory } from 'web3'; +import type { BigNumber } from 'bignumber.js'; import type { Account } from '../reducers/AccountsReducer'; import type { PendingTx } from '../reducers/PendingTxReducer'; import type { Web3Instance } from '../reducers/Web3Reducer'; @@ -53,7 +54,7 @@ export type Web3UpdateGasPriceAction = { }; -export function init(web3: ?Web3, coinIndex: number = 0): AsyncAction { +export function init(instance: ?Web3, coinIndex: number = 0): AsyncAction { return async (dispatch: Dispatch, getState: GetState): Promise => { const { config, ERC20Abi } = getState().localStorage; @@ -72,20 +73,20 @@ export function init(web3: ?Web3, coinIndex: number = 0): AsyncAction { let web3host: string = urls[0]; - if (web3) { - const currentHost = web3.currentProvider.host; + if (instance) { + const currentHost = instance.currentProvider.host; let currentHostIndex: number = urls.indexOf(currentHost); if (currentHostIndex + 1 < urls.length) { web3host = urls[currentHostIndex + 1]; } else { - console.error("TODO: Backend " + network + " not working", web3.currentProvider ); + console.error("TODO: Backend " + network + " not working", instance.currentProvider ); dispatch({ type: WEB3.CREATE, network, - web3, - erc20: web3.eth.contract(ERC20Abi), + web3: instance, + erc20: instance.eth.contract(ERC20Abi), chainId: '0' }); @@ -96,7 +97,7 @@ export function init(web3: ?Web3, coinIndex: number = 0): AsyncAction { } //const instance = new Web3(window.web3.currentProvider); - const instance = new Web3( new Web3.providers.HttpProvider(web3host) ); + const web3 = new Web3( new Web3.providers.HttpProvider(web3host) ); // instance = new Web3( new Web3.providers.HttpProvider('https://pyrus2.ubiqscan.io') ); // UBQ //instance = new Web3( new Web3.providers.HttpProvider('https://node.expanse.tech/') ); // EXP @@ -106,95 +107,109 @@ export function init(web3: ?Web3, coinIndex: number = 0): AsyncAction { //instance = new Web3(new Web3.providers.HttpProvider("https://ropsten.infura.io2/QGyVKozSUEh2YhL4s2G4")); //web3 = new Web3( new Web3.providers.HttpProvider("ws://34.230.234.51:30303") ); + // initial check if backend is running - - instance.eth.getGasPrice((error: Error, gasPrice: string) => { - if (error) { - // try different url - dispatch( init(instance, coinIndex) ); - } else { + if (!web3.currentProvider.isConnected()) { + // try different url + dispatch( init(web3, coinIndex) ); + return; + } - const erc20 = instance.eth.contract(ERC20Abi); + const erc20 = web3.eth.contract(ERC20Abi); - dispatch({ - type: WEB3.CREATE, - network, - web3: instance, - erc20, - chainId: instance.version.network - }); + dispatch({ + type: WEB3.CREATE, + network, + web3: web3, + erc20, + chainId: web3.version.network + }); - dispatch({ - type: WEB3.GAS_PRICE_UPDATED, - network, - gasPrice - }); + // dispatch({ + // type: WEB3.GAS_PRICE_UPDATED, + // network, + // gasPrice + // }); - // console.log("GET CHAIN", instance.version.network) + // console.log("GET CHAIN", instance.version.network) - // instance.version.getWhisper((err, shh) => { - // console.log("-----whisperrr", error, shh) - // }) - + // instance.version.getWhisper((err, shh) => { + // console.log("-----whisperrr", error, shh) + // }) + - // const sshFilter = instance.ssh.filter('latest'); - // sshFilter.watch((error, blockHash) => { - // console.warn("SSH", error, blockHash); - // }); + // const sshFilter = instance.ssh.filter('latest'); + // sshFilter.watch((error, blockHash) => { + // console.warn("SSH", error, blockHash); + // }); - //const shh = instance.shh.newIdentity(); + //const shh = instance.shh.newIdentity(); - const latestBlockFilter = instance.eth.filter('latest'); + const latestBlockFilter = web3.eth.filter('latest'); - const onBlockMined = async (error: ?Error, blockHash: ?string) => { - if (error) { + const onBlockMined = async (error: ?Error, blockHash: ?string) => { + if (error) { - window.setTimeout(() => { - // try again - onBlockMined(new Error("manually_triggered_error"), undefined); - }, 30000); - } + // window.setTimeout(() => { + // // try again + // onBlockMined(new Error("manually_triggered_error"), undefined); + // }, 30000); + } - if (blockHash) { - dispatch({ - type: WEB3.BLOCK_UPDATED, - network, - blockHash - }); - } + if (blockHash) { + dispatch({ + type: WEB3.BLOCK_UPDATED, + network, + blockHash + }); + } - // TODO: filter only current device - const accounts = getState().accounts.filter(a => a.network === network); - for (const addr of accounts) { - dispatch( getBalance(addr) ); - dispatch( getNonce(addr) ); - } + // TODO: filter only current device + const accounts = getState().accounts.filter(a => a.network === network); + for (const account of accounts) { + const nonce = await getNonceAsync(web3, account.address); + if (nonce !== account.nonce) { + dispatch({ + type: ADDRESS.SET_NONCE, + address: account.address, + network: account.network, + nonce + }); - const tokens = getState().tokens.filter(t => t.network === network); - for (const token of tokens) { - dispatch( getTokenBalance(token) ); - } + dispatch( getBalance(account) ); + // TODO: check if nonce was updated, + // update tokens balance, + // update account balance, + // update pending transactions + } + + // dispatch( getNonce(account) ); + + } - dispatch( getGasPrice(network) ); + const tokens = getState().tokens.filter(t => t.network === network); + for (const token of tokens) { + dispatch( getTokenBalance(token) ); + } - const pending = getState().pending.filter(p => p.network === network); - for (const tx of pending) { - dispatch( getTransactionReceipt(tx) ); - } + dispatch( getGasPrice(network) ); - } + const pending = getState().pending.filter(p => p.network === network); + for (const tx of pending) { + dispatch( getTransactionReceipt(tx) ); + } - latestBlockFilter.watch(onBlockMined); + } + latestBlockFilter.watch(onBlockMined); - // init next coin - dispatch( init(instance, coinIndex + 1) ); - } - }); + // init next coin + dispatch( init(web3, coinIndex + 1) ); + // let instance2 = new Web3( new Web3.providers.HttpProvider('https://pyrus2.ubiqscan.io') ); // console.log("INIT WEB3", instance, instance2); @@ -205,45 +220,6 @@ export function init(web3: ?Web3, coinIndex: number = 0): AsyncAction { } -// export function initContracts(): AsyncAction { -// return async (dispatch: Dispatch, getState: GetState): Promise => { -// const { web3, abi, tokens } = getState().web3; - -// const contracts = []; -// for (let token of tokens) { -// contracts.push({ -// contract: web3.eth.contract(abi).at(token.address), -// name: token.name, -// symbol: token.symbol, -// decimal: token.decimal -// }); - -// // web3.eth.contract(abi).at(token.address).balanceOf('0x98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad', (e, r) => { -// // console.warn('contrR', e, r.toString(10)); -// // }); -// } - -// const contract = web3.eth.contract(abi).at('0x58cda554935e4a1f2acbe15f8757400af275e084'); - -// contract.name.call((error, name) => { -// if (error) { -// // TODO: skip -// } -// contract.symbol.call((error, symbol) => { -// if (error) { -// // TODO: skip -// } - -// contract.decimals.call((error, decimals) => { -// }) -// }); - - -// }) -// } -// } - - export function getGasPrice(network: string): AsyncAction { return async (dispatch: Dispatch, getState: GetState): Promise => { @@ -271,7 +247,7 @@ export function getBalance(account: Account): AsyncAction { const web3instance = getState().web3.filter(w3 => w3.network === account.network)[0]; const web3: Web3 = web3instance.web3; - web3.eth.getBalance(account.address, (error, balance) => { + web3.eth.getBalance(account.address, (error: Error, balance: BigNumber) => { if (!error) { const newBalance: string = web3.fromWei(balance.toString(), 'ether'); if (account.balance !== newBalance) { @@ -295,8 +271,6 @@ export function getTokenBalance(token: Token): AsyncAction { const web3 = web3instance.web3; const contract = web3instance.erc20.at(token.address); - console.warn("Get bal", token) - contract.balanceOf(token.ethAddress, (error: ?Error, balance: ?BigNumber) => { if (balance) { const newBalance: string = balance.dividedBy( Math.pow(10, token.decimals) ).toString(); @@ -307,8 +281,6 @@ export function getTokenBalance(token: Token): AsyncAction { newBalance )); } - console.log("BALANCE!", balance, newBalance); - } }); } @@ -422,35 +394,34 @@ export const getNonceAsync = (web3: Web3, address: string): Promise => { } -export const getTokenInfoAsync = (erc20: any, address: string): Promise => { +export const getTokenInfoAsync = (erc20: ContractFactory, address: string): Promise => { return new Promise((resolve, reject) => { const contract = erc20.at(address, (error, res) => { - console.warn("callack", error, res) + console.warn("callback", error, res) }); - console.warn("AT", contract) const info = {}; // TODO: handle errors - contract.name.call((e, name) => { - if (e) { + contract.name.call((error: ?Error, name: ?string) => { + if (error) { //resolve(null); //return; } info.name = name; - contract.symbol.call((e, symbol) => { - if (e) { + contract.symbol.call((error: ?Error, symbol: ?string) => { + if (error) { resolve(null); return; } info.symbol = symbol; - contract.decimals.call((e, decimals) => { - if (e) { + contract.decimals.call((error: ?Error, decimals: ?BigNumber) => { + if (decimals) { + info.decimals = decimals.toString(); + resolve(info); + } else { resolve(null); - return; } - info.decimals = decimals.toString(); - resolve(info); }); }) }); diff --git a/src/js/flowtype/web3.js b/src/js/flowtype/web3.js index 1ce4bc79..0f76b487 100644 --- a/src/js/flowtype/web3.js +++ b/src/js/flowtype/web3.js @@ -64,11 +64,17 @@ declare module 'web3' { } declare export class Contract { - name: (callback: (error: Error, name: string) => void) => void; - symbol: (callback: (error: Error, symbol: string) => void) => void; - decimals: (callback: (error: Error, decimals: BigNumber) => void) => void; - balanceOf: (address: string, callback: (error: Error, balance: BigNumber) => void) => void; - transfer: any; + name: { + call: (callback: (error: Error, name: string) => void) => void; + }, + symbol: { + call: (callback: (error: Error, symbol: string) => void) => void; + }, + decimals: { + call: (callback: (error: Error, decimals: BigNumber) => void) => void; + }, + balanceOf: (address: string, callback: (error: Error, balance: BigNumber) => void) => void, + transfer: any, } declare export default typeof Web3T;