From f70c1ff009385266d694269c2c4dd0e9fb38dc46 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 26 Jun 2018 11:01:50 -0700 Subject: Ledger to metamask to ledger working --- packages/website/ts/blockchain.ts | 51 ++++++++++++++---------- packages/website/ts/blockchain_watcher.ts | 19 --------- packages/website/ts/components/portal/portal.tsx | 7 ++-- 3 files changed, 35 insertions(+), 42 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 16ed8d03a..d55cb6771 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -121,19 +121,18 @@ export class Blockchain { injectedWeb3: Web3, networkIdIfExists: number, userLedgerProvider: boolean = false, - ): Promise { + ): Promise<[Provider, LedgerSubprovider]> { const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3); const isNetworkIdDefined = !_.isUndefined(networkIdIfExists); const publicNodeUrlsIfExistsForNetworkId = configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkIdIfExists]; const isPublicNodeAvailableForNetworkId = !_.isUndefined(publicNodeUrlsIfExistsForNetworkId); - let provider; if (userLedgerProvider && isNetworkIdDefined) { const isU2FSupported = await utils.isU2FSupportedAsync(); if (!isU2FSupported) { throw new Error('Cannot update providerType to LEDGER without U2F support'); } - provider = new ProviderEngine(); + const provider = new ProviderEngine(); const ledgerWalletConfigs = { networkId: networkIdIfExists, ledgerEthereumClientFactoryAsync: ledgerEthereumBrowserClientFactoryAsync, @@ -148,10 +147,11 @@ export class Blockchain { }); provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); provider.start(); + return [provider, ledgerSubprovider]; } else if (doesInjectedWeb3Exist && isPublicNodeAvailableForNetworkId) { // We catch all requests involving a users account and send it to the injectedWeb3 // instance. All other requests go to the public hosted node. - provider = new ProviderEngine(); + const provider = new ProviderEngine(); provider.addProvider(new InjectedWeb3Subprovider(injectedWeb3.currentProvider)); provider.addProvider(new FilterSubprovider()); const rpcSubproviders = _.map(publicNodeUrlsIfExistsForNetworkId, publicNodeUrl => { @@ -161,14 +161,15 @@ export class Blockchain { }); provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); provider.start(); + return [provider, undefined]; } else if (doesInjectedWeb3Exist) { // Since no public node for this network, all requests go to injectedWeb3 instance - provider = injectedWeb3.currentProvider; + return [injectedWeb3.currentProvider, undefined]; } else { // If no injectedWeb3 instance, all requests fallback to our public hosted mainnet/testnet node // We do this so that users can still browse the 0x Portal DApp even if they do not have web3 // injected into their browser. - provider = new ProviderEngine(); + const provider = new ProviderEngine(); provider.addProvider(new FilterSubprovider()); const networkId = Blockchain._getFallbackNetworkId(); const rpcSubproviders = _.map(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId], publicNodeUrl => { @@ -178,9 +179,8 @@ export class Blockchain { }); provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); provider.start(); + return [provider, undefined]; } - - return provider; } constructor(dispatcher: Dispatcher) { this._dispatcher = dispatcher; @@ -243,6 +243,9 @@ export class Blockchain { public async updateProviderToInjectedAsync(): Promise { const shouldPollUserAddress = true; const userLedgerProvider = false; + this._dispatcher.updateBlockchainIsLoaded(false); + // We don't want to be out of sync with the network metamask declares. + const networkId = await Blockchain._getInjectedWeb3ProviderNetworkIdIfExistsAsync(); await this._resetOrInitializeAsync(this.networkId, shouldPollUserAddress, userLedgerProvider); } public async setProxyAllowanceAsync(token: Token, amountInBaseUnits: BigNumber): Promise { @@ -614,8 +617,7 @@ export class Blockchain { return !_.isUndefined(this._userAddressIfExists); } private async _handleInjectedProviderUpdateAsync(update: InjectedProviderUpdate): Promise { - if (update.networkVersion === 'loading') { - // Who comes up with this stuff. + if (update.networkVersion === 'loading' || !_.isUndefined(this._ledgerSubprovider)) { return; } const updatedNetworkId = _.parseInt(update.networkVersion); @@ -778,6 +780,7 @@ export class Blockchain { this._injectedProviderObservable.subscribe(this._handleInjectedProviderUpdateAsync.bind(this)); } } + this._updateProviderName(injectedWeb3); const shouldPollUserAddress = true; const shouldUseLedger = false; await this._resetOrInitializeAsync(this.networkId, shouldPollUserAddress, shouldUseLedger); @@ -787,15 +790,20 @@ export class Blockchain { shouldPollUserAddress: boolean = false, useLedgerProvider: boolean = false, ): Promise { + this._dispatcher.updateBlockchainIsLoaded(false); + this._dispatcher.updateUserWeiBalance(undefined); this.networkId = networkId; - this._dispatcher.updateNetworkId(networkId); const injectedWeb3 = Blockchain._getInjectedWeb3(); - const provider = await Blockchain._getProviderAsync(injectedWeb3, networkId, useLedgerProvider); - // if (!_.isUndefined(this._contractWrappers)) { - // this._contractWrappers.setProvider(provider, networkId); - // } else { - // } - this._contractWrappers = new ContractWrappers(provider, { networkId }); + const [provider, ledgerSubproviderIfExists] = await Blockchain._getProviderAsync( + injectedWeb3, + networkId, + useLedgerProvider, + ); + if (!_.isUndefined(this._contractWrappers)) { + this._contractWrappers.setProvider(provider, networkId); + } else { + this._contractWrappers = new ContractWrappers(provider, { networkId }); + } if (!_.isUndefined(this._blockchainWatcher)) { this._blockchainWatcher.destroy(); } @@ -806,9 +814,10 @@ export class Blockchain { this.networkId, shouldPollUserAddress, ); - if (useLedgerProvider) { + if (useLedgerProvider && !_.isUndefined(ledgerSubproviderIfExists)) { // TODO: why? delete this._userAddressIfExists; + this._ledgerSubprovider = ledgerSubproviderIfExists; this._dispatcher.updateUserAddress(undefined); this._dispatcher.updateProviderType(ProviderType.Ledger); } else { @@ -816,11 +825,13 @@ export class Blockchain { const userAddresses = await this._web3Wrapper.getAvailableAddressesAsync(); this._userAddressIfExists = userAddresses[0]; this._dispatcher.updateUserAddress(this._userAddressIfExists); - this._updateProviderName(injectedWeb3); + if (!_.isUndefined(injectedWeb3)) { + this._dispatcher.updateProviderType(ProviderType.Injected); + } } - // TOOD: should not call this in ledger case? await this.fetchTokenInformationAsync(); await this._blockchainWatcher.startEmittingUserBalanceStateAsync(); + this._dispatcher.updateNetworkId(networkId); await this._rehydrateStoreWithContractEventsAsync(); } private _updateProviderName(injectedWeb3: Web3): void { diff --git a/packages/website/ts/blockchain_watcher.ts b/packages/website/ts/blockchain_watcher.ts index 5d029d4f1..4112c8a15 100644 --- a/packages/website/ts/blockchain_watcher.ts +++ b/packages/website/ts/blockchain_watcher.ts @@ -35,16 +35,6 @@ export class BlockchainWatcher { public updatePrevUserAddress(userAddress: string): void { this._prevUserAddressIfExists = userAddress; } - // public async startEmittingInjectedProviderNetworkIdAsync(injectedProvider: any): Promise { - // if (this._isWatchingNetworkId) { - // return; // we are already watching the network id - // } - // const observable = injectedProvider.publicConfigStore; - // if (observable && observable.subscribe) { - // observable.subscribe(this._handleInjectedProviderUpdate.bind(this)); - // this._isWatchingNetworkId = true; - // } - // } public async startEmittingUserBalanceStateAsync(): Promise { if (!_.isUndefined(this._watchBalanceIntervalId)) { return; // we are already emitting the state @@ -60,15 +50,6 @@ export class BlockchainWatcher { }, ); } - // private _handleInjectedProviderUpdate(update: InjectedProviderUpdate): void { - // const updatedNetworkId = _.parseInt(update.networkVersion); - // if (this._prevNetworkId === updatedNetworkId) { - // return; - // } - // this._prevNetworkId = updatedNetworkId; - // this._dispatcher.updateNetworkId(updatedNetworkId); - // this._updateBalanceAsync(); - // } private async _updateBalanceAsync(): Promise { let prevNodeVersion: string; // Check for node version changes diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index 58acb435e..bb88e3824 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -182,9 +182,10 @@ export class Portal extends React.Component { prevPathname: nextProps.location.pathname, }); } + + // If the address changed, but the network did not, we can just refetch the currently tracked tokens. if ( - nextProps.userAddress !== this.props.userAddress || - nextProps.networkId !== this.props.networkId || + (nextProps.userAddress !== this.props.userAddress && nextProps.networkId === this.props.networkId) || nextProps.lastForceTokenStateRefetch !== this.props.lastForceTokenStateRefetch ) { const trackedTokenAddresses = _.keys(this.state.trackedTokenStateByAddress); @@ -200,7 +201,7 @@ export class Portal extends React.Component { const newTokenAddresses = _.map(newTokens, token => token.address); // Add placeholder entry for this token to the state, since fetching the // balance/allowance is asynchronous - const trackedTokenStateByAddress = this.state.trackedTokenStateByAddress; + const trackedTokenStateByAddress = { ...this.state.trackedTokenStateByAddress }; for (const tokenAddress of newTokenAddresses) { trackedTokenStateByAddress[tokenAddress] = { balance: new BigNumber(0), -- cgit v1.2.3