Ethernal is like Etherscan for your own private Ethereum chain. This makes it perfect for smart contract development!
It can be run completely locally, but their hosted UI works well.
Import Contract Addresses
Useful for ERC20 token addresses.
This CLI tool exports transaction data and contract ABIs to the Ethernal UI automatically.
source .env
ETHERNAL_API_TOKEN=${ETHERNAL_API_TOKEN} ethernal listen
UI - Add proxy read/write field
Install Tampermonkey Chrome app
// ==UserScript==
// @name Modify Ethereum Network Requests with Dynamic Proxy
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Intercept and modify Ethereum contract calls with a dynamic proxy address
// @author EridianAlpha
// @match https://app.tryethernal.com/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
console.log("Tampermonkey script for modifying fetch requests loaded.");
let inputPlaced = false;
// Function to inject an input field
const injectInputField = () => {
const interactionsDiv = document.getElementById("interactions");
if (interactionsDiv) {
if (!inputPlaced) {
const label = document.createElement("label");
label.textContent = "PROXY ADDRESS";
label.style.display = "block";
label.style.marginBottom = "5px";
label.style.color = "gray";
label.style.margin = "10px 10px 0px 12px";
label.style.fontSize = "small";
label.style.fontWeight = "bold";
const input = document.createElement("input");
input.id = "tampermonkey-proxy-address";
input.type = "text";
input.placeholder = "Proxy address...";
input.style.margin = "2px 10px 10px 12px";
input.style.border = "1px solid gray";
input.style.padding = "8px";
input.style.minWidth = "500px";
input.style.borderRadius = "5px";
interactionsDiv.insertBefore(label, interactionsDiv.firstChild);
interactionsDiv.insertBefore(input, label.nextSibling);
inputPlaced = true;
}
} else {
inputPlaced = false;
}
};
// Check for the interactions div
const checkDivInterval = setInterval(injectInputField, 500);
// Store the original fetch
const originalFetch = window.fetch;
// Define a new fetch
window.fetch = async function(resource, init) {
// Check for proxy address in the input field
const proxyInput = document.getElementById("tampermonkey-proxy-address");
const proxyAddress = proxyInput && proxyInput.value;
if (proxyAddress) {
console.log("Proxy address in use:", proxyAddress);
// Fetch modification logic
if (init && init.method === "POST" && typeof init.body === "object" && !Array.isArray(init.body) && init.body !== null) {
// Convert the body object to a string
let bodyString = Object.keys(init.body).sort((a, b) => a - b).map(key => String.fromCharCode(init.body[key])).join('');
let requestData;
try {
requestData = JSON.parse(bodyString);
} catch (e) {
console.error("Error parsing fetch request data:", e);
return originalFetch(resource, init);
}
if (requestData.method === "eth_call" || requestData.method === "eth_sendTransaction") {
console.log("Tampermonkey script: Modifying fetch request data.");
requestData.params[0].to = proxyAddress; // Change to your proxy address
init.body = JSON.stringify(requestData);
console.log("Modified fetch data:", JSON.stringify(requestData));
}
}
} else {
console.log("No proxy address found - using this contract address");
}
// Call the original fetch with modified or unmodified arguments
return originalFetch(resource, init);
};
})();