तो, पिछले दो लेखों में हमने एक "सुरक्षित संचार चैनल" बनाया और स्वैप लॉजिक लिखा। इस अंतिम भाग में, हम इस टूल को पूरा कर रहे हैं। हम ब्लॉक वेटिंग लूप को लागू करेंगे और सब कुछ एक सुविधाजनक कमांड लाइन इंटरफ़ेस (CLI) में लपेट देंगे।
1. भेजने का लॉजिक: आप सीधे "Send" पर क्लिक क्यों नहीं कर सकते?
एथेरियम नेटवर्क लगभग हर 12 सेकंड में एक ब्लॉक जेनरेट करता है। आपका बंडल केवल एक विशिष्ट ब्लॉक नंबर के लिए मान्य होता है। यदि यह निकटतम ब्लॉक में नहीं आता है (उदाहरण के लिए, कम टिप के कारण), तो आपको इसे अपडेट किए गए नंबर के साथ अगले ब्लॉक के लिए फिर से तैयार करना होगा।
हम एक लूप का उपयोग करेंगे जो अगले 10 ब्लॉकों के दौरान हमारे 'Stealth Swap' को "पुश" करने की कोशिश करेगा।
2. कोड: सेंडिंग और CLI का कार्यान्वयन
आइए अंतिम sendBundle मेथड और सरल कमांड-लाइन आर्गुमेंट हैंडलिंग जोड़ें।
import { FlashbotsBundleResolution } from "@flashbots/ethers-provider-bundle";
async function runStealthSwap(amountInEth: string) {
const { wallet, flashbotsProvider, provider } = await initStealthProvider();
const amountIn = ethers.parseEther(amountInEth);
let currentBlock = await provider.getBlockNumber();
console.log(`स्टार्ट ब्लॉक: ${currentBlock}`);
// अगले 10 ब्लॉकों में बंडल भेजने की कोशिश करते हैं
for (let i = 0; i < 10; i++) {
const targetBlock = currentBlock + i;
// विशिष्ट ब्लॉक के लिए बंडल को फिर से तैयार करें (सिमुलेशन सहित)
const signedBundle = await createAndSimulateBundle(wallet, flashbotsProvider, provider, amountIn, targetBlock);
if (!signedBundle) continue;
const bundleSubmission = await flashbotsProvider.sendBundle(signedBundle, targetBlock);
if ("error" in bundleSubmission) {
console.error(`भेजने में त्रुटि: ${bundleSubmission.error.message}`);
continue;
}
console.log(`बंडल भेज दिया गया। ब्लॉक ${targetBlock} का इंतज़ार है...`);
const waitResponse = await bundleSubmission.wait();
if (waitResponse === FlashbotsBundleResolution.BundleIncluded) {
console.log(`जीत! ट्रांजेक्शन ब्लॉक ${targetBlock} में शामिल हो गई`);
console.log(`हैश: https://etherscan.io/tx/${(await signedBundle)[0].hash}`); // अनुमानित हैश
return;
} else if (waitResponse === FlashbotsBundleResolution.BlockPassedWithoutInclusion) {
console.log(`चूक गए। ब्लॉक ${targetBlock} हमारे बिना निकल गया। अगले की कोशिश करते हैं...`);
} else if (waitResponse === FlashbotsBundleResolution.AccountNonceTooHigh) {
console.error("त्रुटि: नॉनसे (Nonce) बहुत अधिक है। अपनी पेंडिंग ट्रांजेक्शन चेक करें।");
return;
}
}
}
// बेसिक CLI इंटरफ़ेस
const amount = process.argv[2] || "0.01";
runStealthSwap(amount);जाहिर है, हमने अब तक जो बनाया है वह Uniswap V3 के माध्यम से स्वैपिंग के लिए सिर्फ एक "Flashbots Hello World" है। इसे एक असली वर्किंग टूल बनाने के लिए, हमें इसमें थोड़ी और जान फूँकनी होगी।
import { ethers } from "ethers";
import { FlashbotsBundleProvider, FlashbotsBundleResolution } from "@flashbots/ethers-provider-bundle";
import * as dotenv from "dotenv";
dotenv.config();
const WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const ROUTER = "0xE592427A0AEce92De3Edee1F18E0157C05861564";
const QUOTER = "0x61fFe014bA17989E743c5F6cB21bF9697530B21e";
const ABI = [
"function exactInputSingle((address tokenIn, address tokenOut, uint24 fee, address recipient, uint256 deadline, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96)) external returns (uint256 amountOut)",
"function quoteExactInputSingle((address tokenIn, address tokenOut, uint256 amountIn, uint24 fee, uint160 sqrtPriceLimitX96)) external returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)",
"function approve(address spender, uint256 amount) external returns (bool)",
"function allowance(address owner, address spender) external view returns (uint256)",
"function balanceOf(address account) external view returns (uint256)"
];
async function main() {
const provider = new ethers.JsonRpcProvider(process.env.ETH_RPC_URL);
const wallet = new ethers.Wallet(process.env.SENDER_PRIVATE_KEY, provider);
const authSigner = new ethers.Wallet(process.env.FLASHBOTS_AUTH_KEY, provider);
const flashbots = await FlashbotsBundleProvider.create(provider, authSigner);
const quoter = new ethers.Contract(QUOTER, ABI, provider);
const weth = new ethers.Contract(WETH, ABI, wallet);
const baseAmount = ethers.parseEther(process.argv[2] || "0.1");
const minThreshold = ethers.parseUnits(process.argv[3] || "200", 6);
// --- प्री-चेक (PRECHECK) ---
const balance = await weth.balanceOf(wallet.address);
if (balance < baseAmount) throw new Error("WETH कम है");
const allowance = await weth.allowance(wallet.address, ROUTER);
if (allowance < baseAmount) {
await (await weth.approve(ROUTER, ethers.MaxUint256)).wait();
}
let nonce = await wallet.getNonce();
let lastQuote = 0n;
let lastExecutionBlock = 0;
provider.on("block", async (block) => {
try {
// --- रैंडम स्किप (पैटर्न तोड़ने के लिए) ---
if (Math.random() < 0.6) return;
const quote = await quoter.quoteExactInputSingle.staticCall({
tokenIn: WETH,
tokenOut: USDC,
amountIn: baseAmount,
fee: 3000,
sqrtPriceLimitX96: 0
});
// --- थ्रेशोल्ड (Threshold) ---
if (quote.amountOut < minThreshold) return;
// --- बदलाव का पता लगाना (Change Detection) ---
if (lastQuote !== 0n) {
const diff = (quote.amountOut * 1000n) / lastQuote;
// अगर बदलाव < 0.3% है तो इग्नोर करें
if (diff > 997n && diff < 1003n) return;
}
// --- कूल डाउन (Cool Down) ---
if (block - lastExecutionBlock < 2) return;
// --- रैंडम अमाउंट (सिग्नेचर छिपाने के लिए) ---
const randomFactor = BigInt(95 + Math.floor(Math.random() * 10)); // 95–105%
const amountIn = (baseAmount * randomFactor) / 100n;
// --- स्लिपेज (Slippage) ---
const minOut = (quote.amountOut * 995n) / 1000n;
const feeData = await provider.getFeeData();
const tx = {
to: ROUTER,
data: new ethers.Interface(ABI).encodeFunctionData("exactInputSingle", [{
tokenIn: WETH,
tokenOut: USDC,
fee: 3000,
recipient: wallet.address,
deadline: Math.floor(Date.now() / 1000) + 90,
amountIn: amountIn,
amountOutMinimum: minOut,
sqrtPriceLimitX96: 0
}]),
chainId: 1,
type: 2,
gasLimit: 250000,
maxFeePerGas: feeData.maxFeePerGas,
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas || 2n,
nonce: nonce
};
const signed = await flashbots.signBundle([{ signer: wallet, transaction: tx }]);
const target = block + 1;
const sim = await flashbots.simulate(signed, target);
if ("error" in sim) return;
const sub = await flashbots.sendBundle(signed, target);
if ("error" in sub) return;
const res = await sub.wait();
nonce++; // ज़रूरी
if (res === FlashbotsBundleResolution.BundleIncluded) {
console.log("एग्जीक्यूटेड (EXECUTED):", target);
process.exit(0);
}
lastQuote = quote.amountOut;
lastExecutionBlock = block;
} catch (e) {
// शांत रहें (Quiet Mode)
}
});
}
main();
3. Anti-MEV Stealth Swap का उपयोग कैसे करें
1. इंस्टालेशन
npm install ethers @flashbots/ethers-provider-bundle dotenv2. .env फ़ाइल बनाएँ
ETH_RPC_URL=https://mainnet.infura.io/v3/आपका_की
SENDER_PRIVATE_KEY=आपका_प्राइवेट_की
FLASHBOTS_AUTH_KEY=कोई_भी_नया_प्राइवेट_की3. वॉलेट की तैयारी
अनिवार्य:
- वॉलेट में एथेरियम (ETH) होना चाहिए → गैस के लिए।
- और रैप्ड ईथर (WETH) → एक्सचेंज के लिए।
अगर WETH नहीं है:
- पहले किसी भी इंटरफ़ेस (जैसे Uniswap) के ज़रिए ETH को WETH में बदलें।
4. लॉन्च (Run)
node app.js 0.1 200जहाँ:
- 0.1 → कितना WETH बदलना है।
- 200 → USDC में न्यूनतम स्वीकार्य आउटपुट।
5. यह कैसे काम करता है?
लॉन्च के बाद:
- WETH बैलेंस चेक किया जाता है।
- एप्रूव (Approve) किया जाता है (केवल 1 बार)।
- स्क्रिप्ट ब्लॉक को "सुनना" शुरू करती है।
- हर ब्लॉक पर:
- कभी-कभी स्किप करती है (रैंडम)।
- Quoter के ज़रिए कीमत लेती है।
- थ्रेशोल्ड चेक करती है।
- कीमत में बदलाव चेक करती है।
- सौदा (Trade) का आकार रैंडम तरीके से बदलती है।
- सिमुलेट करती है।
- Flashbots के ज़रिए भेजती है।
6. सौदा कब होता है? सौदा केवल तब होता है जब:
- कीमत ≥ आपके द्वारा निर्धारित थ्रेशोल्ड।
- कीमत बदली हो (मार्केट स्थिर न हो)।
- कूलडाउन पूरा हो गया हो।
- सिमुलेशन सफल रहा हो।
7. परिणाम
कंसोल में:
EXECUTED: 19483921इसका मतलब है:
- एक्सचेंज सफल रहा।
- स्क्रिप्ट का काम पूरा हुआ।
8. महत्वपूर्ण पैरामीटर्स
थ्रेशोल्ड (दूसरा आर्गुमेंट)
node app.js 0.1 220अधिक थ्रेशोल्ड =
- कम सौदे।
- बेहतर कीमत।
राशि (Amount)
node app.js 0.05 200कम राशि =
- मार्केट पर कम प्रभाव।
- कम जोखिम।
9. क्या समझना ज़रूरी है
- यह हमेशा सबसे अच्छी कीमत की गारंटी नहीं देता।
- यह सभी हमलों से सुरक्षा नहीं देता।
- यह आपके "शिकार" बनने की संभावना को काफी कम कर देता है।
10. कब उपयोग न करें
- अगर आप स्लिपेज (slippage) नहीं समझते।
- अगर पर्याप्त बैलेंस नहीं है।
- अगर नेटवर्क बहुत ज़्यादा व्यस्त है।
निष्कर्ष
- लॉन्च — सिर्फ़ 1 कमांड।
- ऑटोमैटिक काम करता है।
- Flashbots के ज़रिए "शांत" स्वैप करता है।
यह कोड:
- प्रोफेशनल MEV बॉट्स को नहीं हराएगा।
- हर स्थिति में सुरक्षा नहीं देगा।
- कोई जादुई फ़ायदा (edge) नहीं देता।
परन्तु:
👉 अब आप "आसान शिकार" नहीं रहेंगे।
यह टूल तो बस शुरुआत है। इसे आर्बिट्राज, लिक्विडेशन या बड़ी मात्रा में लिक्विडिटी को सुरक्षित रूप से मूव करने के लिए और बेहतर बनाया जा सकता है।
मुख्य बात याद रखें: ब्लॉकचेन के इस "घने जंगल" में वह नहीं बचता जो सबसे ज़ोर से चिल्लाता है, बल्कि वह बचता है जो बिना शोर किए चलना जानता है।
यह सामग्री EXMON Academy के लिए तैयार की गई है। मेननेट (Mainnet) में सावधानी से प्रयोग करें और हमेशा स्लिपेज चेक करें!