Commit before cuna

This commit is contained in:
2025-09-04 02:48:34 +02:00
parent 7e55515063
commit 8ef7f0b9f1
32 changed files with 4668 additions and 17 deletions

View File

@@ -0,0 +1,400 @@
#!/usr/bin/env python3
"""
PacaBotManager Python Client using web3.py
============================================
This script provides a Python interface to interact with the PacaBotManager contract
deployed on BSC mainnet using web3.py.
Requirements:
- pip install web3 python-dotenv
Usage:
- Set your private key in .env file: PRIVATE_KEY=your_private_key_here
- Update the contract addresses if needed
- Run the script to see available functions
"""
import os
import sys
from web3 import Web3
from eth_account import Account
from dotenv import load_dotenv
import json
from web3.middleware import ExtraDataToPOAMiddleware
# Load environment variables
load_dotenv()
class PacaBotManagerClient:
def __init__(self):
# BSC Mainnet RPC
self.rpc_url = "https://bsc-dataseed1.binance.org"
self.w3 = Web3(Web3.HTTPProvider(self.rpc_url))
self.w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
# Contract addresses
self.bot_manager_address = "0x4E5d3cD7743934b61041ba2ac3E9df39a0A26dcC"
self.paca_bsc_address = "0x3fF44D639a4982A4436f6d737430141aBE68b4E1"
# Load private key
self.private_key = os.getenv('PRIVATE_KEY')
if not self.private_key:
print("❌ Error: PRIVATE_KEY not found in environment variables")
print("Please add PRIVATE_KEY=your_private_key_here to your .env file")
sys.exit(1)
# Set up account
self.account = Account.from_key(self.private_key)
print(f"🔑 Using account: {self.account.address}")
print(f"💰 Balance: {self.w3.from_wei(self.w3.eth.get_balance(self.account.address), 'ether')} BNB")
# Contract ABIs
self.bot_manager_abi = [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": False,
"inputs": [
{"indexed": True, "internalType": "address", "name": "target", "type": "address"},
{"indexed": True, "internalType": "bytes4", "name": "selector", "type": "bytes4"},
{"indexed": False, "internalType": "bool", "name": "success", "type": "bool"}
],
"name": "CallExecuted",
"type": "event"
},
{
"anonymous": False,
"inputs": [
{"indexed": True, "internalType": "address", "name": "previousOwner", "type": "address"},
{"indexed": True, "internalType": "address", "name": "newOwner", "type": "address"}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"inputs": [
{"internalType": "address", "name": "pacaContract", "type": "address"},
{"internalType": "address", "name": "user", "type": "address"}
],
"name": "clearStakes",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{"internalType": "address", "name": "pacaContract", "type": "address"},
{"internalType": "address", "name": "user", "type": "address"}
],
"name": "clearVesting",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"components": [
{"internalType": "address", "name": "target", "type": "address"},
{"internalType": "bytes", "name": "callData", "type": "bytes"}
],
"internalType": "struct PacaBotManager.Call[]",
"name": "calls",
"type": "tuple[]"
}
],
"name": "multiCallAtomic",
"outputs": [
{"internalType": "bytes[]", "name": "returnData", "type": "bytes[]"}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{"internalType": "address", "name": "", "type": "address"}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{"internalType": "address", "name": "newOwner", "type": "address"}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
# PACA ABI with correct Stake struct
self.paca_abi = [
{
"inputs": [
{"internalType": "address", "name": "user", "type": "address"}
],
"name": "getStakes",
"outputs": [
{
"components": [
{"internalType": "uint256", "name": "amount", "type": "uint256"},
{"internalType": "uint256", "name": "lastClaimed", "type": "uint256"},
{"internalType": "uint256", "name": "dailyRewardRate", "type": "uint256"},
{"internalType": "uint256", "name": "unlockTime", "type": "uint256"},
{"internalType": "bool", "name": "complete", "type": "bool"}
],
"internalType": "struct PacaFinanceWithBoostAndScheduleBsc.Stake[]",
"name": "",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{"internalType": "address", "name": "", "type": "address"}
],
"stateMutability": "view",
"type": "function"
}
]
# Create contract instances
self.bot_manager = self.w3.eth.contract(
address=self.bot_manager_address,
abi=self.bot_manager_abi
)
self.paca_contract = self.w3.eth.contract(
address=self.paca_bsc_address,
abi=self.paca_abi
)
print(f"🤖 PacaBotManager: {self.bot_manager_address}")
print(f"🔗 PACA Contract: {self.paca_bsc_address}")
print(f"🌐 Network: BSC Mainnet")
print()
def get_gas_price(self):
"""Get current gas price with small buffer"""
base_gas = self.w3.eth.gas_price
return int(base_gas * 1.1) # 10% buffer
def send_transaction(self, tx_dict):
"""Send a transaction and wait for confirmation"""
# Add gas and nonce
tx_dict['gas'] = 500000 # Conservative gas limit
gas_price = self.get_gas_price()
tx_dict['maxFeePerGas'] = gas_price
tx_dict['maxPriorityFeePerGas'] = gas_price # 10% of max fee as priority
tx_dict['nonce'] = self.w3.eth.get_transaction_count(self.account.address)
tx_dict['type'] = 2 # EIP-1559 transaction
print(f"⛽ Max Fee Per Gas: {self.w3.from_wei(gas_price, 'gwei')} gwei")
# Sign and send
signed = self.w3.eth.account.sign_transaction(tx_dict, self.private_key)
tx_hash = self.w3.eth.send_raw_transaction(signed.raw_transaction)
print(f"🧾 Transaction sent: {tx_hash.hex()}")
print("⏳ Waiting for confirmation...")
# Wait for confirmation
receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
if receipt.status == 1:
print("✅ Transaction successful!")
else:
print("❌ Transaction failed!")
print(f"⛽ Gas used: {receipt.gasUsed}")
return receipt
def clear_stakes(self, user_address):
"""Clear all stakes for a user"""
print(f"🔥 Clearing stakes for user: {user_address}")
tx_dict = self.bot_manager.functions.clearStakes(
self.paca_bsc_address,
user_address
).build_transaction({
'from': self.account.address,
})
return self.send_transaction(tx_dict)
def clear_vesting(self, user_address):
"""Clear all vestings for a user"""
print(f"🔮 Clearing vestings for user: {user_address}")
tx_dict = self.bot_manager.functions.clearVesting(
self.paca_bsc_address,
user_address
).build_transaction({
'from': self.account.address,
})
return self.send_transaction(tx_dict)
def multi_call_atomic(self, calls):
"""Execute multiple calls atomically"""
print(f"🔄 Executing {len(calls)} calls atomically...")
tx_dict = self.bot_manager.functions.multiCallAtomic(calls).build_transaction({
'from': self.account.address,
})
return self.send_transaction(tx_dict)
def clear_both_stakes_and_vesting(self, user_address):
"""Clear both stakes and vesting for a user in one atomic transaction"""
print(f"🔥🔮 Clearing BOTH stakes AND vesting for user: {user_address}")
print("⚠️ WARNING: This affects both stakes and vesting!")
# Prepare both calls
calls = [
{
'target': self.paca_bsc_address,
'callData': self.w3.keccak(text="clearStakes(address)")[:4] +
self.w3.eth.codec.encode(['address'], [user_address])
},
{
'target': self.paca_bsc_address,
'callData': self.w3.keccak(text="clearVesting(address)")[:4] +
self.w3.eth.codec.encode(['address'], [user_address])
}
]
return self.multi_call_atomic(calls)
def get_owner(self):
"""Get the owner of the bot manager contract"""
owner = self.bot_manager.functions.owner().call()
print(f"👤 Bot Manager Owner: {owner}")
return owner
def get_stakes(self, user_address):
"""Get stakes for a user from PACA contract"""
print(f"📊 Getting stakes for user: {user_address}")
try:
stakes = self.paca_contract.functions.getStakes(user_address).call()
print(f"📈 User has {len(stakes)} stakes:")
total_amount = 0
active_stakes = 0
for i, stake in enumerate(stakes):
amount = stake[0] # amount
last_claimed = stake[1] # lastClaimed
daily_reward_rate = stake[2] # dailyRewardRate
unlock_time = stake[3] # unlockTime
complete = stake[4] # complete
is_active = not complete and amount > 0
if is_active:
active_stakes += 1
total_amount += amount
print(f" 📌 Stake {i + 1}:")
print(f" Amount: {self.w3.from_wei(amount, 'ether')} ETH")
print(f" Daily Reward Rate: {self.w3.from_wei(daily_reward_rate, 'ether')} ETH")
print(f" Complete: {complete}")
print(f" Status: {'🟢 ACTIVE' if is_active else '🔴 COMPLETED'}")
if last_claimed > 0:
import datetime
last_claimed_date = datetime.datetime.fromtimestamp(last_claimed)
print(f" Last Claimed: {last_claimed_date}")
if unlock_time > 0:
import datetime
unlock_date = datetime.datetime.fromtimestamp(unlock_time)
print(f" Unlock Time: {unlock_date}")
print()
print(f"💎 Summary:")
print(f" Total Stakes: {len(stakes)}")
print(f" Active Stakes: {active_stakes}")
print(f" Total Active Amount: {self.w3.from_wei(total_amount, 'ether')} ETH")
return stakes
except Exception as e:
print(f"❌ Error getting stakes: {e}")
return []
def get_paca_owner(self):
"""Get the owner of the PACA contract"""
try:
owner = self.paca_contract.functions.owner().call()
print(f"👤 PACA Contract Owner: {owner}")
return owner
except Exception as e:
print(f"❌ Error getting PACA owner: {e}")
return None
def main():
print("🐍 PacaBotManager Python Client")
print("=" * 40)
try:
client = PacaBotManagerClient()
# Show available commands
print("📋 Available Commands:")
print("1. Get Bot Manager Owner")
print("2. Get PACA Contract Owner")
print("3. Get Stakes for User")
print("4. Clear Stakes for User")
print("5. Clear Vesting for User")
print("6. Clear BOTH Stakes and Vesting (Atomic)")
print()
# Example usage - uncomment to test specific functions
# 1. Get owners
client.get_owner()
client.get_paca_owner()
print()
# 2. Get stakes for the test user
test_user = "0x41970Ce76b656030A79E7C1FA76FC4EB93980255"
# client.get_stakes(test_user)
# 3. Uncomment to clear stakes ONLY (BE CAREFUL - this affects real funds!)
# print("⚠️ WARNING: This will clear real stakes!")
# client.clear_stakes(test_user)
# 4. Uncomment to clear vesting ONLY (BE CAREFUL - this affects real funds!)
print("⚠️ WARNING: This will clear real vesting!")
client.clear_vesting(test_user)
# 5. Example: Clear BOTH stakes and vesting in one atomic transaction
# print("⚠️ WARNING: This will clear both stakes AND vesting atomically!")
# client.clear_both_stakes_and_vesting(test_user)
except Exception as e:
print(f"💥 Error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()