Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ cd scroll

pip install -r requirements.txt

~/scroll$ python run_swaps.py --wallets WALLET_KEY1 WALLET_KEY2 WALLET_KEYN
~/scroll$ python run_swaps.py --wallet_file json file that contains keys
```
---
<h2>🚨 Features</h2>
Expand Down
37 changes: 37 additions & 0 deletions README_refactor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## Description

This pull request introduces significant enhancements to the existing functionality, enabling automated trades across multiple websites using a single Python command. The key features include:

Unified Command: Users can now execute automated trades across multiple websites with a single Python command.

Support for Multiple Wallets: The system now accepts one or multiple wallet private keys for performing swaps, offering enhanced flexibility to users.

Dynamic Randomization Schedule: Trades are executed using a dynamically randomizing schedule, contributing to improved security and efficiency.

Configurability: Command-line arguments have been exposed to facilitate easy configuration, allowing users to customize randomization schedules, swap amounts, and tokens.

Cycle Functionality: The system automatically cycles between swapping from ETH to USDC and back, optimizing trading processes.

## Changes Made
Implemented run_swaps.py to enable executing automated trades across multiple websites.

Added support for accepting one or multiple wallet private keys for performing swaps.

Integrated dynamic randomization schedule for executing trades and recycling wallets.

Exposed command-line arguments for configuring randomization schedules, swap amounts, and tokens.

Implemented automatic cycling between swapping from ETH to USDC and back for optimized trading.

## Usage
python run_swaps.py --wallets "WALLET_KEY1 WALLET_KEY2 ... WALLET_KEYN"
or
python run_swaps.py --wallet_file <file_name.json>

## Testing
Manual testing has been conducted to validate the behavior across different machines all using one wallet.

## Additional Notes
Documentation has been updated to reflect the changes and provide guidance on usage.

All new code adheres to best practices.
48 changes: 25 additions & 23 deletions domain/config.py
Original file line number Diff line number Diff line change
@@ -1,72 +1,74 @@
import json
import os
base_dir = os.path.dirname(os.path.abspath(__file__))

with open('domain/data/rpc.json') as file:
with open(os.path.join(base_dir, 'data/rpc.json')) as file:
RPC = json.load(file)

with open('domain/data/abi/erc20_abi.json') as file:
with open(os.path.join(base_dir, 'data/abi/erc20_abi.json')) as file:
ERC20_ABI = json.load(file)

with open('domain/data/abi/bridge/deposit.json') as file:
with open(os.path.join(base_dir, 'data/abi/bridge/deposit.json')) as file:
DEPOSIT_ABI = json.load(file)

with open('domain/data/abi/bridge/withdraw.json') as file:
with open(os.path.join(base_dir, 'data/abi/bridge/withdraw.json')) as file:
WITHDRAW_ABI = json.load(file)

with open('domain/data/abi/bridge/oracle.json') as file:
with open(os.path.join(base_dir, 'data/abi/bridge/oracle.json')) as file:
ORACLE_ABI = json.load(file)

with open('domain/data/abi/scroll/weth.json') as file:
with open(os.path.join(base_dir, 'data/abi/scroll/weth.json')) as file:
WETH_ABI = json.load(file)

with open("domain/data/abi/syncswap/router.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/syncswap/router.json'), "r") as file:
SYNCSWAP_ROUTER_ABI = json.load(file)

with open('domain/data/abi/syncswap/classic_pool.json') as file:
with open(os.path.join(base_dir, 'data/abi/syncswap/classic_pool.json')) as file:
SYNCSWAP_CLASSIC_POOL_ABI = json.load(file)

with open('domain/data/abi/syncswap/classic_pool_data.json') as file:
with open(os.path.join(base_dir, 'data/abi/syncswap/classic_pool_data.json')) as file:
SYNCSWAP_CLASSIC_POOL_DATA_ABI = json.load(file)

with open("domain/data/abi/skydrome/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/skydrome/abi.json'), "r") as file:
SKYDROME_ROUTER_ABI = json.load(file)

with open("domain/data/abi/zebra/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/zebra/abi.json'), "r") as file:
ZEBRA_ROUTER_ABI = json.load(file)

with open("domain/data/abi/aave/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/aave/abi.json'), "r") as file:
AAVE_ABI = json.load(file)

with open("domain/data/abi/layerbank/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/layerbank/abi.json'), "r") as file:
LAYERBANK_ABI = json.load(file)

with open("domain/data/abi/zerius/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/zerius/abi.json'), "r") as file:
ZERIUS_ABI = json.load(file)

with open("domain/data/abi/l2pass/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/l2pass/abi.json'), "r") as file:
L2PASS_ABI = json.load(file)

with open("domain/data/abi/dmail/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/dmail/abi.json'), "r") as file:
DMAIL_ABI = json.load(file)

with open("domain/data/abi/omnisea/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/omnisea/abi.json'), "r") as file:
OMNISEA_ABI = json.load(file)

with open("domain/data/abi/nft2me/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/nft2me/abi.json'), "r") as file:
NFTS2ME_ABI = json.load(file)

with open("domain/data/abi/gnosis/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/gnosis/abi.json'), "r") as file:
SAFE_ABI = json.load(file)

with open("domain/data/deploy/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/deploy/abi.json'), "r") as file:
DEPLOYER_ABI = json.load(file)

with open("domain/data/deploy/bytecode.txt", "r") as file:
with open(os.path.join(base_dir, 'data/deploy/bytecode.txt'), "r") as file:
DEPLOYER_BYTECODE = file.read()

with open("domain/data/abi/zkstars/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/zkstars/abi.json'), "r") as file:
ZKSTARS_ABI = json.load(file)

with open("domain/data/abi/rubyscore/abi.json", "r") as file:
with open(os.path.join(base_dir, 'data/abi/rubyscore/abi.json'), "r") as file:
RUBYSCORE_VOTE_ABI = json.load(file)

ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
Expand Down
138 changes: 105 additions & 33 deletions domain/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
import time
from typing import Union
import asyncio

from eth_account import Account as EthereumAccount
from loguru import logger

from .modules_settings import handle_app_expiration
from .settings import managingEnvironment

async def run_module(module, wallet_number, key, recipient: Union[str, None] = None, settings: dict = {}):
try:
await module(
wallet_number,
key,
recipient,
wallet_number,
key,
recipient,
from_token=settings.get('from_token'),
to_token=settings.get('to_token'),
min_amount=settings.get('min_amount'),
Expand All @@ -30,51 +31,122 @@ def _async_run_module(module, wallet_number, key, recipient, settings):
asyncio.run(run_module(module, wallet_number, key, recipient, settings))



def main(
websites,
wallets,
website_settings,
website_settings,
wait_between_wallets_max=30,
wait_between_wallets_min=20,
wait_between_websites_max=20,
wait_between_websites_min=5,
wait_between_cycles_max=((12*60*60)+90),
wait_between_cycles_min=((12*60*60)+5),
wait_between_cycles_min=((12*60*60)+5),
):


is_expired = handle_app_expiration()
if is_expired:
return



while True:

logger.info(f"Selected wallets: {len(wallets)}")
# iterate through the wallets
for _, wallet_key in enumerate(wallets, start=1):
# website transactions to perform at each website
# iterate through websites
for tuple in zip(websites, website_settings):
logger.info(f"Running module {tuple[0].__name__} with wallet {wallet_key}")
_async_run_module(
tuple[0],
_,
wallet_key,
None,
tuple[1]
)


wallet_address = EthereumAccount.from_key(wallet_key).address
logger.info(f"Running module {websites[0].__name__}")
logger.info(f"With wallet {wallet_address[:6]}...{wallet_address[-6:]}")

_async_run_module(
websites[0],
_,
wallet_key,
None,
website_settings[0]
)

env = managingEnvironment["python_running_env"]
# random wait to swap back
random_wait = random.randint(managingEnvironment[env]["waitTimeBetweenSwapBack"]["from"], managingEnvironment[env]["waitTimeBetweenSwapBack"]["to"])
minutes = int((random_wait % managingEnvironment['totalSecond']) // managingEnvironment['totalMinutes'])

logger.info(f"Randomly wait between switching from {website_settings[0]['from_token']} to {website_settings[0]['to_token']} for {minutes} minutes")
time.sleep(random_wait)
website_settings[0]['from_token'], website_settings[0]['to_token'] = website_settings[0]['to_token'], website_settings[0]['from_token']

# After Switching running the module again
# logger.info(f"Running module {websites[0].__name__} with wallet {wallet_key}")
_async_run_module(
websites[0],
_,
wallet_key,
None,
website_settings[0]
)

# Switch the token back to original for next wallet
website_settings[0]['from_token'], website_settings[0]['to_token'] = website_settings[0]['to_token'], website_settings[0]['from_token']

#----- for multiple website we comment this for now ------
# iterate through websites
# for tuple in zip(websites, website_settings):
# logger.info(f"Running module {tuple[0].__name__} with wallet {wallet_key}")
# _async_run_module(
# tuple[0],
# _,
# wallet_key,
# None,
# tuple[1]
# )


# wait between website actions
random_wait = random.randint(wait_between_websites_min, wait_between_websites_max)
logger.info(f"Waiting between websites for {random_wait} seconds")
time.sleep(random_wait)

# random_wait = random.randint(wait_between_websites_min, wait_between_websites_max)
# logger.info(f"Waiting between websites for {random_wait/3600} hours")
# time.sleep(random_wait)

#---------- multiple website comment end ----------

# wait between wallets
random_wait = random.randint(wait_between_wallets_min, wait_between_wallets_max)
logger.info(f"Waiting between wallets for {random_wait} seconds")
time.sleep(random_wait)
if len(wallets) > 1:
random_wait = random.randint(wait_between_wallets_min, wait_between_wallets_max)
hours = int(random_wait // managingEnvironment['totalSecond'])
minutes = int((random_wait % managingEnvironment['totalSecond']) // managingEnvironment['totalMinutes'])

if hours == 0:
logger.info(f"Waiting between wallets for {minutes} minutes.")
else:
logger.info(f"Waiting between wallets for {hours} hours and {minutes} minutes.")
time.sleep(random_wait)

# wait between cycles
random_wait = random.randint(wait_between_cycles_min, wait_between_cycles_max)
logger.info(f"Waiting between cycles for {random_wait} seconds")
time.sleep(random_wait)

hours = int(random_wait // managingEnvironment['totalSecond'])
minutes = int((random_wait % managingEnvironment['totalSecond']) // managingEnvironment['totalMinutes'])
if hours == 0:
logger.info(f"Waiting between cycles for {minutes} minutes.")
else:
logger.info(f"Waiting between cycles for {hours} hours and {minutes} minutes.")

while random_wait >= 3600: # If the wait time is more than equal to 1 hour
hours_remaining = int(random_wait // 3600)
if hours_remaining >= 1: # Log time every hour
logger.info(f"{hours_remaining} hours left until next swap")
# Sleep for 1 hour
time.sleep(3600)
# Decrease the remaining time by 1 hour
random_wait -= 3600

# change all the settings
logger.info(f"Switching from_token and to_token")
for setting in website_settings:
# ETH to USDC or back
setting['from_token'], setting['to_token'] = setting['to_token'], setting['from_token']

# for setting in website_settings:
# # ETH to USDC or back
# setting['from_token'], setting['to_token'] = setting['to_token'], setting['from_token']




7 changes: 5 additions & 2 deletions domain/modules/aave.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,11 @@ async def withdraw(self) -> None:
f"[{self.account_id}][{self.address}] Make withdraw from Aave | " +
f"{self.w3.from_wei(amount, 'ether')} ETH"
)

await self.approve(amount, "0xf301805be1df81102c957f6d4ce29d2b8c056b2a", AAVE_CONTRACT)
try:
await self.approve(amount, "0xf301805be1df81102c957f6d4ce29d2b8c056b2a", AAVE_CONTRACT)
except Exception as e:
logger.error(f"Output while dealing with func:self.approve() under withdraw function in aave file{e} ")
await self.approve(amount, "0xf301805be1df81102c957f6d4ce29d2b8c056b2a", AAVE_CONTRACT)

tx_data = await self.get_tx_data()

Expand Down
Loading