Skip to content

Commit

Permalink
Merge pull request #196 from UnitapApp/feature/move-web3-functionalit…
Browse files Browse the repository at this point in the history
…y-from-EVMManager-to-Web3Utils

Move web3 functionalities from EvmFundManager to Web3Utils
  • Loading branch information
PooyaFekri authored Nov 23, 2023
2 parents 4bfba9c + 876ebbc commit ca0570d
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 72 deletions.
25 changes: 21 additions & 4 deletions core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,12 @@ def contract(self) -> Type[Contract]:
def set_contract(self, address, abi):
self._contract = self.w3.eth.contract(address=address, abi=abi)

def contract_txn(self, func: Type[ContractFunction]):
signed_tx = self.build_contract_txn(func)
def get_contract_function(self, func_name: str):
func = getattr(self.contract.functions, func_name)
return func

def contract_txn(self, func: Type[ContractFunction], **kwargs):
signed_tx = self.build_contract_txn(func, **kwargs)
txn_hash = self.send_raw_tx(signed_tx)
return txn_hash.hex()

Expand All @@ -107,9 +111,12 @@ def contract_call(self, func: Type[ContractFunction], from_address=None):
return func.call({"from": from_address})
return func.call()

def build_contract_txn(self, func: Type[ContractFunction]):
def get_gas_estimate(self, func: Type[ContractFunction]):
return func.estimate_gas({"from": self.account.address})

def build_contract_txn(self, func: Type[ContractFunction], **kwargs):
nonce = self.w3.eth.get_transaction_count(self.account.address)
tx_data = func.build_transaction({"from": self.account.address, "nonce": nonce})
tx_data = func.build_transaction({"from": self.account.address, "nonce": nonce, **kwargs})
return self.sign_tx(tx_data)

def sign_tx(self, tx_data: TxParams):
Expand All @@ -127,5 +134,15 @@ def current_block(self):
def get_transaction_by_hash(self, hash):
return self.w3.eth.get_transaction(hash)

def get_gas_price(self):
return self.w3.eth.gas_price

def from_wei(self, value: int, unit: str = "ether"):
return self.w3.from_wei(value, unit)

@staticmethod
def to_checksum_address(address: str):
return Web3.to_checksum_address(address.lower())

def get_transaction_receipt(self, hash):
return self.w3.eth.get_transaction_receipt(hash)
89 changes: 25 additions & 64 deletions faucet/faucet_manager/fund_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@
from solders.pubkey import Pubkey
from solders.signature import Signature
from solders.transaction_status import TransactionConfirmationStatus
from web3 import Web3
from web3.gas_strategies.rpc import rpc_gas_price_strategy
from web3.middleware import geth_poa_middleware

from core.utils import Web3Utils
from faucet.constants import MEMCACHE_LIGHTNING_LOCK_KEY
from faucet.faucet_manager.fund_manager_abi import manager_abi
from faucet.helpers import memcache_lock
Expand All @@ -37,105 +35,68 @@ class RPCError(Exception):
class EVMFundManager:
def __init__(self, chain: Chain):
self.chain = chain
self.abi = manager_abi

@property
def w3(self) -> Web3:
assert self.chain.rpc_url_private is not None
try:
_w3 = Web3(Web3.HTTPProvider(self.chain.rpc_url_private))
if self.chain.poa:
_w3.middleware_onion.inject(geth_poa_middleware, layer=0)
if _w3.is_connected():
_w3.eth.set_gas_price_strategy(rpc_gas_price_strategy)
return _w3
except Exception as e:
logging.error(e)
raise FundMangerException.RPCError(f"Could not connect to rpc {self.chain.rpc_url_private}")
self.web3_utils = Web3Utils(self.chain.rpc_url_private)
self.web3_utils.set_account(self.chain.wallet.main_key)
self.web3_utils.set_contract(self.get_fund_manager_checksum_address(), abi=manager_abi)

@property
def is_gas_price_too_high(self):
try:
gas_price = self.w3.eth.gas_price
print(f"Gas price: {gas_price} vs max: {self.chain.max_gas_price}")
gas_price = self.web3_utils.get_gas_price()
logging.info(f"Gas price: {gas_price} vs max: {self.chain.max_gas_price}")
if gas_price > self.chain.max_gas_price:
return True
return False
except Exception as e:
logging.error(e)
return True

@property
def account(self) -> LocalAccount:
return self.w3.eth.account.from_key(self.chain.wallet.main_key)

@staticmethod
def to_checksum_address(address: str):
return Web3.to_checksum_address(address.lower())

def get_fund_manager_checksum_address(self):
return self.to_checksum_address(self.chain.fund_manager_address)

@property
def contract(self):
return self.w3.eth.contract(address=self.get_fund_manager_checksum_address(), abi=self.abi)
return self.web3_utils.to_checksum_address(self.chain.fund_manager_address)

def transfer(self, bright_user: BrightUser, amount: int):
tx = self.single_eth_transfer_signed_tx(amount, bright_user.address)
try:
self.w3.eth.send_raw_transaction(tx.rawTransaction)
return tx["hash"].hex()
except Exception as e:
raise FundMangerException.RPCError(str(e))
return self._transfer("withdrawEth", amount, bright_user.address)

def multi_transfer(self, data):
tx = self.multi_eth_transfer_signed_tx(data)
return self._transfer("multiWithdrawEth", data)

def _transfer(self, tx_function_str, *args):
tx = self.prepare_tx_for_broadcast(tx_function_str, *args)
try:
self.w3.eth.send_raw_transaction(tx.rawTransaction)
self.web3_utils.send_raw_tx(tx.rawTransaction)
return tx["hash"].hex()
except Exception as e:
raise FundMangerException.RPCError(str(e))

def single_eth_transfer_signed_tx(self, amount: int, to: str):
tx_function = self.contract.functions.withdrawEth(amount, to)
return self.prepare_tx_for_broadcast(tx_function)

def multi_eth_transfer_signed_tx(self, data):
tx_function = self.contract.functions.multiWithdrawEth(data)
return self.prepare_tx_for_broadcast(tx_function)

def prepare_tx_for_broadcast(self, tx_function):
nonce = self.w3.eth.get_transaction_count(self.account.address)
gas_estimation = tx_function.estimate_gas({"from": self.account.address})
def prepare_tx_for_broadcast(self, tx_function_str, *args):
tx_function = self.web3_utils.get_contract_function(tx_function_str)(*args)
gas_estimation = self.web3_utils.get_gas_estimate(tx_function)
if self.chain.chain_id == "997":
gas_estimation = 100000

if self.is_gas_price_too_high:
raise FundMangerException.GasPriceTooHigh("Gas price is too high")

tx_data = tx_function.build_transaction(
{
"nonce": nonce,
"from": self.account.address,
"gas": gas_estimation,
"gasPrice": int(self.w3.eth.gas_price * self.chain.gas_multiplier),
}
)
signed_tx = self.w3.eth.account.sign_transaction(tx_data, self.account.key)
tx_params = {
"gas": gas_estimation,
"gasPrice": int(self.web3_utils.get_gas_price() * self.chain.gas_multiplier),
}

signed_tx = self.web3_utils.build_contract_txn(tx_function, **tx_params)
return signed_tx

def is_tx_verified(self, tx_hash):
receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
receipt = self.web3_utils.wait_for_transaction_receipt(tx_hash)
if receipt["status"] == 1:
return True
return False

def get_tx(self, tx_hash):
tx = self.w3.eth.get_transaction(tx_hash)
tx = self.web3_utils.get_transaction_by_hash(tx_hash)
return tx

def from_wei(self, value: int, unit: str = "ether"):
return self.w3.from_wei(value, unit)
return self.web3_utils.from_wei(value, unit)


class SolanaFundManager:
Expand Down
6 changes: 2 additions & 4 deletions faucet/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from authentication.models import NetworkTypes, Wallet
from core.models import TokenPrice
from core.utils import Web3Utils
from tokenTap.models import TokenDistributionClaim

from .faucet_manager.fund_manager import (
Expand Down Expand Up @@ -382,10 +383,7 @@ def process_donation_receipt(self, donation_receipt_pk):
).values_list("lower_address", flat=True):
donation_receipt.delete()
return
if (
evm_fund_manager.to_checksum_address(tx.get("to"))
!= evm_fund_manager.get_fund_manager_checksum_address()
):
if Web3Utils.to_checksum_address(tx.get("to")) != evm_fund_manager.get_fund_manager_checksum_address():
donation_receipt.delete()
return
donation_receipt.value = str(evm_fund_manager.from_wei(tx.get("value")))
Expand Down

0 comments on commit ca0570d

Please sign in to comment.