Here's the complete code to handle deposits, withdrawals, and the corresponding USDT transactions using MetaMask and PHP.
### 1. **Database and PHP Backend (Deposit/Withdrawal Logic)**
```php
<?php
// Database connection details
$servername = "localhost";
$username = "your_db_username";
$password = "your_db_password";
$dbname = "your_db_name";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Handle deposit or withdrawal request
$action = $_POST['action']; // 'deposit' or 'withdrawal'
$walletAddress = $_POST['walletAddress']; // MetaMask wallet address
$amount = $_POST['amount']; // Amount to deposit or withdraw
if ($action == 'deposit') {
// Deposit logic
// Check if the user exists
$sql = "SELECT * FROM users WHERE wallet_address = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $walletAddress);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows == 0) {
// User does not exist, insert new user
$insertQuery = "INSERT INTO users (wallet_address, usdt_balance) VALUES (?, ?)";
$insertStmt = $conn->prepare($insertQuery);
$insertStmt->bind_param("sd", $walletAddress, $amount);
$insertStmt->execute();
echo "New user added, balance updated!";
} else {
// User exists, update balance
$updateQuery = "UPDATE users SET usdt_balance = usdt_balance + ? WHERE wallet_address = ?";
$updateStmt = $conn->prepare($updateQuery);
$updateStmt->bind_param("ds", $amount, $walletAddress);
$updateStmt->execute();
echo "Balance updated successfully!";
}
} elseif ($action == 'withdrawal') {
// Withdrawal logic
// Check if the user exists
$sql = "SELECT usdt_balance FROM users WHERE wallet_address = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $walletAddress);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows == 0) {
echo "Error: User does not exist.";
} else {
$row = $result->fetch_assoc();
$currentBalance = $row['usdt_balance'];
if ($currentBalance < $amount) {
echo "Error: Insufficient balance!";
} else {
// Deduct the withdrawal amount
$newBalance = $currentBalance - $amount;
$updateQuery = "UPDATE users SET usdt_balance = ? WHERE wallet_address = ?";
$updateStmt = $conn->prepare($updateQuery);
$updateStmt->bind_param("ds", $newBalance, $walletAddress);
if ($updateStmt->execute()) {
echo "Withdrawal request processed successfully!";
// Call the frontend JS to transfer USDT to MetaMask
} else {
echo "Error: Failed to process withdrawal.";
}
}
}
}
$conn->close();
?>
```
### 2. **Front-End JavaScript (MetaMask Integration for USDT Transactions)**
This JavaScript handles the **MetaMask** USDT transactions (deposit to the project wallet and withdrawal to the user's wallet).
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>USDT Deposit/Withdrawal</title>
<script src="https://cdn.jsdelivr.net/npm/ethers@5.4.4/dist/ethers.min.js"></script>
</head>
<body>
<!-- Input for deposit and withdrawal -->
<form id="transactionForm">
<input type="text" id="walletAddress" placeholder="Enter MetaMask Wallet Address" required>
<input type="number" id="amount" placeholder="Enter Amount" required>
<button type="button" onclick="deposit()">Deposit</button>
<button type="button" onclick="withdraw()">Withdraw</button>
</form>
<script>
const usdtContractAddress = "USDT_CONTRACT_ADDRESS"; // Replace with actual USDT contract address
const usdtABI = [ /* USDT ABI goes here */ ]; // Replace with actual USDT ABI
const projectWalletAddress = "0xYourProjectWalletAddress"; // Replace with your project wallet address
// MetaMask deposit function
async function deposit() {
const walletAddress = document.getElementById('walletAddress').value;
const amount = document.getElementById('amount').value;
const amountInUSDT = ethers.utils.parseUnits(amount, 6); // USDT uses 6 decimal places
try {
// MetaMask provider
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
// Get USDT contract
const usdtContract = new ethers.Contract(usdtContractAddress, usdtABI, signer);
// Call MetaMask to transfer USDT to project wallet
const tx = await usdtContract.transfer(projectWalletAddress, amountInUSDT);
await tx.wait();
alert("Deposit successful! Transaction hash: " + tx.hash);
// Now send the deposit data to your backend
sendTransactionData(walletAddress, amount, 'deposit');
} catch (error) {
console.error("Deposit failed", error);
}
}
// MetaMask withdrawal function
async function withdraw() {
const walletAddress = document.getElementById('walletAddress').value;
const amount = document.getElementById('amount').value;
const amountInUSDT = ethers.utils.parseUnits(amount, 6); // USDT uses 6 decimal places
try {
// MetaMask provider
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
// Get USDT contract
const usdtContract = new ethers.Contract(usdtContractAddress, usdtABI, signer);
// Call MetaMask to transfer USDT from project wallet to user's MetaMask wallet
const tx = await usdtContract.transfer(walletAddress, amountInUSDT);
await tx.wait();
alert("Withdrawal successful! Transaction hash: " + tx.hash);
// Now send the withdrawal data to your backend
sendTransactionData(walletAddress, amount, 'withdrawal');
} catch (error) {
console.error("Withdrawal failed", error);
}
}
// Send transaction data to backend (deposit or withdrawal)
function sendTransactionData(walletAddress, amount, action) {
const formData = new FormData();
formData.append('walletAddress', walletAddress);
formData.append('amount', amount);
formData.append('action', action);
fetch('transaction.php', {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(data => {
console.log(data);
alert(data);
})
.catch(error => {
console.error('Error:', error);
});
}
</script>
</body>
</html>
```
### Breakdown of Code:
1. **PHP (Backend)**:
- Handles both **deposits** and **withdrawals**.
- Deposits add to the user's balance.
- Withdrawals first check if the user has enough balance and then deduct the withdrawal amount.
2. **JavaScript (Front-End)**:
- **MetaMask** integration using **`ethers.js`** for USDT transfer.
- Users can **deposit** USDT into the project’s wallet.
- Users can **withdraw** USDT from the project wallet back to their MetaMask wallet.
### Flow:
1. The user enters their MetaMask wallet address and amount.
2. They choose to either **deposit** or **withdraw**.
3. The MetaMask transaction is processed, and then the backend (PHP) is updated with the new balance.
Demo code for testing
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test USDT Transfer</title>
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js"></script>
</head>
<body>
<h2>USDT Transfer Demo</h2>
<button id="connectMetamask">Connect MetaMask</button>
<p>From Address: <span id="fromAddress"></span></p>
<p>USDT Balance: <span id="usdtBalance"></span></p>
<h3>Transfer USDT</h3>
<form id="transferForm">
<label for="recipient">Recipient Address:</label>
<input type="text" id="recipient" required><br>
<label for="amount">Amount (USDT):</label>
<input type="number" id="amount" required><br>
<button type="submit">Send USDT</button>
</form>
<script>
const usdtContractAddress = '0xYourTestnetUSDTContractAddress'; // USDT Contract on Testnet
const usdtABI = [ /* USDT ABI */ ]; // Paste the USDT ABI here
let web3;
let usdtContract;
let fromAddress;
// Connect to MetaMask
document.getElementById('connectMetamask').addEventListener('click', async () => {
if (typeof window.ethereum !== 'undefined') {
web3 = new Web3(window.ethereum);
await window.ethereum.request({ method: 'eth_requestAccounts' });
fromAddress = (await web3.eth.getAccounts())[0];
document.getElementById('fromAddress').innerText = fromAddress;
// Initialize USDT contract
usdtContract = new web3.eth.Contract(usdtABI, usdtContractAddress);
// Fetch USDT balance
const usdtBalance = await usdtContract.methods.balanceOf(fromAddress).call();
document.getElementById('usdtBalance').innerText = web3.utils.fromWei(usdtBalance, 'mwei'); // USDT is 6 decimals
} else {
alert('MetaMask not found');
}
});
// Transfer USDT
document.getElementById('transferForm').addEventListener('submit', async (event) => {
event.preventDefault();
const recipient = document.getElementById('recipient').value;
const amount = web3.utils.toWei(document.getElementById('amount').value, 'mwei'); // Convert amount to 6 decimals (USDT)
try {
const tx = await usdtContract.methods.transfer(recipient, amount).send({ from: fromAddress });
console.log('Transaction successful:', tx);
alert('USDT sent successfully!');
} catch (error) {
console.error('Transaction failed:', error);
alert('Transaction fai
led!');
}
});
</script>
</body>
</html>