Skip to content

Instantly share code, notes, and snippets.

@pedrouid
Last active March 1, 2024 03:43
Show Gist options
  • Save pedrouid/5d081f8f13d13d12762bc880ce79a000 to your computer and use it in GitHub Desktop.
Save pedrouid/5d081f8f13d13d12762bc880ce79a000 to your computer and use it in GitHub Desktop.
EIP-6963 react example
import React from "react";
import * as uuid from 'uuid';
import { WindowProvider } from "@wagmi/connectors"
import defaultProviderIcon from "../assets/defaultProviderIcon.png"
// copied from https://github.com/wagmi-dev/references/blob/main/packages/connectors/src/utils/getInjectedName.ts
function getInjectedName(ethereum?: WindowProvider) {
if (!ethereum) return 'Injected'
const getName = (provider: WindowProvider) => {
if (provider.isApexWallet) return 'Apex Wallet'
if (provider.isAvalanche) return 'Core Wallet'
if (provider.isBackpack) return 'Backpack'
if (provider.isBifrost) return 'Bifrost Wallet'
if (provider.isBitKeep) return 'BitKeep'
if (provider.isBitski) return 'Bitski'
if (provider.isBlockWallet) return 'BlockWallet'
if (provider.isBraveWallet) return 'Brave Wallet'
if (provider.isCoinbaseWallet) return 'Coinbase Wallet'
if (provider.isDawn) return 'Dawn Wallet'
if (provider.isDefiant) return 'Defiant'
if (provider.isEnkrypt) return 'Enkrypt'
if (provider.isExodus) return 'Exodus'
if (provider.isFrame) return 'Frame'
if (provider.isFrontier) return 'Frontier Wallet'
if (provider.isGamestop) return 'GameStop Wallet'
if (provider.isHyperPay) return 'HyperPay Wallet'
if (provider.isImToken) return 'ImToken'
if (provider.isHaloWallet) return 'Halo Wallet'
if (provider.isKuCoinWallet) return 'KuCoin Wallet'
if (provider.isMathWallet) return 'MathWallet'
if (provider.isOkxWallet || provider.isOKExWallet) return 'OKX Wallet'
if (provider.isOneInchIOSWallet || provider.isOneInchAndroidWallet)
return '1inch Wallet'
if (provider.isOpera) return 'Opera'
if (provider.isPhantom) return 'Phantom'
if (provider.isPortal) return 'Ripio Portal'
if (provider.isRabby) return 'Rabby Wallet'
if (provider.isRainbow) return 'Rainbow'
if (provider.isStatus) return 'Status'
if (provider.isTalisman) return 'Talisman'
if (provider.isTally) return 'Taho'
if (provider.isTokenPocket) return 'TokenPocket'
if (provider.isTokenary) return 'Tokenary'
if (provider.isTrust || provider.isTrustWallet) return 'Trust Wallet'
if (provider.isXDEFI) return 'XDEFI Wallet'
if (provider.isZerion) return 'Zerion'
if (provider.isMetaMask) return 'MetaMask'
}
// Some injected providers detect multiple other providers and create a list at `window.ethereum.providers`
if (ethereum.providers?.length) {
// Deduplicate names using Set
// Coinbase Wallet puts multiple providers in `ethereum.providers`
const nameSet = new Set<string>()
let unknownCount = 1
for (const provider of ethereum.providers) {
let name = getName(provider)
if (!name) {
name = `Unknown Wallet #${unknownCount}`
unknownCount += 1
}
nameSet.add(name)
}
const names = [...nameSet]
if (names.length) return names
return names[0] ?? 'Injected'
}
return getName(ethereum) ?? 'Injected'
}
// this is oversimplified but it comes from the spec here: https://eips.ethereum.org/EIPS/eip-1193
interface EIP1193Provider {
request: (payload: { method: string, params: params?: unknown[] | object }) => Promise<unknown>
}
// this matches the spec here: https://eips.ethereum.org/EIPS/eip-6963
interface EIP6963ProviderInfo {
walletId: string;
uuid: string;
name: string;
icon: string;
}
// this matches the spec here: https://eips.ethereum.org/EIPS/eip-6963
interface EIP6963ProviderDetail {
info: EIP6963ProviderInfo;
provider: EIP1193Provider;
}
// this will enrich the interface to include a boolean for connected and accounts
interface EVMProviderDetected extends EIP6963ProviderDetail {
connected: boolean;
accounts: string[];
}
function App() {
const [providers, setProviders] = React.useState<EVMProviderDetected[]>([]);
if (typeof window.ethereum !== "undefined") {
const windowProvider = {
info: {
walletId: "window-ethereum-provider",
uuid: uuid.v4(),
name: getInjectedName(window.ethereum),
icon: defaultProviderIcon
}
provider: window.ethereum,
connected: false,
accounts: []
}
setProviders([...providers, windowProvider])
}
window.addEventListener(
"eip6963:announceProvider",
(event: EIP6963AnnounceProviderEvent) => {
const announcedProvider = {
...event.detail,
connected: false,
accounts: []
}
setProviders([...providers, newProvider])
}
);
window.dispatchEvent(new Event("eip6963:requestProvider"));
async function connectProvider(selectedProvider: EVMProviderDetected) {
// requesting accounts with EIP-1102: https://eips.ethereum.org/EIPS/eip-1102
const accounts = await selectedProvider.request({ method: "eth_requestAccounts" })
// once succesful we filter out the previous provider and update with new state
const updatedProvider = {
...selectedProvider,
connected: true,
accounts,
}
const otherProviders = providers.filter(provider => provider.info.uuid !== selectedProvider.info.uuid)
setProviders([
...ohterProviders,
updatedProvider
])
}
return (
<div>
{providers.map(provider => (
<div onClick={connectProvider(provider)}>
<div>{provider.info.name}</div>
<img src={provider.info.icon} />
{provider.connected && <div>accounts: {provider.accounts}</div>}
<div>
))}
</div>
);
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment