Skip to content

Commit

Permalink
feat: allow for alternative wallet injections (#34)
Browse files Browse the repository at this point in the history
* fix: wallet popup on page open

* refactor: rename walletconnct connector

* feat: allow alternative injections

* refactor: rename

* fix: merge

* fix: import error: remove logs
  • Loading branch information
Addminus authored Nov 11, 2022
1 parent 62f10de commit f7790b4
Show file tree
Hide file tree
Showing 8 changed files with 478 additions and 188 deletions.
74 changes: 54 additions & 20 deletions packages/wallet-management/src/LiFiWalletManagement.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import type { ExternalProvider, Web3Provider } from '@ethersproject/providers';
import { ethers } from 'ethers';
import type { Connector } from '@web3-react/types';
import type { Signer } from 'ethers';
import { useCallback, useEffect, useState } from 'react';
import { usePriorityConnector, usePriorityProvider } from './connectorHooks';
import { getSelectedConnector } from '@web3-react/core';
import { usePriorityConnector, usePriorityProvider } from './priorityConnector';
// import { usePriorityConnector, usePriorityProvider } from './connectorHooks';
import {
addToActiveWallets,
addToDeactivatedWallets,
Expand All @@ -14,14 +19,39 @@ export const useLiFiWalletManagement = () => {
const priorityConnector = usePriorityConnector();
// "any" because of https://github.com/ethers-io/ethers.js/issues/866
const priorityProvider = usePriorityProvider('any');
const [currentProvider, setCurrentProvider] = useState<Web3Provider>();
const [currentConnector, setCurrentConnector] = useState<Connector>();
const [signer, setSigner] = useState<Signer>();

const flushCurrentWalletData = () => {
console.log('flushing wallet data');

setCurrentConnector(() => undefined);
setCurrentProvider(() => undefined);
setSigner(() => undefined);
};

// eslint-disable-next-line react-hooks/exhaustive-deps
const calcWalletData = (connector?: Connector) => {
if (connector) {
const provider = new ethers.providers.Web3Provider(
connector.provider as ExternalProvider,
);
setCurrentProvider(() => provider);
setCurrentConnector(() => connector);
setSigner(() => provider?.getSigner?.());
}
};

const connect = useCallback(
async (wallet?: Wallet) => {
const selectedAddress = (window as any)?.ethereum?.selectedAddress;

try {
if (wallet) {
await wallet.connector.activate();
const { connector } = wallet.web3react;
await connector.activate();
calcWalletData(connector);
} else {
await priorityConnector.activate();
}
Expand All @@ -31,7 +61,7 @@ export const useLiFiWalletManagement = () => {
removeFromDeactivatedWallets(selectedAddress);
addToActiveWallets(selectedAddress);
},
[priorityConnector],
[calcWalletData, priorityConnector],
);

const disconnect = useCallback(
Expand All @@ -40,52 +70,56 @@ export const useLiFiWalletManagement = () => {
removeFromActiveWallets(selectedAddress);
addToDeactivatedWallets(selectedAddress);
if (wallet) {
await wallet.connector.deactivate?.();
await currentConnector?.deactivate?.();
flushCurrentWalletData();
} else if (priorityConnector.deactivate) {
await priorityConnector.deactivate?.();
flushCurrentWalletData();
} else {
await priorityConnector.resetState();
setSigner(undefined);
flushCurrentWalletData();
}
},
[priorityConnector],
[priorityConnector, currentConnector],
);

useEffect(() => {
setSigner(priorityProvider?.getSigner());
}, [priorityProvider]);

// eager connect
useEffect(() => {
const selectedAddress = (window as any).ethereum?.selectedAddress;
if (!isWalletDeactivated(selectedAddress)) {
if (!isWalletDeactivated(selectedAddress) && priorityConnector) {
priorityConnector?.connectEagerly!();
}
}, [priorityConnector?.connectEagerly]);
}, [priorityConnector]);

// injected wallet listeners
useEffect(() => {
const { ethereum } = window as any;
const handleConnect = async () => {
await priorityConnector.activate();
};
const handleChainChanged = async (chainId: string | number) => {
await priorityConnector.activate();
await currentConnector?.activate();
calcWalletData(currentConnector);
};
const handleAccountsChanged = async (accounts: string[]) => {
if (!accounts.length) {
await currentConnector?.deactivate?.();
flushCurrentWalletData();
}
};

ethereum?.on('connect', handleConnect);
ethereum?.on('chainChanged', handleChainChanged);
ethereum?.on('accountsChanged', handleAccountsChanged);

return () => {
if (ethereum?.removeListener) {
ethereum.removeListener('connect', handleConnect);
ethereum.removeListener('chainChanged', handleChainChanged);
ethereum.removeListener('accountsChanged', handleAccountsChanged);
}
};
}, [priorityConnector]);
}, [currentConnector]);

return {
connect,
disconnect,
signer,
provider: priorityProvider,
provider: currentProvider ?? priorityProvider,
};
};
85 changes: 57 additions & 28 deletions packages/wallet-management/src/connectors/eip1193.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,69 @@
// eslint-disable-next-line max-classes-per-file
import { Eip1193Bridge } from '@ethersproject/experimental';
import { initializeConnector } from '@web3-react/core';
import { EIP1193 } from '@web3-react/eip1193';
import { EIP1193, EIP1193ConstructorArgs } from '@web3-react/eip1193';
import type { Empty } from '@web3-react/empty';
import { EMPTY } from '@web3-react/empty';
import { ProviderConnectInfo, ProviderRpcError } from '@web3-react/types';
import { providers } from 'ethers';

class Eip1193BridgeWithoutAccounts extends Eip1193Bridge {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
request(request: { method: string; params?: any[] }): Promise<any> {
if (
request.method === 'eth_requestAccounts' ||
request.method === 'eth_accounts'
) {
return Promise.resolve([]);
}
return super.request(request);
}
}
const { ethereum } = window as any;
const currentProvider = ethereum ? new providers.Web3Provider(ethereum) : null;

const eip1193Provider = currentProvider
? new Eip1193BridgeWithoutAccounts(
currentProvider?.getSigner(),
currentProvider,
)
: null;

export const [eip1193, hooks, store] = initializeConnector<EIP1193 | Empty>(
(actions) =>
eip1193Provider
? new EIP1193({
actions,
provider: eip1193Provider,
onError: (error) => console.warn(error),
})
: EMPTY,
// supportedChains.map((chain) => chain.id),
);
class EIP1193Listener extends EIP1193 {
constructor({ actions, provider, onError }: EIP1193ConstructorArgs) {
super({ actions, provider, onError });

this.provider = provider;

this.provider.on('connect', ({ chainId }: ProviderConnectInfo): void => {
console.log('connect:', chainId);
});

this.provider.on('disconnect', (error: ProviderRpcError): void => {
this.actions.resetState();
this.onError?.(error);
});

this.provider.on('chainChanged', (chainId: string): void => {
console.log(chainId);
});

this.provider.on('accountsChanged', (accounts: string[]): void => {
console.log('eip1193 accounts', accounts);
});
}
}

export const createEip1193Connector = () => {
const { ethereum } = window as any;
const currentProvider = ethereum
? new providers.Web3Provider(ethereum)
: null;

const eip1193Provider = new Eip1193BridgeWithoutAccounts(
currentProvider!.getSigner(),
currentProvider!,
);
const [eip1193, hooks] = initializeConnector<EIP1193Listener | Empty>(
(actions) =>
eip1193Provider
? new EIP1193({
actions,
provider: eip1193Provider,
onError: (error) => console.warn(error),
})
: EMPTY,
// supportedChains.map((chain) => chain.id),
);

console.log('eip1193:', eip1193);

return {
connector: eip1193,
hooks,
};
};
7 changes: 7 additions & 0 deletions packages/wallet-management/src/connectors/metaMask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ export const [metaMask, hooks] = initializeConnector<MetaMask>(
(actions) => new MetaMask({ actions }),
);

export const createMetamaskConnector = () => {
const [connector, hooks] = initializeConnector<MetaMask>(
(actions) => new MetaMask({ actions }),
);
return { connector, hooks };
};

/*
Known issues:
issue: metamask uninitialized
Expand Down
Loading

0 comments on commit f7790b4

Please sign in to comment.