Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eliminate polling for wallet account change #36

Draft
wants to merge 2 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 0 additions & 65 deletions packages/alchemy/src/arc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { getNetworkId, getNetworkName, targetedNetwork, targetNetworks, Networks
import { settings } from "./settings";
import { Address, Arc } from "@daostack/arc.js";
import Web3Modal, { getProviderInfo, IProviderInfo } from "web3modal";
import { Observable } from "rxjs";
import gql from "graphql-tag";

const Web3 = require("web3");
Expand Down Expand Up @@ -415,22 +414,6 @@ async function enableWeb3Provider(network?: Networks): Promise<void> {
selectedProvider = provider;
}

/**
* @return the current account address from Arc. Ignores any injected
* account unless Arc knows about the provider.
*/
async function getCurrentAccountFromProvider(): Promise<Address | null> {
if (!selectedProvider) {
/**
* though an account may actually be available via injection, we're not going
* to return it. The flow needs to start from a selected provider first,
* only then the current account.
*/
return null;
}
return _getCurrentAccountFromProvider(await getNetworkName(selectedProvider.chainId));
}

/**
* Logout, switch to readonly mode (effectively a logout).
* Clear caches as every case where we're manually logging out
Expand Down Expand Up @@ -541,54 +524,6 @@ export async function enableWalletProvider(options: IEnableWalletProviderParams,
return true;
}

// Polling is Evil!
// TO DO: See https://github.com/daostack/alchemy/issues/2295.
export function pollForAccountChanges(currentAccountAddress: Address | null, interval = 2000): Observable<Address> {
// eslint-disable-next-line no-console
console.log(`start polling for account changes from: ${currentAccountAddress}`);
return Observable.create((observer: any): () => void => {
let prevAccount = currentAccountAddress;
let running = false;

async function poll(): Promise<void> {

if (!running) {
running = true;
try {
await getCurrentAccountFromProvider()
.then(async (account: Address | null): Promise<void> => {
if (prevAccount !== account) {
if (account && initializedAccount && (account !== initializedAccount)) {
/**
* Handle when user changes account in MetaMask while already connected to Alchemy.
* Also handles how the Burner provider switches from a Fortmatic address to the
* burner address at the time of connecting.
*/
await initializeArc(await getNetworkName(selectedProvider.chainId), selectedProvider);
}
observer.next(account);
// eslint-disable-next-line require-atomic-updates
prevAccount = account;
}
})
// eslint-disable-next-line no-console
.catch((err): void => {console.error(err ? err.message : "unknown error"); });
} catch (ex) {
// eslint-disable-next-line no-console
console.error(ex ? ex.message : "unknown error");
}
finally {
running = false;
}
}
}

poll();
const timeout = setInterval(poll, interval);
return (): void => { clearTimeout(timeout); };
});
}

/**
* extension of the Web3Modal IProviderInfo
*/
Expand Down
43 changes: 5 additions & 38 deletions packages/alchemy/src/layouts/AppContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Header from "layouts/Header";
import SidebarMenu from "layouts/SidebarMenu";
import { IRootState } from "@store";
import { dismissNotification, INotificationsState, NotificationStatus, showNotification, INotification } from "@store/notifications/notifications.reducer";
import { getCachedAccount, cacheWeb3Info, logout, pollForAccountChanges } from "arc";
import { cacheWeb3Info, getCachedAccount } from "arc";
import ErrorUncaught from "components/Errors/ErrorUncaught";
import { parse } from "query-string";
import * as React from "react";
Expand All @@ -18,7 +18,6 @@ import { matchPath, Link, Route, RouteComponentProps, Switch } from "react-route
import { ModalContainer } from "react-router-modal";
import { History } from "history";
import classNames from "classnames";
import { Address } from "@daostack/arc.js";
import { sortedNotifications } from "@store/notifications/notifications";
import * as css from "./App.scss";
import SimpleMessagePopup, { ISimpleMessagePopupProps } from "components/Shared/SimpleMessagePopup";
Expand Down Expand Up @@ -114,9 +113,7 @@ class AppContainer extends React.Component<IProps, IState> {
* not yet made available to the app.
*/
const currentAddress = getCachedAccount();
let accountWasCached = false;
if (currentAddress) {
accountWasCached = true;
// eslint-disable-next-line no-console
console.log(`using account from local storage: ${currentAddress}`);
}
Expand All @@ -130,42 +127,12 @@ class AppContainer extends React.Component<IProps, IState> {
window.ethereum.on("chainChanged", async (chainId: string) => {
this.props.setCurrentAccount(getCachedAccount(), await getNetworkName(chainId));
});
// TO DO: Listen to account changes in MetaMask instead of polling!
//window.ethereum.on("accountsChanged", (accounts: Array<any>) => {
// Handle the new accounts, or lack thereof.
// "accounts" will always be an array, but it can be empty.
// The current account is at accounts[0]
//});
}

/**
* Only supply currentAddress if it was obtained from a provider. The poll
* is only comparing changes with respect to the provider state. Passing it a cached state
* will only cause it to get the wrong impression and misbehave.
*/
pollForAccountChanges(accountWasCached ? null : currentAddress).subscribe(
(newAddress: Address | null): void => {
// eslint-disable-next-line no-console
console.log(`new account: ${newAddress}`);
this.props.setCurrentAccount(newAddress);
if (newAddress) {
cacheWeb3Info(newAddress);
} else {
logout(this.props.showNotification);

// TODO: save the threebox for each profile separately so we dont have to logout here
this.props.threeBoxLogout();
}
window.ethereum.on("accountsChanged", (accounts: Array<any>) => {
this.props.setCurrentAccount(accounts[0]);
cacheWeb3Info(accounts[0]);
});

/**
* display checking the subgraph. It is falsely reporting that the subgraph is down.
pollSubgraphUpdating().subscribe(async (subgraphRunning: boolean) => {
if (!subgraphRunning) {
this.props.showNotification(NotificationStatus.Failure, "The subgraph is no longer updating, please refresh the page to see the latest data");
}
});
*/
}
}

private clearError = () => {
Expand Down