Skip to content

Instantly share code, notes, and snippets.

@hsnsbhshsh
Created March 12, 2026 22:06
Show Gist options
  • Select an option

  • Save hsnsbhshsh/640f0d1f6841e7b5163a214a2567eaac to your computer and use it in GitHub Desktop.

Select an option

Save hsnsbhshsh/640f0d1f6841e7b5163a214a2567eaac to your computer and use it in GitHub Desktop.
Untitled
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🚀 أداة السحب التلقائي المتطورة - Auto Sweeper</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css">
<style>
:root {
--primary-color: #6366f1;
--secondary-color: #8b5cf6;
--success-color: #10b981;
--danger-color: #ef4444;
--warning-color: #f59e0b;
--dark-bg: #1f2937;
}
body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
font-family: 'Tajawal', sans-serif;
}
.main-container {
padding: 20px;
}
.dashboard-card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
margin-bottom: 30px;
overflow: hidden;
}
.card-header {
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
color: white;
padding: 20px;
border-bottom: none;
}
.card-header h2 {
margin: 0;
font-weight: 600;
display: flex;
align-items: center;
gap: 10px;
}
.stat-card {
background: white;
border-radius: 15px;
padding: 20px;
text-align: center;
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
transition: transform 0.3s;
}
.stat-card:hover {
transform: translateY(-5px);
}
.stat-icon {
font-size: 2.5rem;
color: var(--primary-color);
margin-bottom: 10px;
}
.stat-value {
font-size: 1.8rem;
font-weight: bold;
color: var(--dark-bg);
}
.stat-label {
color: #6b7280;
font-size: 0.9rem;
}
.network-badge {
display: inline-block;
padding: 5px 15px;
border-radius: 20px;
font-size: 0.9rem;
font-weight: 600;
margin: 0 5px 5px 0;
cursor: pointer;
transition: all 0.3s;
}
.network-badge.active {
background: var(--primary-color);
color: white;
transform: scale(1.05);
}
.network-badge.ethereum { background: #627eea; color: white; }
.network-badge.bsc { background: #f3ba2f; color: black; }
.network-badge.polygon { background: #8247e5; color: white; }
.token-item {
background: #f9fafb;
border-radius: 10px;
padding: 15px;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
border: 1px solid #e5e7eb;
transition: all 0.3s;
}
.token-item:hover {
border-color: var(--primary-color);
box-shadow: 0 5px 15px rgba(99, 102, 241, 0.1);
}
.token-info {
display: flex;
align-items: center;
gap: 15px;
}
.token-icon {
width: 40px;
height: 40px;
border-radius: 50%;
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
}
.token-balance {
font-size: 1.2rem;
font-weight: bold;
color: var(--dark-bg);
}
.progress {
height: 30px;
border-radius: 15px;
margin: 20px 0;
}
.progress-bar {
background: linear-gradient(90deg, var(--primary-color), var(--secondary-color));
font-weight: 600;
}
.alert {
border-radius: 15px;
border: none;
padding: 15px;
}
.btn-sweep {
background: linear-gradient(135deg, var(--danger-color), #dc2626);
color: white;
border: none;
padding: 12px 30px;
border-radius: 10px;
font-weight: 600;
transition: all 0.3s;
}
.btn-sweep:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px rgba(239, 68, 68, 0.3);
}
.btn-scan {
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
color: white;
border: none;
padding: 12px 30px;
border-radius: 10px;
font-weight: 600;
transition: all 0.3s;
}
.btn-scan:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px rgba(99, 102, 241, 0.3);
}
.transaction-log {
background: #1f2937;
color: #10b981;
padding: 15px;
border-radius: 10px;
font-family: 'Monaco', monospace;
font-size: 0.9rem;
max-height: 300px;
overflow-y: auto;
}
.transaction-log .log-entry {
padding: 5px;
border-bottom: 1px solid #374151;
}
.loading-spinner {
display: none;
text-align: center;
padding: 40px;
}
.loading-spinner .spinner-border {
width: 3rem;
height: 3rem;
}
.auto-sweep-toggle {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.auto-sweep-toggle input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: .4s;
border-radius: 34px;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
transition: .4s;
border-radius: 50%;
}
input:checked + .slider {
background-color: var(--success-color);
}
input:checked + .slider:before {
transform: translateX(26px);
}
</style>
</head>
<body>
<div class="container main-container">
<!-- رأس الصفحة -->
<div class="dashboard-card">
<div class="card-header">
<div class="d-flex justify-content-between align-items-center">
<h2><i class="bi bi-lightning-charge-fill"></i> أداة السحب التلقائي المتطورة - Auto Sweeper</h2>
<div>
<button class="btn btn-light" id="connectWallet">
<i class="bi bi-wallet2"></i> <span id="walletText">ربط المحفظة</span>
</button>
</div>
</div>
</div>
<!-- معلومات المحفظة -->
<div class="p-4" id="walletInfo" style="display: none;">
<div class="row">
<div class="col-md-6">
<div class="stat-card">
<div class="stat-icon"><i class="bi bi-wallet"></i></div>
<div class="stat-value" id="displayAddress">0x...</div>
<div class="stat-label">عنوان المحفظة</div>
</div>
</div>
<div class="col-md-6">
<div class="stat-card">
<div class="stat-icon"><i class="bi bi-cash-stack"></i></div>
<div class="stat-value" id="totalBalance">$0.00</div>
<div class="stat-label">القيمة الإجمالية</div>
</div>
</div>
</div>
</div>
</div>
<!-- لوحة التحكم الرئيسية -->
<div class="row">
<div class="col-md-8">
<div class="dashboard-card">
<div class="card-header">
<h3><i class="bi bi-grid"></i> لوحة التحكم</h3>
</div>
<div class="p-4">
<!-- اختيار الشبكة -->
<div class="mb-4">
<label class="form-label fw-bold">الشبكة:</label>
<div>
<span class="network-badge ethereum active" data-network="ethereum">
<i class="bi bi-currency-bitcoin"></i> Ethereum
</span>
<span class="network-badge bsc" data-network="bsc">
<i class="bi bi-currency-dollar"></i> BSC
</span>
<span class="network-badge polygon" data-network="polygon">
<i class="bi bi-hexagon"></i> Polygon
</span>
<span class="network-badge" data-network="arbitrum">
<i class="bi bi-arrow-up-right"></i> Arbitrum
</span>
</div>
</div>
<!-- عنوان المستلم -->
<div class="mb-4">
<label class="form-label fw-bold">🏦 عنوان المستلم (Master Wallet):</label>
<input type="text" class="form-control" id="masterAddress"
placeholder="0x..." value="0xYourMasterWalletAddress">
</div>
<!-- أزرار التحكم -->
<div class="row mb-4">
<div class="col-md-6">
<button class="btn-scan w-100" id="scanWallet">
<i class="bi bi-search"></i> مسح المحفظة وجمع العملات
</button>
</div>
<div class="col-md-6">
<button class="btn-sweep w-100" id="sweepAll" disabled>
<i class="bi bi-lightning"></i> سحب تلقائي للكل
</button>
</div>
</div>
<!-- تفعيل المراقبة التلقائية -->
<div class="mb-4 p-3 bg-light rounded">
<div class="d-flex justify-content-between align-items-center">
<div>
<h5 class="mb-1"><i class="bi bi-eye-fill"></i> المراقبة التلقائية</h5>
<p class="text-muted small mb-0">مسح تلقائي كل 60 ثانية وسحب أي رصيد جديد</p>
</div>
<label class="auto-sweep-toggle">
<input type="checkbox" id="autoSweepToggle">
<span class="slider"></span>
</label>
</div>
</div>
<!-- قائمة التوكنات -->
<div id="tokensList" style="display: none;">
<h5 class="mb-3">📋 العملات المكتشفة:</h5>
<div id="tokensContainer"></div>
</div>
<!-- مؤشر التحميل -->
<div class="loading-spinner" id="loading">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">جاري التحميل...</span>
</div>
<p class="mt-2" id="loadingText">جاري معالجة الطلب...</p>
</div>
<!-- شريط التقدم -->
<div id="progressContainer" style="display: none;">
<div class="progress">
<div id="progressBar" class="progress-bar progress-bar-striped progress-bar-animated"
role="progressbar" style="width: 0%">0%</div>
</div>
<p id="progressStatus" class="text-center mt-2"></p>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<!-- سجل المعاملات -->
<div class="dashboard-card">
<div class="card-header">
<h3><i class="bi bi-clock-history"></i> سجل المعاملات</h3>
</div>
<div class="p-0">
<div class="transaction-log" id="transactionLog">
<div class="log-entry">📝 جاهز لبدء العمليات...</div>
</div>
</div>
</div>
<!-- إحصائيات سريعة -->
<div class="dashboard-card">
<div class="card-header">
<h3><i class="bi bi-pie-chart"></i> إحصائيات</h3>
</div>
<div class="p-4">
<div class="mb-3">
<div class="d-flex justify-content-between">
<span>عدد المعاملات اليوم:</span>
<span class="fw-bold" id="dailyTxCount">0</span>
</div>
</div>
<div class="mb-3">
<div class="d-flex justify-content-between">
<span>إجمالي المسحوبات:</span>
<span class="fw-bold" id="totalSwept">$0.00</span>
</div>
</div>
<div class="mb-3">
<div class="d-flex justify-content-between">
<span>آخر عملية:</span>
<span class="fw-bold" id="lastSweep">-</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- حالة المعاملة -->
<div id="transactionStatus" class="position-fixed bottom-0 end-0 p-3" style="z-index: 11"></div>
<!-- إضافة المكتبات -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/web3@1.8.2/dist/web3.min.js"></script>
<script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
<script>
// تكوين التطبيق
const API_BASE_URL = window.location.hostname === 'localhost'
? 'http://localhost:5000'
: 'https://your-app.onrender.com';
let web3;
let userAccount;
let detectedTokens = [];
let activeNetwork = 'ethereum';
let socket;
let autoSweepInterval;
// تهيئة Socket.IO
function initSocket() {
socket = io(API_BASE_URL);
socket.on('connect', () => {
addToLog('✅ متصل بالخادم');
});
socket.on('status_update', (data) => {
addToLog(`📊 ${data.status} - ${new Date(data.timestamp).toLocaleTimeString()}`);
});
socket.on('disconnect', () => {
addToLog('🔌 تم قطع الاتصال بالخادم');
});
}
// تهيئة Web3
async function initWeb3() {
if (window.ethereum) {
web3 = new Web3(window.ethereum);
return true;
} else {
showStatus('الرجاء تثبيت MetaMask', 'danger');
return false;
}
}
// ربط المحفظة
document.getElementById('connectWallet').addEventListener('click', async () => {
try {
if (!await initWeb3()) return;
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
userAccount = accounts[0];
document.getElementById('walletText').innerHTML = '<i class="bi bi-check-circle"></i> متصل';
document.getElementById('walletInfo').style.display = 'block';
document.getElementById('displayAddress').textContent =
userAccount.substring(0, 6) + '...' + userAccount.substring(38);
showStatus('✅ تم ربط المحفظة بنجاح', 'success');
addToLog('🔗 تم ربط المحفظة: ' + userAccount);
// مسح المحفظة تلقائياً بعد الربط
setTimeout(() => scanWallet(), 1000);
} catch (error) {
showStatus('خطأ: ' + error.message, 'danger');
}
});
// اختيار الشبكة
document.querySelectorAll('.network-badge').forEach(badge => {
badge.addEventListener('click', function() {
document.querySelectorAll('.network-badge').forEach(b => b.classList.remove('active'));
this.classList.add('active');
activeNetwork = this.dataset.network;
addToLog(`🔄 تغيير الشبكة إلى: ${this.textContent.trim()}`);
if (userAccount) {
scanWallet();
}
});
});
// مسح المحفظة
document.getElementById('scanWallet').addEventListener('click', scanWallet);
async function scanWallet() {
if (!userAccount) {
showStatus('الرجاء ربط المحفظة أولاً', 'warning');
return;
}
showLoading(true, 'جاري مسح المحفظة...');
try {
const response = await fetch(`${API_BASE_URL}/api/scan`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
network: activeNetwork,
walletAddress: userAccount
})
});
const data = await response.json();
if (data.success) {
displayTokens(data.data);
document.getElementById('tokensList').style.display = 'block';
document.getElementById('sweepAll').disabled = false;
addToLog(`🔍 تم مسح المحفظة - الرصيد: ${data.data.native_balance} ${getNativeSymbol()}`);
// تحديث إجمالي الرصيد
updateTotalBalance(data.data);
} else {
showStatus('خطأ: ' + data.error, 'danger');
}
} catch (error) {
showStatus('خطأ في الاتصال: ' + error.message, 'danger');
} finally {
showLoading(false);
}
}
// عرض التوكنات
function displayTokens(data) {
const container = document.getElementById('tokensContainer');
container.innerHTML = '';
// عرض العملة الأساسية
addTokenToDisplay(container, {
symbol: getNativeSymbol(),
balance: data.native_balance,
isNative: true
});
// عرض التوكنات
data.tokens.forEach(token => {
addTokenToDisplay(container, token);
});
detectedTokens = data.tokens;
}
function addTokenToDisplay(container, token) {
const tokenDiv = document.createElement('div');
tokenDiv.className = 'token-item';
tokenDiv.innerHTML = `
<div class="token-info">
<div class="token-icon">${token.symbol.charAt(0)}</div>
<div>
<strong>${token.symbol}</strong>
<small class="text-muted d-block">${token.isNative ? 'Native' : 'Token'}</small>
</div>
</div>
<div class="token-balance">${token.balance} ${token.symbol}</div>
`;
container.appendChild(tokenDiv);
}
// تنفيذ السحب
document.getElementById('sweepAll').addEventListener('click', async () => {
if (!userAccount) {
showStatus('الرجاء ربط المحفظة أولاً', 'warning');
return;
}
const masterAddress = document.getElementById('masterAddress').value;
if (!web3.utils.isAddress(masterAddress)) {
showStatus('عنوان المستلم غير صالح', 'warning');
return;
}
// تأكيد العملية
if (!confirm('⚠️ تحذير: سيتم سحب جميع العملات من محفظتك. هل أنت متأكد؟')) {
return;
}
showLoading(true, 'جاري تجهيز المعاملات...');
document.getElementById('progressContainer').style.display = 'block';
try {
// طلب التوقيع من MetaMask للمعاملة الأولى
const accounts = await web3.eth.getAccounts();
const fromAddress = accounts[0];
// إنشاء معاملة السحب
const txCount = detectedTokens.length + 1; // +1 للعملة الأساسية
let completed = 0;
// سحب العملة الأساسية أولاً
const nativeSymbol = getNativeSymbol();
addToLog(`💰 بدء سحب ${nativeSymbol}...`);
// طلب إرسال معاملة ETH/BNB
const nativeBalance = await web3.eth.getBalance(fromAddress);
const gasPrice = await web3.eth.getGasPrice();
const gasLimit = 21000;
const gasCost = BigInt(gasPrice) * BigInt(gasLimit);
const amountToSend = BigInt(nativeBalance) - gasCost;
if (amountToSend > 0) {
const tx = {
from: fromAddress,
to: masterAddress,
value: amountToSend.toString(16),
gas: web3.utils.toHex(gasLimit),
gasPrice: web3.utils.toHex(gasPrice)
};
const txHash = await window.ethereum.request({
method: 'eth_sendTransaction',
params: [tx]
});
addToLog(`✅ تم سحب ${nativeSymbol}: ${txHash.substring(0, 10)}...`);
completed++;
updateProgress(completed, txCount);
}
// سحب التوكنات
for (const token of detectedTokens) {
try {
addToLog(`🔄 جاري سحب ${token.symbol}...`);
// هنا يمكن إضافة معاملات التوكنات
// تحتاج إلى إنشاء contract instance واستدعاء transfer
completed++;
updateProgress(completed, txCount);
// انتظار قليلاً بين المعاملات
await new Promise(resolve => setTimeout(resolve, 2000));
} catch (error) {
addToLog(`❌ فشل سحب ${token.symbol}: ${error.message}`);
}
}
showStatus('✅ اكتملت عملية السحب', 'success');
addToLog('🎉 اكتملت جميع عمليات السحب');
// إعادة مسح المحفظة
setTimeout(() => scanWallet(), 5000);
} catch (error) {
showStatus('خطأ: ' + error.message, 'danger');
addToLog(`❌ خطأ: ${error.message}`);
} finally {
showLoading(false);
setTimeout(() => {
document.getElementById('progressContainer').style.display = 'none';
}, 3000);
}
});
// تفعيل/إلغاء المراقبة التلقائية
document.getElementById('autoSweepToggle').addEventListener('change', function(e) {
if (e.target.checked) {
startAutoSweep();
} else {
stopAutoSweep();
}
});
function startAutoSweep() {
addToLog('▶️ بدء المراقبة التلقائية');
autoSweepInterval = setInterval(() => {
if (userAccount) {
scanWallet();
}
}, 60000); // كل 60 ثانية
}
function stopAutoSweep() {
addToLog('⏹️ إيقاف المراقبة التلقائية');
clearInterval(autoSweepInterval);
}
// دوال مساعدة
function getNativeSymbol() {
const symbols = {
'ethereum': 'ETH',
'bsc': 'BNB',
'polygon': 'MATIC',
'arbitrum': 'ETH'
};
return symbols[activeNetwork] || 'ETH';
}
function updateProgress(current, total) {
const percent = Math.round((current / total) * 100);
document.getElementById('progressBar').style.width = percent + '%';
document.getElementById('progressBar').textContent = percent + '%';
document.getElementById('progressStatus').textContent =
`جاري التنفيذ... ${current}/${total}`;
}
function updateTotalBalance(data) {
// هنا يمكن إضافة حساب القيمة الإجمالية باستخدام أسعار حقيقية
document.getElementById('totalBalance').textContent = `$${(data.native_balance * 2000).toFixed(2)}`; // مثال فقط
}
function showLoading(show, text = 'جاري التحميل...') {
document.getElementById('loading').style.display = show ? 'block' : 'none';
document.getElementById('loadingText').textContent = text;
document.getElementById('scanWallet').disabled = show;
document.getElementById('sweepAll').disabled = show;
}
function showStatus(message, type) {
const statusDiv = document.getElementById('transactionStatus');
const alertDiv = document.createElement('div');
alertDiv.className = `alert alert-${type} alert-dismissible fade show`;
alertDiv.role = 'alert';
alertDiv.innerHTML = `
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
statusDiv.appendChild(alertDiv);
setTimeout(() => {
alertDiv.remove();
}, 5000);
}
function addToLog(message) {
const log = document.getElementById('transactionLog');
const entry = document.createElement('div');
entry.className = 'log-entry';
entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
log.insertBefore(entry, log.firstChild);
// الاحتفاظ بآخر 50 رسالة فقط
while (log.children.length > 50) {
log.removeChild(log.lastChild);
}
}
// تهيئة
initSocket();
// مراقبة تغيير الحساب
if (window.ethereum) {
window.ethereum.on('accountsChanged', (accounts) => {
if (accounts.length > 0) {
userAccount = accounts[0];
document.getElementById('displayAddress').textContent =
userAccount.substring(0, 6) + '...' + userAccount.substring(38);
scanWallet();
} else {
userAccount = null;
document.getElementById('walletInfo').style.display = 'none';
document.getElementById('walletText').innerHTML = '<i class="bi bi-wallet2"></i> ربط المحفظة';
}
});
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment