From 53e2cda4c8d6698b5c4b69f510ad8764cb089306 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 22 Jun 2018 15:37:42 -0700 Subject: Remove existing networkId watching logic from BlockchainWatcher --- packages/website/ts/blockchain.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'packages/website/ts/blockchain.ts') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 46a4d6629..11202eb64 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -229,7 +229,7 @@ export class Blockchain { shouldPollUserAddress, ); this._contractWrappers.setProvider(provider, this.networkId); - await this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceStateAsync(); + await this._blockchainWatcher.startEmittingUserBalanceStateAsync(); this._dispatcher.updateProviderType(ProviderType.Ledger); } public async updateProviderToInjectedAsync(): Promise { @@ -259,7 +259,7 @@ export class Blockchain { this._contractWrappers.setProvider(provider, this.networkId); await this.fetchTokenInformationAsync(); - await this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceStateAsync(); + await this._blockchainWatcher.startEmittingUserBalanceStateAsync(); this._dispatcher.updateProviderType(ProviderType.Injected); delete this._ledgerSubprovider; delete this._cachedProvider; @@ -816,7 +816,7 @@ export class Blockchain { this._userAddressIfExists = userAddresses[0]; this._dispatcher.updateUserAddress(this._userAddressIfExists); await this.fetchTokenInformationAsync(); - await this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceStateAsync(); + await this._blockchainWatcher.startEmittingUserBalanceStateAsync(); await this._rehydrateStoreWithContractEventsAsync(); } private _updateProviderName(injectedWeb3: Web3): void { -- cgit v1.2.3 From c4e2dcafa4bd5f4b905680e2c1b80d6ddb6ab6fb Mon Sep 17 00:00:00 2001 From: fragosti Date: Mon, 25 Jun 2018 16:26:34 -0700 Subject: Have basic network switching working --- packages/website/ts/blockchain.ts | 224 +++++++++++++++++++------------------- 1 file changed, 114 insertions(+), 110 deletions(-) (limited to 'packages/website/ts/blockchain.ts') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 11202eb64..16ed8d03a 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -50,6 +50,8 @@ import { SideToAssetToken, Token, TokenByAddress, + InjectedProviderObservable, + InjectedProviderUpdate, } from 'ts/types'; import { backendClient } from 'ts/utils/backend_client'; import { configs } from 'ts/utils/configs'; @@ -79,9 +81,8 @@ export class Blockchain { private _dispatcher: Dispatcher; private _web3Wrapper?: Web3Wrapper; private _blockchainWatcher?: BlockchainWatcher; + private _injectedProviderObservable?: InjectedProviderObservable; private _userAddressIfExists: string; - private _cachedProvider: Provider; - private _cachedProviderNetworkId: number; private _ledgerSubprovider: LedgerSubprovider; private _defaultGasPrice: BigNumber; private static _getNameGivenProvider(provider: Provider): string { @@ -92,13 +93,62 @@ export class Blockchain { } return providerNameIfExists; } - private static async _getProviderAsync(injectedWeb3: Web3, networkIdIfExists: number): Promise { + private static _getInjectedWeb3(): any { + return (window as any).web3; + } + private static _getFallbackNetworkId(): number { + return configs.IS_MAINNET_ENABLED ? constants.NETWORK_ID_MAINNET : constants.NETWORK_ID_KOVAN; + } + private static async _getInjectedWeb3ProviderNetworkIdIfExistsAsync(): Promise { + // Hack: We need to know the networkId the injectedWeb3 is connected to (if it is defined) in + // order to properly instantiate the web3Wrapper. Since we must use the async call, we cannot + // retrieve it from within the web3Wrapper constructor. This is and should remain the only + // call to a web3 instance outside of web3Wrapper in the entire dapp. + // In addition, if the user has an injectedWeb3 instance that is disconnected from a backing + // Ethereum node, this call will throw. We need to handle this case gracefully + const injectedWeb3 = Blockchain._getInjectedWeb3(); + let networkIdIfExists: number; + if (!_.isUndefined(injectedWeb3)) { + try { + networkIdIfExists = _.parseInt(await promisify(injectedWeb3.version.getNetwork)()); + } catch (err) { + // Ignore error and proceed with networkId undefined + } + } + return networkIdIfExists; + } + private static async _getProviderAsync( + injectedWeb3: Web3, + networkIdIfExists: number, + userLedgerProvider: boolean = false, + ): Promise { 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 (doesInjectedWeb3Exist && isPublicNodeAvailableForNetworkId) { + 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 ledgerWalletConfigs = { + networkId: networkIdIfExists, + ledgerEthereumClientFactoryAsync: ledgerEthereumBrowserClientFactoryAsync, + }; + const ledgerSubprovider = new LedgerSubprovider(ledgerWalletConfigs); + provider.addProvider(ledgerSubprovider); + provider.addProvider(new FilterSubprovider()); + const rpcSubproviders = _.map(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkIdIfExists], publicNodeUrl => { + return new RpcSubprovider({ + rpcUrl: publicNodeUrl, + }); + }); + provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); + provider.start(); + } 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(); @@ -120,7 +170,7 @@ export class Blockchain { // injected into their browser. provider = new ProviderEngine(); provider.addProvider(new FilterSubprovider()); - const networkId = configs.IS_MAINNET_ENABLED ? constants.NETWORK_ID_MAINNET : constants.NETWORK_ID_KOVAN; + const networkId = Blockchain._getFallbackNetworkId(); const rpcSubproviders = _.map(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId], publicNodeUrl => { return new RpcSubprovider({ rpcUrl: publicNodeUrl, @@ -141,6 +191,7 @@ export class Blockchain { // tslint:disable-next-line:no-floating-promises this._onPageLoadInitFireAndForgetAsync(); } + // TODO: Investigate if we need this. public async networkIdUpdatedFireAndForgetAsync(newNetworkId: number): Promise { const isConnected = !_.isUndefined(newNetworkId); if (!isConnected) { @@ -185,84 +236,14 @@ export class Blockchain { this._ledgerSubprovider.setPath(path); } public async updateProviderToLedgerAsync(networkId: number): Promise { - utils.assert(!_.isUndefined(this._contractWrappers), 'Contract Wrappers must be instantiated.'); - - const isU2FSupported = await utils.isU2FSupportedAsync(); - if (!isU2FSupported) { - throw new Error('Cannot update providerType to LEDGER without U2F support'); - } - - // Cache injected provider so that we can switch the user back to it easily - if (_.isUndefined(this._cachedProvider)) { - this._cachedProvider = this._web3Wrapper.getProvider(); - this._cachedProviderNetworkId = this.networkId; - } - - this._blockchainWatcher.destroy(); - - delete this._userAddressIfExists; - this._dispatcher.updateUserAddress(undefined); // Clear old userAddress - - const provider = new ProviderEngine(); - const ledgerWalletConfigs = { - networkId, - ledgerEthereumClientFactoryAsync: ledgerEthereumBrowserClientFactoryAsync, - }; - this._ledgerSubprovider = new LedgerSubprovider(ledgerWalletConfigs); - provider.addProvider(this._ledgerSubprovider); - provider.addProvider(new FilterSubprovider()); - const rpcSubproviders = _.map(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId], publicNodeUrl => { - return new RpcSubprovider({ - rpcUrl: publicNodeUrl, - }); - }); - provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); - provider.start(); - this.networkId = networkId; - this._dispatcher.updateNetworkId(this.networkId); const shouldPollUserAddress = false; - this._web3Wrapper = new Web3Wrapper(provider); - this._blockchainWatcher = new BlockchainWatcher( - this._dispatcher, - this._web3Wrapper, - this.networkId, - shouldPollUserAddress, - ); - this._contractWrappers.setProvider(provider, this.networkId); - await this._blockchainWatcher.startEmittingUserBalanceStateAsync(); - this._dispatcher.updateProviderType(ProviderType.Ledger); + const useLedgerProvider = true; + await this._resetOrInitializeAsync(networkId, shouldPollUserAddress, useLedgerProvider); } public async updateProviderToInjectedAsync(): Promise { - utils.assert(!_.isUndefined(this._contractWrappers), 'Contract Wrappers must be instantiated.'); - - if (_.isUndefined(this._cachedProvider)) { - return; // Going from injected to injected, so we noop - } - - this._blockchainWatcher.destroy(); - - const provider = this._cachedProvider; - this.networkId = this._cachedProviderNetworkId; - const shouldPollUserAddress = true; - this._web3Wrapper = new Web3Wrapper(provider); - this._blockchainWatcher = new BlockchainWatcher( - this._dispatcher, - this._web3Wrapper, - this.networkId, - shouldPollUserAddress, - ); - - const userAddresses = await this._web3Wrapper.getAvailableAddressesAsync(); - this._userAddressIfExists = userAddresses[0]; - - this._contractWrappers.setProvider(provider, this.networkId); - - await this.fetchTokenInformationAsync(); - await this._blockchainWatcher.startEmittingUserBalanceStateAsync(); - this._dispatcher.updateProviderType(ProviderType.Injected); - delete this._ledgerSubprovider; - delete this._cachedProvider; + const userLedgerProvider = false; + await this._resetOrInitializeAsync(this.networkId, shouldPollUserAddress, userLedgerProvider); } public async setProxyAllowanceAsync(token: Token, amountInBaseUnits: BigNumber): Promise { utils.assert(this.isValidAddress(token.address), BlockchainCallErrs.TokenAddressIsInvalid); @@ -632,6 +613,19 @@ export class Blockchain { private _doesUserAddressExist(): boolean { return !_.isUndefined(this._userAddressIfExists); } + private async _handleInjectedProviderUpdateAsync(update: InjectedProviderUpdate): Promise { + if (update.networkVersion === 'loading') { + // Who comes up with this stuff. + return; + } + const updatedNetworkId = _.parseInt(update.networkVersion); + if (this.networkId === updatedNetworkId) { + return; + } + const shouldPollUserAddress = true; + const useLedgerProvider = false; + await this._resetOrInitializeAsync(updatedNetworkId, shouldPollUserAddress, useLedgerProvider); + } private async _rehydrateStoreWithContractEventsAsync(): Promise { // Ensure we are only ever listening to one set of events this._stopWatchingExchangeLogFillEvents(); @@ -774,36 +768,37 @@ export class Blockchain { } private async _onPageLoadInitFireAndForgetAsync(): Promise { await utils.onPageLoadAsync(); // wait for page to load - - // Hack: We need to know the networkId the injectedWeb3 is connected to (if it is defined) in - // order to properly instantiate the web3Wrapper. Since we must use the async call, we cannot - // retrieve it from within the web3Wrapper constructor. This is and should remain the only - // call to a web3 instance outside of web3Wrapper in the entire dapp. - // In addition, if the user has an injectedWeb3 instance that is disconnected from a backing - // Ethereum node, this call will throw. We need to handle this case gracefully - const injectedWeb3 = (window as any).web3; - let networkIdIfExists: number; - if (!_.isUndefined(injectedWeb3)) { - try { - networkIdIfExists = _.parseInt(await promisify(injectedWeb3.version.getNetwork)()); - } catch (err) { - // Ignore error and proceed with networkId undefined + const networkIdIfExists = await Blockchain._getInjectedWeb3ProviderNetworkIdIfExistsAsync(); + this.networkId = !_.isUndefined(networkIdIfExists) ? networkIdIfExists : Blockchain._getFallbackNetworkId(); + const injectedWeb3 = Blockchain._getInjectedWeb3(); + if (injectedWeb3) { + const injectedProviderObservable = injectedWeb3.currentProvider.publicConfigStore; + if (injectedProviderObservable && !this._injectedProviderObservable) { + this._injectedProviderObservable = injectedProviderObservable; + this._injectedProviderObservable.subscribe(this._handleInjectedProviderUpdateAsync.bind(this)); } } - - const provider = await Blockchain._getProviderAsync(injectedWeb3, networkIdIfExists); - this.networkId = !_.isUndefined(networkIdIfExists) - ? networkIdIfExists - : configs.IS_MAINNET_ENABLED - ? constants.NETWORK_ID_MAINNET - : constants.NETWORK_ID_KOVAN; - this._dispatcher.updateNetworkId(this.networkId); - const zeroExConfigs = { - networkId: this.networkId, - }; - this._contractWrappers = new ContractWrappers(provider, zeroExConfigs); - this._updateProviderName(injectedWeb3); const shouldPollUserAddress = true; + const shouldUseLedger = false; + await this._resetOrInitializeAsync(this.networkId, shouldPollUserAddress, shouldUseLedger); + } + private async _resetOrInitializeAsync( + networkId: number, + shouldPollUserAddress: boolean = false, + useLedgerProvider: boolean = false, + ): Promise { + 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 }); + if (!_.isUndefined(this._blockchainWatcher)) { + this._blockchainWatcher.destroy(); + } this._web3Wrapper = new Web3Wrapper(provider); this._blockchainWatcher = new BlockchainWatcher( this._dispatcher, @@ -811,10 +806,19 @@ export class Blockchain { this.networkId, shouldPollUserAddress, ); - - const userAddresses = await this._web3Wrapper.getAvailableAddressesAsync(); - this._userAddressIfExists = userAddresses[0]; - this._dispatcher.updateUserAddress(this._userAddressIfExists); + if (useLedgerProvider) { + // TODO: why? + delete this._userAddressIfExists; + this._dispatcher.updateUserAddress(undefined); + this._dispatcher.updateProviderType(ProviderType.Ledger); + } else { + delete this._ledgerSubprovider; + const userAddresses = await this._web3Wrapper.getAvailableAddressesAsync(); + this._userAddressIfExists = userAddresses[0]; + this._dispatcher.updateUserAddress(this._userAddressIfExists); + this._updateProviderName(injectedWeb3); + } + // TOOD: should not call this in ledger case? await this.fetchTokenInformationAsync(); await this._blockchainWatcher.startEmittingUserBalanceStateAsync(); await this._rehydrateStoreWithContractEventsAsync(); -- cgit v1.2.3 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 ++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 20 deletions(-) (limited to 'packages/website/ts/blockchain.ts') 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 { -- cgit v1.2.3 From e27780aee9de63790da0ebd610761458f42c9259 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 26 Jun 2018 11:59:23 -0700 Subject: Fix subtle issues with ledger config dialog --- packages/website/ts/blockchain.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/website/ts/blockchain.ts') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index d55cb6771..d2040abb5 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -828,8 +828,8 @@ export class Blockchain { if (!_.isUndefined(injectedWeb3)) { this._dispatcher.updateProviderType(ProviderType.Injected); } + await this.fetchTokenInformationAsync(); } - await this.fetchTokenInformationAsync(); await this._blockchainWatcher.startEmittingUserBalanceStateAsync(); this._dispatcher.updateNetworkId(networkId); await this._rehydrateStoreWithContractEventsAsync(); -- cgit v1.2.3 From 3866154b505c40008b57afb8b75575eb14419578 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 26 Jun 2018 12:16:10 -0700 Subject: Fix stateful ledger dialog edge state --- packages/website/ts/blockchain.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'packages/website/ts/blockchain.ts') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index d2040abb5..0d8cbdcd4 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -191,7 +191,6 @@ export class Blockchain { // tslint:disable-next-line:no-floating-promises this._onPageLoadInitFireAndForgetAsync(); } - // TODO: Investigate if we need this. public async networkIdUpdatedFireAndForgetAsync(newNetworkId: number): Promise { const isConnected = !_.isUndefined(newNetworkId); if (!isConnected) { @@ -246,7 +245,7 @@ export class Blockchain { 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); + await this._resetOrInitializeAsync(networkId, shouldPollUserAddress, userLedgerProvider); } public async setProxyAllowanceAsync(token: Token, amountInBaseUnits: BigNumber): Promise { utils.assert(this.isValidAddress(token.address), BlockchainCallErrs.TokenAddressIsInvalid); -- cgit v1.2.3 From 0a0da63ac7913f0c3a27147a700c9a3dbccf0c40 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 26 Jun 2018 12:33:38 -0700 Subject: Make unsubscribing work --- packages/website/ts/blockchain.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'packages/website/ts/blockchain.ts') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 0d8cbdcd4..7bd6fe800 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -82,6 +82,7 @@ export class Blockchain { private _web3Wrapper?: Web3Wrapper; private _blockchainWatcher?: BlockchainWatcher; private _injectedProviderObservable?: InjectedProviderObservable; + private _injectedProviderUpdateHandler: (update: InjectedProviderUpdate) => Promise; private _userAddressIfExists: string; private _ledgerSubprovider: LedgerSubprovider; private _defaultGasPrice: BigNumber; @@ -186,6 +187,8 @@ export class Blockchain { this._dispatcher = dispatcher; const defaultGasPrice = GWEI_IN_WEI * 30; this._defaultGasPrice = new BigNumber(defaultGasPrice); + // We need a unique reference to this function so we can use it to unsubcribe. + this._injectedProviderUpdateHandler = this._handleInjectedProviderUpdateAsync.bind(this); // tslint:disable-next-line:no-floating-promises this._updateDefaultGasPriceAsync(); // tslint:disable-next-line:no-floating-promises @@ -521,6 +524,7 @@ export class Blockchain { } public destroy(): void { this._blockchainWatcher.destroy(); + this._injectedProviderObservable.unsubscribe(this._injectedProviderUpdateHandler); this._stopWatchingExchangeLogFillEvents(); } public async fetchTokenInformationAsync(): Promise { @@ -776,7 +780,7 @@ export class Blockchain { const injectedProviderObservable = injectedWeb3.currentProvider.publicConfigStore; if (injectedProviderObservable && !this._injectedProviderObservable) { this._injectedProviderObservable = injectedProviderObservable; - this._injectedProviderObservable.subscribe(this._handleInjectedProviderUpdateAsync.bind(this)); + this._injectedProviderObservable.subscribe(this._injectedProviderUpdateHandler); } } this._updateProviderName(injectedWeb3); -- cgit v1.2.3 From d72e06842f2c561ef27d0adba6f2b4a51d38a87a Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 26 Jun 2018 12:48:00 -0700 Subject: Remove unused variables --- packages/website/ts/blockchain.ts | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'packages/website/ts/blockchain.ts') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 7bd6fe800..7dda0a191 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -43,6 +43,8 @@ import { BlockchainErrs, ContractInstance, Fill, + InjectedProviderObservable, + InjectedProviderUpdate, Order as PortalOrder, Providers, ProviderType, @@ -50,8 +52,6 @@ import { SideToAssetToken, Token, TokenByAddress, - InjectedProviderObservable, - InjectedProviderUpdate, } from 'ts/types'; import { backendClient } from 'ts/utils/backend_client'; import { configs } from 'ts/utils/configs'; @@ -811,14 +811,8 @@ export class Blockchain { this._blockchainWatcher.destroy(); } this._web3Wrapper = new Web3Wrapper(provider); - this._blockchainWatcher = new BlockchainWatcher( - this._dispatcher, - this._web3Wrapper, - this.networkId, - shouldPollUserAddress, - ); + this._blockchainWatcher = new BlockchainWatcher(this._dispatcher, this._web3Wrapper, shouldPollUserAddress); if (useLedgerProvider && !_.isUndefined(ledgerSubproviderIfExists)) { - // TODO: why? delete this._userAddressIfExists; this._ledgerSubprovider = ledgerSubproviderIfExists; this._dispatcher.updateUserAddress(undefined); -- cgit v1.2.3 From de50407953d36ae43f909ad8b3b5e249151bdb51 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 27 Jun 2018 10:34:17 -0700 Subject: Rename all corresponding bools to shouldUseLedgerProvider --- packages/website/ts/blockchain.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'packages/website/ts/blockchain.ts') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 7dda0a191..cac362795 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -121,14 +121,14 @@ export class Blockchain { private static async _getProviderAsync( injectedWeb3: Web3, networkIdIfExists: number, - userLedgerProvider: boolean = false, + shouldUserLedgerProvider: boolean = false, ): 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); - if (userLedgerProvider && isNetworkIdDefined) { + if (shouldUserLedgerProvider && isNetworkIdDefined) { const isU2FSupported = await utils.isU2FSupportedAsync(); if (!isU2FSupported) { throw new Error('Cannot update providerType to LEDGER without U2F support'); @@ -239,16 +239,16 @@ export class Blockchain { } public async updateProviderToLedgerAsync(networkId: number): Promise { const shouldPollUserAddress = false; - const useLedgerProvider = true; - await this._resetOrInitializeAsync(networkId, shouldPollUserAddress, useLedgerProvider); + const shouldUserLedgerProvider = true; + await this._resetOrInitializeAsync(networkId, shouldPollUserAddress, shouldUserLedgerProvider); } public async updateProviderToInjectedAsync(): Promise { const shouldPollUserAddress = true; - const userLedgerProvider = false; + const shouldUserLedgerProvider = 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(networkId, shouldPollUserAddress, userLedgerProvider); + await this._resetOrInitializeAsync(networkId, shouldPollUserAddress, shouldUserLedgerProvider); } public async setProxyAllowanceAsync(token: Token, amountInBaseUnits: BigNumber): Promise { utils.assert(this.isValidAddress(token.address), BlockchainCallErrs.TokenAddressIsInvalid); @@ -628,8 +628,8 @@ export class Blockchain { return; } const shouldPollUserAddress = true; - const useLedgerProvider = false; - await this._resetOrInitializeAsync(updatedNetworkId, shouldPollUserAddress, useLedgerProvider); + const shouldUserLedgerProvider = false; + await this._resetOrInitializeAsync(updatedNetworkId, shouldPollUserAddress, shouldUserLedgerProvider); } private async _rehydrateStoreWithContractEventsAsync(): Promise { // Ensure we are only ever listening to one set of events @@ -785,13 +785,13 @@ export class Blockchain { } this._updateProviderName(injectedWeb3); const shouldPollUserAddress = true; - const shouldUseLedger = false; - await this._resetOrInitializeAsync(this.networkId, shouldPollUserAddress, shouldUseLedger); + const shouldUseLedgerProvider = false; + await this._resetOrInitializeAsync(this.networkId, shouldPollUserAddress, shouldUseLedgerProvider); } private async _resetOrInitializeAsync( networkId: number, shouldPollUserAddress: boolean = false, - useLedgerProvider: boolean = false, + shouldUserLedgerProvider: boolean = false, ): Promise { this._dispatcher.updateBlockchainIsLoaded(false); this._dispatcher.updateUserWeiBalance(undefined); @@ -800,7 +800,7 @@ export class Blockchain { const [provider, ledgerSubproviderIfExists] = await Blockchain._getProviderAsync( injectedWeb3, networkId, - useLedgerProvider, + shouldUserLedgerProvider, ); if (!_.isUndefined(this._contractWrappers)) { this._contractWrappers.setProvider(provider, networkId); @@ -812,7 +812,7 @@ export class Blockchain { } this._web3Wrapper = new Web3Wrapper(provider); this._blockchainWatcher = new BlockchainWatcher(this._dispatcher, this._web3Wrapper, shouldPollUserAddress); - if (useLedgerProvider && !_.isUndefined(ledgerSubproviderIfExists)) { + if (shouldUserLedgerProvider && !_.isUndefined(ledgerSubproviderIfExists)) { delete this._userAddressIfExists; this._ledgerSubprovider = ledgerSubproviderIfExists; this._dispatcher.updateUserAddress(undefined); -- cgit v1.2.3 From 2a092143dc01d84e5dc0b6dc2998cfd4efb38d73 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 27 Jun 2018 10:40:07 -0700 Subject: Remove IS_MAINNET_ENABLED config --- packages/website/ts/blockchain.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'packages/website/ts/blockchain.ts') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index cac362795..a0a404d5a 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -97,9 +97,6 @@ export class Blockchain { private static _getInjectedWeb3(): any { return (window as any).web3; } - private static _getFallbackNetworkId(): number { - return configs.IS_MAINNET_ENABLED ? constants.NETWORK_ID_MAINNET : constants.NETWORK_ID_KOVAN; - } private static async _getInjectedWeb3ProviderNetworkIdIfExistsAsync(): Promise { // Hack: We need to know the networkId the injectedWeb3 is connected to (if it is defined) in // order to properly instantiate the web3Wrapper. Since we must use the async call, we cannot @@ -172,7 +169,7 @@ export class Blockchain { // injected into their browser. const provider = new ProviderEngine(); provider.addProvider(new FilterSubprovider()); - const networkId = Blockchain._getFallbackNetworkId(); + const networkId = constants.NETWORK_ID_MAINNET; const rpcSubproviders = _.map(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId], publicNodeUrl => { return new RpcSubprovider({ rpcUrl: publicNodeUrl, @@ -774,7 +771,7 @@ export class Blockchain { private async _onPageLoadInitFireAndForgetAsync(): Promise { await utils.onPageLoadAsync(); // wait for page to load const networkIdIfExists = await Blockchain._getInjectedWeb3ProviderNetworkIdIfExistsAsync(); - this.networkId = !_.isUndefined(networkIdIfExists) ? networkIdIfExists : Blockchain._getFallbackNetworkId(); + this.networkId = !_.isUndefined(networkIdIfExists) ? networkIdIfExists : constants.NETWORK_ID_MAINNET; const injectedWeb3 = Blockchain._getInjectedWeb3(); if (injectedWeb3) { const injectedProviderObservable = injectedWeb3.currentProvider.publicConfigStore; -- cgit v1.2.3 From b6f546ebe0b71ce450c1e724fc8f3b670bf97773 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 27 Jun 2018 11:17:32 -0700 Subject: Fix convention stuff --- packages/website/ts/blockchain.ts | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'packages/website/ts/blockchain.ts') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index a0a404d5a..4a041d20c 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -97,18 +97,18 @@ export class Blockchain { private static _getInjectedWeb3(): any { return (window as any).web3; } - private static async _getInjectedWeb3ProviderNetworkIdIfExistsAsync(): Promise { + private static async _getInjectedWeb3ProviderNetworkIdIfExistsAsync(): Promise { // Hack: We need to know the networkId the injectedWeb3 is connected to (if it is defined) in // order to properly instantiate the web3Wrapper. Since we must use the async call, we cannot // retrieve it from within the web3Wrapper constructor. This is and should remain the only // call to a web3 instance outside of web3Wrapper in the entire dapp. // In addition, if the user has an injectedWeb3 instance that is disconnected from a backing // Ethereum node, this call will throw. We need to handle this case gracefully - const injectedWeb3 = Blockchain._getInjectedWeb3(); + const injectedWeb3IfExists = Blockchain._getInjectedWeb3(); let networkIdIfExists: number; - if (!_.isUndefined(injectedWeb3)) { + if (!_.isUndefined(injectedWeb3IfExists)) { try { - networkIdIfExists = _.parseInt(await promisify(injectedWeb3.version.getNetwork)()); + networkIdIfExists = _.parseInt(await promisify(injectedWeb3IfExists.version.getNetwork)()); } catch (err) { // Ignore error and proceed with networkId undefined } @@ -119,13 +119,13 @@ export class Blockchain { injectedWeb3: Web3, networkIdIfExists: number, shouldUserLedgerProvider: boolean = false, - ): Promise<[Provider, LedgerSubprovider]> { + ): Promise<[Provider, LedgerSubprovider | undefined]> { const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3); - const isNetworkIdDefined = !_.isUndefined(networkIdIfExists); + const isNetworkIdAvailable = !_.isUndefined(networkIdIfExists); const publicNodeUrlsIfExistsForNetworkId = configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkIdIfExists]; const isPublicNodeAvailableForNetworkId = !_.isUndefined(publicNodeUrlsIfExistsForNetworkId); - if (shouldUserLedgerProvider && isNetworkIdDefined) { + if (shouldUserLedgerProvider && isNetworkIdAvailable) { const isU2FSupported = await utils.isU2FSupportedAsync(); if (!isU2FSupported) { throw new Error('Cannot update providerType to LEDGER without U2F support'); @@ -243,7 +243,7 @@ export class Blockchain { const shouldPollUserAddress = true; const shouldUserLedgerProvider = false; this._dispatcher.updateBlockchainIsLoaded(false); - // We don't want to be out of sync with the network metamask declares. + // We don't want to be out of sync with the network the injected provider declares. const networkId = await Blockchain._getInjectedWeb3ProviderNetworkIdIfExistsAsync(); await this._resetOrInitializeAsync(networkId, shouldPollUserAddress, shouldUserLedgerProvider); } @@ -772,15 +772,15 @@ export class Blockchain { await utils.onPageLoadAsync(); // wait for page to load const networkIdIfExists = await Blockchain._getInjectedWeb3ProviderNetworkIdIfExistsAsync(); this.networkId = !_.isUndefined(networkIdIfExists) ? networkIdIfExists : constants.NETWORK_ID_MAINNET; - const injectedWeb3 = Blockchain._getInjectedWeb3(); - if (injectedWeb3) { - const injectedProviderObservable = injectedWeb3.currentProvider.publicConfigStore; + const injectedWeb3IfExists = Blockchain._getInjectedWeb3(); + if (injectedWeb3IfExists) { + const injectedProviderObservable = injectedWeb3IfExists.currentProvider.publicConfigStore; if (injectedProviderObservable && !this._injectedProviderObservable) { this._injectedProviderObservable = injectedProviderObservable; this._injectedProviderObservable.subscribe(this._injectedProviderUpdateHandler); } } - this._updateProviderName(injectedWeb3); + this._updateProviderName(injectedWeb3IfExists); const shouldPollUserAddress = true; const shouldUseLedgerProvider = false; await this._resetOrInitializeAsync(this.networkId, shouldPollUserAddress, shouldUseLedgerProvider); @@ -793,9 +793,9 @@ export class Blockchain { this._dispatcher.updateBlockchainIsLoaded(false); this._dispatcher.updateUserWeiBalance(undefined); this.networkId = networkId; - const injectedWeb3 = Blockchain._getInjectedWeb3(); + const injectedWeb3IfExists = Blockchain._getInjectedWeb3(); const [provider, ledgerSubproviderIfExists] = await Blockchain._getProviderAsync( - injectedWeb3, + injectedWeb3IfExists, networkId, shouldUserLedgerProvider, ); @@ -819,7 +819,7 @@ export class Blockchain { const userAddresses = await this._web3Wrapper.getAvailableAddressesAsync(); this._userAddressIfExists = userAddresses[0]; this._dispatcher.updateUserAddress(this._userAddressIfExists); - if (!_.isUndefined(injectedWeb3)) { + if (!_.isUndefined(injectedWeb3IfExists)) { this._dispatcher.updateProviderType(ProviderType.Injected); } await this.fetchTokenInformationAsync(); -- cgit v1.2.3 From 360927ec77d5ea50848f4c1b2c66566542a28d1c Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 27 Jun 2018 11:37:24 -0700 Subject: Changing provider to ledger more consistent with previous experience --- packages/website/ts/blockchain.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'packages/website/ts/blockchain.ts') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 4a041d20c..18363a4c7 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -773,9 +773,9 @@ export class Blockchain { const networkIdIfExists = await Blockchain._getInjectedWeb3ProviderNetworkIdIfExistsAsync(); this.networkId = !_.isUndefined(networkIdIfExists) ? networkIdIfExists : constants.NETWORK_ID_MAINNET; const injectedWeb3IfExists = Blockchain._getInjectedWeb3(); - if (injectedWeb3IfExists) { + if (!_.isUndefined(injectedWeb3IfExists) && !_.isUndefined(injectedWeb3IfExists.currentProvider)) { const injectedProviderObservable = injectedWeb3IfExists.currentProvider.publicConfigStore; - if (injectedProviderObservable && !this._injectedProviderObservable) { + if (!_.isUndefined(injectedProviderObservable) && _.isUndefined(this._injectedProviderObservable)) { this._injectedProviderObservable = injectedProviderObservable; this._injectedProviderObservable.subscribe(this._injectedProviderUpdateHandler); } @@ -790,7 +790,9 @@ export class Blockchain { shouldPollUserAddress: boolean = false, shouldUserLedgerProvider: boolean = false, ): Promise { - this._dispatcher.updateBlockchainIsLoaded(false); + if (!shouldUserLedgerProvider) { + this._dispatcher.updateBlockchainIsLoaded(false); + } this._dispatcher.updateUserWeiBalance(undefined); this.networkId = networkId; const injectedWeb3IfExists = Blockchain._getInjectedWeb3(); -- cgit v1.2.3