Commit 95a82b5f authored by Stefy Spora's avatar Stefy Spora

Fix MetaMask detection in extension popup

- Create dedicated metamask-detector.js content script that runs on all websites
- Update manifest.json to include MetaMask detector for all URLs
- Modify popup.js to communicate with MetaMask detector via message passing
- Remove direct window.ethereum access from popup context (not available)
- Web3 donations now work properly by using content script on active tab
- MetaMask detection should now work correctly on any website
parent 4918646d
...@@ -24,6 +24,11 @@ ...@@ -24,6 +24,11 @@
{ {
"matches": ["https://fetlife.com/*"], "matches": ["https://fetlife.com/*"],
"js": ["content.js"] "js": ["content.js"]
},
{
"matches": ["<all_urls>"],
"js": ["metamask-detector.js"],
"run_at": "document_start"
} }
], ],
"icons": { "icons": {
......
/*
* FetLife Privacy Helper - MetaMask Detector
* Copyright (C) 2025 Stefy Spora <stefy@sexhack.me> - sexhack.me
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// MetaMask detection content script
// This script runs on all websites to provide MetaMask detection capabilities
(function() {
'use strict';
// Function to check if MetaMask is available
function isMetaMaskAvailable() {
return typeof window.ethereum !== 'undefined' ||
(typeof window.web3 !== 'undefined' && typeof window.web3.currentProvider !== 'undefined');
}
// Function to get MetaMask provider
function getMetaMaskProvider() {
return window.ethereum || window.web3.currentProvider;
}
// Listen for messages from popup
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'checkMetaMask') {
sendResponse({
available: isMetaMaskAvailable(),
provider: getMetaMaskProvider() ? true : false
});
} else if (request.action === 'executeWeb3Donation') {
// Handle Web3 donation directly in content script
executeWeb3Donation().then(result => {
sendResponse(result);
});
return true; // Keep message channel open for async response
}
});
// Web3 donation function for content script
async function executeWeb3Donation() {
try {
// Check if MetaMask is installed
if (!isMetaMaskAvailable()) {
return { success: false, message: 'MetaMask not detected. Please install MetaMask extension.' };
}
const ethereumProvider = getMetaMaskProvider();
// Request account access
let accounts;
try {
accounts = await ethereumProvider.request({
method: 'eth_requestAccounts'
});
} catch (requestError) {
// Fallback for legacy providers
if (ethereumProvider.enable) {
accounts = await ethereumProvider.enable();
} else {
throw requestError;
}
}
if (!accounts || accounts.length === 0) {
return { success: false, message: 'No accounts found. Please unlock your Web3 wallet.' };
}
const donationAddress = '0xdA6dAb526515b5cb556d20269207D43fcc760E51';
// Prepare transaction parameters (user can modify amount in wallet)
const transactionParameters = {
to: donationAddress,
from: accounts[0],
value: '0x16345785D8A0000', // 0.1 ETH in wei (default amount, user can change)
gas: '0x5208', // 21000 gas limit for simple transfer
};
// Send transaction
let txHash;
try {
txHash = await ethereumProvider.request({
method: 'eth_sendTransaction',
params: [transactionParameters],
});
} catch (transactionError) {
// Handle user rejection specifically
if (transactionError.code === 4001 ||
(transactionError.message && transactionError.message.includes('User denied transaction signature'))) {
return { success: false, message: 'Transaction cancelled by user.' };
}
throw transactionError;
}
return { success: true, message: `Transaction sent! Hash: ${txHash.substring(0, 10)}...` };
} catch (error) {
console.error('Web3 donation error:', error);
if (error.code === 4001 || (error.message && error.message.includes('User denied'))) {
return { success: false, message: 'Transaction cancelled by user.' };
} else if (error.code === -32602) {
return { success: false, message: 'Invalid transaction parameters.' };
} else {
return { success: false, message: `Transaction failed: ${error.message || error.toString()}` };
}
}
}
console.log('FetLife Privacy Helper MetaMask detector loaded');
})();
\ No newline at end of file
...@@ -233,21 +233,38 @@ document.addEventListener('DOMContentLoaded', function() { ...@@ -233,21 +233,38 @@ document.addEventListener('DOMContentLoaded', function() {
}, 5000); }, 5000);
} }
// Function to check if MetaMask is available in popup context // Function to check if MetaMask is available via content script
function checkMetaMaskAvailable() { async function checkMetaMaskAvailable() {
return typeof window.ethereum !== 'undefined' || try {
(typeof window.web3 !== 'undefined' && typeof window.web3.currentProvider !== 'undefined'); // Get the current active tab
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!tab || !tab.id) {
return false;
}
// Send message to MetaMask detector content script
const response = await chrome.tabs.sendMessage(tab.id, { action: 'checkMetaMask' });
return response.available;
} catch (error) {
console.error('Error checking MetaMask availability:', error);
return false;
}
} }
// Function to handle Web3 donation directly in popup context // Function to handle Web3 donation via content script
async function executeWeb3Donation() { async function executeWeb3Donation() {
try { try {
// Check if MetaMask is installed // Get the current active tab
if (!checkMetaMaskAvailable()) { const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
return { success: false, message: 'MetaMask not detected. Please install MetaMask extension.' };
if (!tab || !tab.id) {
return { success: false, message: 'No active tab found.' };
} }
const ethereumProvider = window.ethereum || window.web3.currentProvider; // Send message to MetaMask detector content script to handle donation
const response = await chrome.tabs.sendMessage(tab.id, { action: 'executeWeb3Donation' });
return response;
// Request account access // Request account access
let accounts; let accounts;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment