├── .gitignore ├── src ├── js │ ├── inject.js │ ├── background.js │ └── content.js └── html │ ├── popup.js │ └── popup.html ├── manifest.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | content-backup.js -------------------------------------------------------------------------------- /src/js/inject.js: -------------------------------------------------------------------------------- 1 | window.InscriptionHelperPresent = true; -------------------------------------------------------------------------------- /src/js/background.js: -------------------------------------------------------------------------------- 1 | chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { 2 | if (changeInfo.status === 'complete' && tab.active) { 3 | // Execute your content script instead of just logging a message 4 | chrome.scripting.executeScript({ 5 | target: { tabId: tabId }, 6 | files: ['content.js'] // Ensure this path is correct 7 | }); 8 | } 9 | }); -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "name": "Inscription Helper", 4 | "description": "Inscription Helper is designed to seamlessly load IPFS files directly from Bitcoin Ordinals inscriptions.", 5 | "version": "0.1", 6 | "permissions": ["activeTab", "scripting", "storage"], 7 | "background": { 8 | "service_worker": "/src/js/background.js" 9 | }, 10 | "action": { 11 | "default_popup": "/src/html/popup.html" 12 | }, 13 | "content_scripts": [ 14 | { 15 | "matches": [""], 16 | "js": ["/src/js/content.js"] 17 | } 18 | ], 19 | "web_accessible_resources": [ 20 | { 21 | "resources": ["/src/js/inject.js"], 22 | "matches": [""] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/html/popup.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function() { 2 | // Get the current value from storage and set it as the input's placeholder 3 | chrome.storage.local.get('ipfsGateway', function(data) { 4 | const currentGateway = data.ipfsGateway || 'https://ipfs.io/ipfs/'; // Default gateway if none saved 5 | document.getElementById('gateway').placeholder = currentGateway; 6 | }); 7 | 8 | // Save button event listener 9 | document.getElementById('save').addEventListener('click', function() { 10 | const gateway = document.getElementById('gateway').value; 11 | if (gateway) { 12 | // Save the user's preferred gateway to storage 13 | chrome.storage.local.set({ 'ipfsGateway': gateway }, function() { 14 | console.log('Gateway URL saved: ' + gateway); 15 | // Optionally, you can provide user feedback here, like updating the placeholder to the new value 16 | document.getElementById('gateway').placeholder = gateway; 17 | }); 18 | } 19 | }); 20 | }); -------------------------------------------------------------------------------- /src/html/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Inscription Helper - Configuration 5 | 48 | 49 | 50 |

Inscription Helper - Configuration

51 |
52 | 53 | 54 | 55 | 56 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Inscription Helper Chrome Extension 3 | 4 | ## Overview 5 | 6 | Inscription Helper is a Chrome extension designed to seamlessly load IPFS (InterPlanetary File System) files directly from Bitcoin Ordinals inscriptions. This extension is especially useful for those interacting with Bitcoin Ordinals, as it automatically recognizes inscriptions requesting files with `ipfs://` protocol and retrieves them using IPFS. 7 | 8 | ## Features 9 | 10 | - **IPFS Integration**: Automatically detects `ipfs://` links in Bitcoin Ordinals inscriptions and loads the associated files. 11 | - **Customizable IPFS Gateway**: Users can configure their preferred IPFS gateway. The default gateway is `https://ipfs.io/ipfs/`. 12 | - **User-Friendly Interface**: Simple and easy-to-use interface, enhancing the user experience in interacting with Bitcoin Ordinals and IPFS. 13 | 14 | ## Installation 15 | 16 | Follow these steps to install Inscription Helper: 17 | 18 | 1. **Clone the Repository** 19 | 20 | - Open your terminal. 21 | - Run the command: `git clone https://github.com/jerryfane/inscription-helper.git` 22 | - This will download the code to your local machine. 23 | 2. **Enable Developer Mode in Chrome** 24 | 25 | - Open the Chrome browser. 26 | - Go to `chrome://extensions/` in your browser. 27 | - Enable 'Developer mode' at the top-right corner. 28 | 3. **Load the Extension** 29 | 30 | - Click on 'Load unpacked' button on the top-left corner. 31 | - Navigate to the directory where you cloned the Inscription Helper repository. 32 | - Select the folder and click 'Open'. 33 | 34 | The Inscription Helper Chrome Extension should now be added to your Chrome browser and ready to use. 35 | 36 | ## Configuration 37 | 38 | To configure a different IPFS gateway: 39 | 40 | - Click on the Inscription Helper icon in your Chrome toolbar. 41 | - Go to the settings page in the extension. 42 | - Enter the URL of your preferred IPFS gateway. 43 | - Save the changes. 44 | 45 | The extension will now use your specified gateway to load IPFS files. 46 | 47 | ## Usage 48 | 49 | Simply browse Bitcoin Ordinals and when an inscription with an `ipfs://` link is detected, Inscription Helper will automatically retrieve the file via the configured IPFS gateway. 50 | 51 | ## Donations 52 | 53 | If you find Inscription Helper useful and would like to support its development, consider making a donation. Any amount is greatly appreciated and will help further development and maintenance. 54 | 55 | Bitcoin Address for Donations: `bc1pqgxx27urevpvtxrnfdahgfxcn55vhv63sv7v9xujy3mraykhcf9q7xlumn` 56 | 57 | ## Support 58 | 59 | For support, feature requests, or bug reports, please open an issue on the [GitHub repository page](https://github.com/jerryfane/inscription-helper/issues). 60 | 61 | ## License 62 | 63 | Inscription Helper is licensed under [MIT License](https://opensource.org/licenses/MIT). -------------------------------------------------------------------------------- /src/js/content.js: -------------------------------------------------------------------------------- 1 | async function replaceIPFSProtocol(node) { 2 | try { 3 | const data = await chrome.storage.local.get('ipfsGateway'); 4 | const gateway = data.ipfsGateway || 'https://ipfs.io/ipfs/'; 5 | 6 | if (node.nodeType === Node.ELEMENT_NODE && node.hasAttributes()) { 7 | const attributes = node.attributes; 8 | for (let attr of attributes) { 9 | if (attr.value.includes('ipfs://')) { 10 | attr.value = attr.value.replace(/ipfs:\/\//g, gateway); 11 | } 12 | } 13 | } 14 | } catch (error) { 15 | console.error('Error in replaceIPFSProtocol:', error); 16 | } 17 | } 18 | 19 | function handleMutations(mutations) { 20 | for (let mutation of mutations) { 21 | for (let node of mutation.addedNodes) { 22 | // Existing IPFS protocol replacement 23 | replaceIPFSProtocol(node); 24 | 25 | // Check for the addition of the inscribe button or its container 26 | if (node.nodeType === Node.ELEMENT_NODE) { 27 | if (node.id === 'inscribe-button' || node.querySelector('#inscribe-button')) { 28 | setupInscribeButtonListener(); 29 | } 30 | } 31 | } 32 | } 33 | } 34 | 35 | function setupInscribeButtonListener() { 36 | const inscribeButton = document.getElementById('inscribe-button'); 37 | const verifyButton = document.getElementById('verify-button'); 38 | if (inscribeButton && verifyButton) { 39 | inscribeButton.addEventListener('click', handleInscribeClick); 40 | verifyButton.addEventListener('click', handleInscribeClick); 41 | } else { 42 | console.log('Inscribe or Verify button not found'); 43 | } 44 | } 45 | 46 | function handleInscribeClick() { 47 | console.log('Inscribe or Verify clicked'); 48 | const modalImageSrc = document.querySelector('#modal-image-container img').src; 49 | 50 | getImageAsBase64(modalImageSrc) 51 | .then(base64data => { 52 | // Inject the base64 data into the page 53 | window.postMessage({ 54 | type: 'SET_BASE64_DATA', 55 | base64data: base64data 56 | }, '*'); 57 | 58 | console.log('window.currentBase64data has been set in the page context.'); 59 | }) 60 | .catch(error => { 61 | console.error('Error fetching image:', error); 62 | }); 63 | } 64 | 65 | async function getImageAsBase64(url) { 66 | try { 67 | const response = await fetch(url); 68 | if (!response.ok) { 69 | throw new Error('Network response was not ok'); 70 | } 71 | const blob = await response.blob(); 72 | return new Promise((resolve, reject) => { 73 | const reader = new FileReader(); 74 | reader.onloadend = () => resolve(reader.result); // Base64 string 75 | reader.onerror = reject; 76 | reader.readAsDataURL(blob); 77 | }); 78 | } catch (error) { 79 | console.error('Error fetching image:', error); 80 | } 81 | } 82 | 83 | // Existing code to inject script and create observer 84 | var s = document.createElement('script'); 85 | s.src = chrome.runtime.getURL('./src/js/inject.js'); 86 | s.onload = function() { 87 | this.remove(); 88 | }; 89 | (document.head || document.documentElement).appendChild(s); 90 | 91 | // Existing MutationObserver setup 92 | const observer = new MutationObserver(handleMutations); 93 | observer.observe(document, { 94 | childList: true, 95 | subtree: true 96 | }); 97 | 98 | // Replace protocols for existing nodes on the page 99 | document.querySelectorAll('*').forEach(node => { 100 | replaceIPFSProtocol(node); 101 | }); --------------------------------------------------------------------------------