@@ -96,7 +96,6 @@ function decryptWithAnyKey(encrypted) {
9696// === CONFIG ===
9797// List of public RPCs for Celo.
9898const 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 ---
157175const personaFile = "personas.json" ;
158176let walletProfiles = { } ;
@@ -194,6 +212,7 @@ async function savePersonas() {
194212
195213function 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
365385function 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