Skip to content

Commit ece0e9d

Browse files
authored
generateDeviceAgent function and integrated it into the persona system
The code is now more advanced with the simulated device agents and network latency. The persona system now controls not just the transaction behavior but also the network characteristics of each wallet.
1 parent 718210a commit ece0e9d

File tree

1 file changed

+37
-10
lines changed

1 file changed

+37
-10
lines changed

index.js

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ function decryptWithAnyKey(encrypted) {
9696
// === CONFIG ===
9797
// List of public RPCs for Celo.
9898
const RPCS = [
99-
"https://celo-mainnet.infura.io/v3/f0c6b3797dd54dc2aa91cd4a463bcc57",
10099
"https://rpc.ankr.com/celo",
101100
"https://celo.drpc.org",
102101
"https://forno.celo.org",
@@ -153,6 +152,25 @@ async function loadKeysInline() {
153152
console.log(chalk.cyan(`🔐 Loaded ${ALL_WALLETS.length} wallets (encrypted in memory)`));
154153
}
155154

155+
// === NEW: Device Agent Generation ===
156+
function generateDeviceAgent() {
157+
const browsers = ["Chrome", "Firefox", "Edge", "Safari"];
158+
const os = ["Windows NT 10.0", "Macintosh; Intel Mac OS X 13_0", "Linux x86_64"];
159+
160+
const browser = browsers[Math.floor(Math.random() * browsers.length)];
161+
const system = os[Math.floor(Math.random() * os.length)];
162+
const version = `${Math.floor(Math.random() * 100)}.0.${Math.floor(Math.random() * 1000)}`;
163+
164+
// Simulated network latency per wallet (in ms)
165+
const latency = 50 + Math.floor(Math.random() * 200); // 50ms to 250ms
166+
167+
return {
168+
userAgent: `${browser}/${version} (${system})`,
169+
latency
170+
};
171+
}
172+
173+
156174
// --- Wallet Persona Management ---
157175
const personaFile = "personas.json";
158176
let walletProfiles = {};
@@ -194,6 +212,7 @@ async function savePersonas() {
194212

195213
function ensurePersona(wallet) {
196214
if (!walletProfiles[wallet.address]) {
215+
const deviceAgent = generateDeviceAgent();
197216
walletProfiles[wallet.address] = {
198217
idleBias: Math.random() * 0.25,
199218
pingBias: Math.random() * 0.25,
@@ -207,7 +226,8 @@ function ensurePersona(wallet) {
207226
maxNonce: 520 + Math.floor(Math.random() * 80),
208227
// failure tracking
209228
failCount: 0,
210-
lastFailAt: null
229+
lastFailAt: null,
230+
deviceAgent // store User-Agent + latency
211231
};
212232
savePersonas();
213233
}
@@ -333,7 +353,7 @@ function getProvider(rpcUrl, agent) {
333353
* Attempts to connect to an RPC endpoint.
334354
* @returns {Promise<{provider: ethers.JsonRpcProvider, url: string}|null>} The working provider and its URL, or null if all fail.
335355
*/
336-
async function tryProviders() {
356+
async function tryProviders(profile) {
337357
console.log(chalk.hex("#00FFFF").bold("🔍 Searching for a working RPC endpoint..."));
338358
for (const url of RPCS) {
339359
try {
@@ -358,8 +378,8 @@ async function tryProviders() {
358378
* Iterates through the list of RPCs and returns the first one that successfully connects.
359379
* @returns {Promise<{provider: ethers.JsonRpcProvider, url: string}>} The working provider and its URL.
360380
*/
361-
async function getWorkingProvider() {
362-
return await tryProviders();
381+
async function getWorkingProvider(profile) {
382+
return await tryProviders(profile);
363383
}
364384

365385
function randomDelay(minSec, maxSec) {
@@ -398,6 +418,10 @@ async function sendTx(wallet, provider, profile, url) {
398418
return;
399419
}
400420

421+
// === NEW: Simulate Network Latency ===
422+
console.log(chalk.hex("#FFA500").bold(`🌐 Simulating network latency: ${profile.deviceAgent.latency}ms...`));
423+
await new Promise(res => setTimeout(res, profile.deviceAgent.latency));
424+
401425
const balance = await provider.getBalance(wallet.address);
402426
await randomDelay(2, 4);
403427

@@ -546,6 +570,11 @@ async function main() {
546570
await initLogFile();
547571

548572
while (true) {
573+
// Pick a wallet and its persona
574+
let key = pickRandomKey();
575+
let wallet = new ethers.Wallet(key);
576+
const profile = ensurePersona(wallet);
577+
549578
// === NEW LOGIC: Check if all wallets are inactive and sleep if so ===
550579
if (inactiveWallets.size >= ALL_WALLETS.length) {
551580
console.log(chalk.yellow("😴 All wallets are currently inactive. Sleeping for 5 minutes..."));
@@ -557,7 +586,7 @@ async function main() {
557586
let provider = null;
558587
let url = null;
559588
while (!provider) {
560-
const providerResult = await getWorkingProvider();
589+
const providerResult = await getWorkingProvider(profile);
561590
if (providerResult) {
562591
provider = providerResult.provider;
563592
url = providerResult.url;
@@ -568,10 +597,8 @@ async function main() {
568597
}
569598
// === END NEW LOGIC ===
570599

571-
// Get the decrypted private key and create a new wallet instance for the transaction
572-
let key = pickRandomKey();
573-
let wallet = new ethers.Wallet(key, provider);
574-
const profile = ensurePersona(wallet);
600+
// Re-attach wallet to the working provider
601+
wallet = new ethers.Wallet(key, provider);
575602

576603
// === NEW: Main loop modification ===
577604
if (!checkActive(wallet, profile)) {

0 commit comments

Comments
 (0)