]> git.ardis.lu - alu.bz/commitdiff
Support multiple wallets installed simultaneously (EIP-6963)
authorArdis Lu <ardisglu@gmail.com>
Thu, 15 Feb 2024 06:40:37 +0000 (22:40 -0800)
committerArdis Lu <ardisglu@gmail.com>
Thu, 15 Feb 2024 06:40:37 +0000 (22:40 -0800)
index.html
script.js
style.css

index 6d9a9b4381be7bfd4b870900184da6c90d040cd9..e0be2de4bb0f791de2b4f60c041f00e72bf51c6e 100644 (file)
       <p>This is a personal project. Short links may be changed or deleted at any time.</p>
     </dialog>
 
+    <dialog id="wallet-picker">
+      <form method="dialog">
+        <p>Select a wallet:</p>
+        <ul></ul>
+        <button class="text-button">Cancel</button>
+      </form>
+    </dialog>
+
     <dialog id="notification">
       <form method="dialog">
         <p>No wallet detected. Install a wallet to connect.</p>
index 69eba57d109038bc19139e17a40f7e60b087c5ca..7a33a5788fcb67feb30f136050d12a140ba79863 100644 (file)
--- 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', `<li><button data-uuid="${wallet.info.uuid}">${wallet.info.name}</button></li>`)
+    }
+    // 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);
+});
index 50c7820cbf0664810f8c33c4a556c840f05553b0..0a046d8da70c267315334964de703cb7f1552d9d 100644 (file)
--- 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 {
This page took 0.040763 seconds and 4 git commands to generate.