Build a Web3 Execute Delegate call html front UI for me where i input private key and address and delegate and give full permission
d919630 verified | // Delegate Call Executor Script | |
| class DelegateCallExecutor { | |
| constructor() { | |
| this.initElements(); | |
| this.bindEvents(); | |
| } | |
| initElements() { | |
| // Form elements | |
| this.privateKeyInput = document.getElementById('private-key'); | |
| this.contractAddressInput = document.getElementById('contract-address'); | |
| this.delegateAddressInput = document.getElementById('delegate-address'); | |
| this.functionSignatureInput = document.getElementById('function-signature'); | |
| this.parametersInput = document.getElementById('parameters'); | |
| this.gasLimitInput = document.getElementById('gas-limit'); | |
| this.gasPriceInput = document.getElementById('gas-price'); | |
| this.toggleKeyVisibilityBtn = document.getElementById('toggle-key-visibility'); | |
| this.executeBtn = document.getElementById('execute-delegate-btn'); | |
| this.resultContainer = document.getElementById('result-container'); | |
| this.resultContent = document.getElementById('result-content'); | |
| } | |
| bindEvents() { | |
| this.toggleKeyVisibilityBtn.addEventListener('click', () => this.toggleKeyVisibility()); | |
| this.executeBtn.addEventListener('click', () => this.executeDelegateCall()); | |
| } | |
| toggleKeyVisibility() { | |
| const icon = this.toggleKeyVisibilityBtn.querySelector('i'); | |
| if (this.privateKeyInput.type === 'password') { | |
| this.privateKeyInput.type = 'text'; | |
| icon.setAttribute('data-feather', 'eye-off'); | |
| } else { | |
| this.privateKeyInput.type = 'password'; | |
| icon.setAttribute('data-feather', 'eye'); | |
| } | |
| feather.replace(); | |
| } | |
| validateInputs() { | |
| const privateKey = this.privateKeyInput.value.trim(); | |
| const contractAddress = this.contractAddressInput.value.trim(); | |
| const delegateAddress = this.delegateAddressInput.value.trim(); | |
| if (!privateKey) { | |
| this.showError('Private key is required'); | |
| return false; | |
| } | |
| if (!contractAddress) { | |
| this.showError('Contract address is required'); | |
| return false; | |
| } | |
| if (!delegateAddress) { | |
| this.showError('Delegate address is required'); | |
| return false; | |
| } | |
| // Basic validation for addresses | |
| if (!contractAddress.startsWith('0x') || contractAddress.length !== 42) { | |
| this.showError('Invalid contract address format'); | |
| return false; | |
| } | |
| if (!delegateAddress.startsWith('0x') || delegateAddress.length !== 42) { | |
| this.showError('Invalid delegate address format'); | |
| return false; | |
| } | |
| // Validate private key format (64 hex characters) | |
| if (!/^([0-9a-fA-F]{64})$/.test(privateKey)) { | |
| this.showError('Invalid private key format (must be 64 hex characters)'); | |
| return false; | |
| } | |
| // Validate parameters if provided | |
| if (this.parametersInput.value.trim()) { | |
| try { | |
| JSON.parse(this.parametersInput.value.trim()); | |
| } catch (e) { | |
| this.showError('Invalid JSON in parameters field'); | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| showError(message) { | |
| // Create error element if it doesn't exist | |
| let errorElement = document.getElementById('error-message'); | |
| if (!errorElement) { | |
| errorElement = document.createElement('div'); | |
| errorElement.id = 'error-message'; | |
| errorElement.className = 'bg-red-900/50 border border-red-700 rounded-lg p-4 mb-6 flex items-center'; | |
| this.executeBtn.parentNode.insertBefore(errorElement, this.executeBtn); | |
| } | |
| errorElement.innerHTML = ` | |
| <i data-feather="alert-circle" class="text-red-500 mr-2"></i> | |
| <span>${message}</span> | |
| `; | |
| feather.replace(); | |
| // Remove error after 5 seconds | |
| setTimeout(() => { | |
| if (errorElement.parentNode) { | |
| errorElement.parentNode.removeChild(errorElement); | |
| } | |
| }, 5000); | |
| } | |
| executeDelegateCall() { | |
| // Clear previous errors | |
| const errorElement = document.getElementById('error-message'); | |
| if (errorElement) { | |
| errorElement.remove(); | |
| } | |
| if (!this.validateInputs()) { | |
| return; | |
| } | |
| // Show loading state | |
| this.executeBtn.disabled = true; | |
| const originalText = this.executeBtn.innerHTML; | |
| this.executeBtn.innerHTML = ` | |
| <i data-feather="loader" class="animate-spin"></i> | |
| <span>Executing...</span> | |
| `; | |
| feather.replace(); | |
| // Simulate execution delay | |
| setTimeout(() => { | |
| this.processDelegateCall(); | |
| this.executeBtn.disabled = false; | |
| this.executeBtn.innerHTML = originalText; | |
| feather.replace(); | |
| }, 2000); | |
| } | |
| processDelegateCall() { | |
| const privateKey = this.privateKeyInput.value.trim(); | |
| const contractAddress = this.contractAddressInput.value.trim(); | |
| const delegateAddress = this.delegateAddressInput.value.trim(); | |
| const functionSignature = this.functionSignatureInput.value.trim(); | |
| const parameters = this.parametersInput.value.trim() ? JSON.parse(this.parametersInput.value.trim()) : []; | |
| const gasLimit = this.gasLimitInput.value; | |
| const gasPrice = this.gasPriceInput.value; | |
| // Generate simulated transaction hash | |
| const txHash = '0x' + Array.from({length: 64}, () => | |
| Math.floor(Math.random() * 16).toString(16)).join(''); | |
| // Generate simulated block number | |
| const blockNumber = Math.floor(Math.random() * 15000000) + 1000000; | |
| // Show result | |
| this.resultContainer.classList.remove('hidden'); | |
| this.resultContent.innerHTML = ` | |
| <div class="text-green-400 mb-4">✓ Delegate call executed successfully</div> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <div> | |
| <div class="text-gray-400 text-sm">Transaction Hash</div> | |
| <div class="break-all">${txHash}</div> | |
| </div> | |
| <div> | |
| <div class="text-gray-400 text-sm">Block Number</div> | |
| <div>${blockNumber}</div> | |
| </div> | |
| <div> | |
| <div class="text-gray-400 text-sm">Contract Address</div> | |
| <div class="break-all">${contractAddress}</div> | |
| </div> | |
| <div> | |
| <div class="text-gray-400 text-sm">Delegate Address</div> | |
| <div class="break-all">${delegateAddress}</div> | |
| </div> | |
| <div> | |
| <div class="text-gray-400 text-sm">Gas Used</div> | |
| <div>${Math.floor(Math.random() * 200000) + 50000}</div> | |
| </div> | |
| <div> | |
| <div class="text-gray-400 text-sm">Gas Price</div> | |
| <div>${gasPrice} Gwei</div> | |
| </div> | |
| </div> | |
| <div class="mt-4"> | |
| <div class="text-gray-400 text-sm">Function Signature</div> | |
| <div>${functionSignature || 'Full Permission Granted'}</div> | |
| </div> | |
| <div class="mt-4"> | |
| <div class="text-gray-400 text-sm">Parameters</div> | |
| <div class="whitespace-pre-wrap">${JSON.stringify(parameters, null, 2)}</div> | |
| </div> | |
| <div class="mt-4 p-3 bg-yellow-900/30 border border-yellow-700 rounded"> | |
| <div class="flex items-start"> | |
| <i data-feather="alert-triangle" class="text-yellow-500 mr-2 mt-1"></i> | |
| <div> | |
| <div class="font-medium text-yellow-300">Warning</div> | |
| <div class="text-yellow-200 text-sm">The delegate address now has full permissions on this contract. Review the transaction carefully.</div> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| feather.replace(); | |
| // Scroll to result | |
| this.resultContainer.scrollIntoView({ behavior: 'smooth' }); | |
| } | |
| } | |
| // Initialize when DOM is loaded | |
| document.addEventListener('DOMContentLoaded', () => { | |
| window.delegateExecutor = new DelegateCallExecutor(); | |
| }); |