From: Ardis Lu Date: Thu, 15 Feb 2024 06:40:37 +0000 (-0800) Subject: Support multiple wallets installed simultaneously (EIP-6963) X-Git-Url: https://git.ardis.lu/?a=commitdiff_plain;h=cc968a1b6a078d4b6baff6220899df099c4d81d2;p=alu.bz Support multiple wallets installed simultaneously (EIP-6963) --- diff --git a/index.html b/index.html index 6d9a9b4..e0be2de 100644 --- a/index.html +++ b/index.html @@ -94,6 +94,14 @@

This is a personal project. Short links may be changed or deleted at any time.

+ +
+

Select a wallet:

+
    + +
    +
    +

    No wallet detected. Install a wallet to connect.

    diff --git a/script.js b/script.js index 69eba57..7a33a57 100644 --- a/script.js +++ b/script.js @@ -6,7 +6,9 @@ const shortUrlInput = document.getElementById('short-url'); const shortUrlAside = document.getElementById('short-url-aside'); const statusOutput = document.getElementById('status'); const form = document.querySelector('form'); +const walletPicker = document.getElementById('wallet-picker'); const notification = document.getElementById('notification'); +const wallets = []; // Helper function to call the balanceOf function on an address to check if it's eligible to create // custom short URLs. The same logic is executed on the backend to independently validate on server-side. @@ -111,16 +113,19 @@ async function handleSubmit(event) { } } -if (window.ethereum !== undefined) { - // User switches account manually in wallet - ethereum?.addListener?.('accountsChanged', setAccount) ?? ethereum.on('accountsChanged', setAccount); -} - connectButton.addEventListener('click', () => { - if (window.ethereum !== undefined) { - ethereum - .request({ method: 'eth_requestAccounts' }) - .then(setAccount); + if (wallets.length <= 1 && window.ethereum !== undefined) { + ethereum?.addListener?.('accountsChanged', setAccount) ?? ethereum.on('accountsChanged', setAccount); // Handle user switching account after connecting + ethereum.request({ method: 'eth_requestAccounts' }).then(setAccount); // Set initial address + } + else if (wallets.length > 0) { + walletPicker.showModal(); + const walletList = walletPicker.querySelector('ul'); + walletList.innerHTML = ''; + for (const wallet of wallets) { + walletList.insertAdjacentHTML('beforeend', `
  • `) + } + // The rest of logic is handled in the wallet picker "click" event listener } else { notification.show(); @@ -132,3 +137,19 @@ form.addEventListener('submit', handleSubmit); infoButton.addEventListener('click', () => { infoDialog.showModal(); }); + +// EIP-6963: Multi Injected Provider Discovery +// https://eips.ethereum.org/EIPS/eip-6963 +window.addEventListener('eip6963:announceProvider', e => wallets.push(e.detail)); +window.dispatchEvent(new Event('eip6963:requestProvider')); + +// Capture bubbled-up "click" events from the wallet buttons inside the picker dialog. +// Listening for the "click" event instead of "close" to capture the specific button element. +walletPicker.addEventListener('click', e => { + if (e.target.dataset?.uuid === undefined) { + return; + } + globalThis.ethereum = wallets.find(wallet => wallet.info.uuid === e.target.dataset.uuid)?.provider ?? globalThis.ethereum; + ethereum?.addListener?.('accountsChanged', setAccount) ?? ethereum.on('accountsChanged', setAccount); + ethereum.request({ method: 'eth_requestAccounts' }).then(setAccount); +}); diff --git a/style.css b/style.css index 50c7820..0a046d8 100644 --- a/style.css +++ b/style.css @@ -265,11 +265,52 @@ dialog button { align-self: center; } +#wallet-picker, #notification { + border-radius: 16px; + border: 2px solid var(--primary-strongest); +} + +#wallet-picker::backdrop { + filter: blur(4px); + background-color: var(--primary-transparent); +} + +#wallet-picker ul { + list-style-type: none; + padding: 0; + margin: 0; +} + +#wallet-picker li { + background-color: var(--secondary-transparent); + border: 2px solid var(--primary-stronger); + border-radius: 16px; + margin: 4px; + transition: filter 400ms, background-color 400ms; +} + +#wallet-picker :is(li:hover, li:focus-within) { + background-color: var(--secondary); + filter: brightness(115%); + transition: filter 200ms, background-color 200ms; +} + +#wallet-picker li button { + inline-size: 100%; + font-weight: 700; + font-size: 1.5rem; + padding: 36px; +} + +#wallet-picker p { + margin: 0; + font-weight: 700; + font-size: 1.5rem; +} + #notification { position: fixed; bottom: 16px; - border-radius: 16px; - border: 2px solid var(--primary-strongest); } #notification>form {