kopia lustrzana https://github.com/bugout-dev/moonworm
Add web3 v6 support.
rodzic
d47f4eb4c2
commit
538842897c
|
@ -172,7 +172,7 @@ def handle_watch(args: argparse.Namespace) -> None:
|
||||||
watch_contract(
|
watch_contract(
|
||||||
web3=web3,
|
web3=web3,
|
||||||
state_provider=state_provider,
|
state_provider=state_provider,
|
||||||
contract_address=web3.toChecksumAddress(args.contract),
|
contract_address=web3.to_checksum_address(args.contract),
|
||||||
contract_abi=contract_abi,
|
contract_abi=contract_abi,
|
||||||
num_confirmations=args.confirmations,
|
num_confirmations=args.confirmations,
|
||||||
start_block=args.start,
|
start_block=args.start,
|
||||||
|
@ -186,7 +186,7 @@ def handle_watch(args: argparse.Namespace) -> None:
|
||||||
watch_contract(
|
watch_contract(
|
||||||
web3=web3,
|
web3=web3,
|
||||||
state_provider=Web3StateProvider(web3),
|
state_provider=Web3StateProvider(web3),
|
||||||
contract_address=web3.toChecksumAddress(args.contract),
|
contract_address=web3.to_checksum_address(args.contract),
|
||||||
contract_abi=contract_abi,
|
contract_abi=contract_abi,
|
||||||
num_confirmations=args.confirmations,
|
num_confirmations=args.confirmations,
|
||||||
start_block=args.start,
|
start_block=args.start,
|
||||||
|
@ -418,7 +418,7 @@ def generate_argument_parser() -> argparse.ArgumentParser:
|
||||||
find_deployment_parser.add_argument(
|
find_deployment_parser.add_argument(
|
||||||
"-c",
|
"-c",
|
||||||
"--contract",
|
"--contract",
|
||||||
type=Web3.toChecksumAddress,
|
type=Web3.to_checksum_address,
|
||||||
required=True,
|
required=True,
|
||||||
help="Contract address",
|
help="Contract address",
|
||||||
)
|
)
|
||||||
|
|
|
@ -62,7 +62,7 @@ class Web3StateProvider(EthereumStateProvider):
|
||||||
def _get_block(self, block_number: int) -> Dict[str, Any]:
|
def _get_block(self, block_number: int) -> Dict[str, Any]:
|
||||||
if block_number in self.blocks_cache:
|
if block_number in self.blocks_cache:
|
||||||
return self.blocks_cache[block_number]
|
return self.blocks_cache[block_number]
|
||||||
block = self.w3.eth.getBlock(block_number, full_transactions=True)
|
block = self.w3.eth.get_block(block_number, full_transactions=True)
|
||||||
|
|
||||||
# clear cache if it grows too large
|
# clear cache if it grows too large
|
||||||
if len(self.blocks_cache) > 50:
|
if len(self.blocks_cache) > 50:
|
||||||
|
|
|
@ -111,7 +111,7 @@ def utfy_dict(dic):
|
||||||
return dic
|
return dic
|
||||||
|
|
||||||
elif isinstance(dic, bytes):
|
elif isinstance(dic, bytes):
|
||||||
return Web3.toHex(dic)
|
return Web3.to_hex(dic)
|
||||||
|
|
||||||
elif isinstance(dic, tuple):
|
elif isinstance(dic, tuple):
|
||||||
return tuple(utfy_dict(x) for x in dic)
|
return tuple(utfy_dict(x) for x in dic)
|
||||||
|
@ -148,7 +148,7 @@ class FunctionCallCrawler:
|
||||||
self.contract = Web3().eth.contract(abi=self.contract_abi)
|
self.contract = Web3().eth.contract(abi=self.contract_abi)
|
||||||
self.on_decode_error = on_decode_error
|
self.on_decode_error = on_decode_error
|
||||||
self.whitelisted_methods = {
|
self.whitelisted_methods = {
|
||||||
Web3.toHex(function_abi_to_4byte_selector(a)) for a in self.contract_abi
|
Web3.to_hex(function_abi_to_4byte_selector(a)) for a in self.contract_abi
|
||||||
}
|
}
|
||||||
|
|
||||||
def process_transaction(self, transaction: Dict[str, Any]):
|
def process_transaction(self, transaction: Dict[str, Any]):
|
||||||
|
|
|
@ -3,7 +3,8 @@ import datetime
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple
|
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union
|
||||||
|
import traceback
|
||||||
|
|
||||||
from eth_abi.codec import ABICodec
|
from eth_abi.codec import ABICodec
|
||||||
from eth_typing.evm import ChecksumAddress
|
from eth_typing.evm import ChecksumAddress
|
||||||
|
@ -113,7 +114,7 @@ def _fetch_events_chunk(
|
||||||
raw_event = get_event_data(codec, event_abi, log)
|
raw_event = get_event_data(codec, event_abi, log)
|
||||||
event = {
|
event = {
|
||||||
"event": raw_event["event"],
|
"event": raw_event["event"],
|
||||||
"args": json.loads(Web3.toJSON(utfy_dict(dict(raw_event["args"])))),
|
"args": json.loads(Web3.to_json(utfy_dict(dict(raw_event["args"])))),
|
||||||
"address": raw_event["address"],
|
"address": raw_event["address"],
|
||||||
"blockNumber": raw_event["blockNumber"],
|
"blockNumber": raw_event["blockNumber"],
|
||||||
"transactionHash": raw_event["transactionHash"].hex(),
|
"transactionHash": raw_event["transactionHash"].hex(),
|
||||||
|
@ -195,7 +196,7 @@ class EventScanner:
|
||||||
self.checksum_addresses = []
|
self.checksum_addresses = []
|
||||||
if addresses:
|
if addresses:
|
||||||
for address in addresses:
|
for address in addresses:
|
||||||
self.checksum_addresses.append(web3.toChecksumAddress(address))
|
self.checksum_addresses.append(web3.to_checksum_address(address))
|
||||||
|
|
||||||
# Our JSON-RPC throttling parameters
|
# Our JSON-RPC throttling parameters
|
||||||
self.min_scan_chunk_size = 10 # 12 s/block = 120 seconds period
|
self.min_scan_chunk_size = 10 # 12 s/block = 120 seconds period
|
||||||
|
@ -216,7 +217,7 @@ class EventScanner:
|
||||||
# Returning None since, config set to skip getting block timestamp data
|
# Returning None since, config set to skip getting block timestamp data
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
block_info = self.web3.eth.getBlock(block_num)
|
block_info = self.web3.eth.get_block(block_num)
|
||||||
except BlockNotFound:
|
except BlockNotFound:
|
||||||
# Block was not mined yet,
|
# Block was not mined yet,
|
||||||
# minor chain reorganisation?
|
# minor chain reorganisation?
|
||||||
|
@ -247,13 +248,24 @@ class EventScanner:
|
||||||
return self.web3.eth.blockNumber - 1
|
return self.web3.eth.blockNumber - 1
|
||||||
|
|
||||||
def get_last_scanned_block(self) -> int:
|
def get_last_scanned_block(self) -> int:
|
||||||
|
"""Get the last scanned block number."""
|
||||||
|
|
||||||
|
if self.state is None:
|
||||||
|
return 0
|
||||||
|
|
||||||
return self.state.get_last_scanned_block()
|
return self.state.get_last_scanned_block()
|
||||||
|
|
||||||
def delete_potentially_forked_block_data(self, after_block: int):
|
def delete_potentially_forked_block_data(self, after_block: int):
|
||||||
"""Purge old data in the case of blockchain reorganisation."""
|
"""Purge old data in the case of blockchain reorganisation."""
|
||||||
|
|
||||||
|
if self.state is None:
|
||||||
|
return
|
||||||
|
|
||||||
self.state.delete_data(after_block)
|
self.state.delete_data(after_block)
|
||||||
|
|
||||||
def estimate_next_chunk_size(self, current_chuck_size: int, event_found_count: int):
|
def estimate_next_chunk_size(
|
||||||
|
self, current_chuck_size: Union[int, float], event_found_count: int
|
||||||
|
):
|
||||||
"""Try to figure out optimal chunk size
|
"""Try to figure out optimal chunk size
|
||||||
|
|
||||||
Our scanner might need to scan the whole blockchain for all events
|
Our scanner might need to scan the whole blockchain for all events
|
||||||
|
@ -343,6 +355,8 @@ class EventScanner:
|
||||||
evt["event"],
|
evt["event"],
|
||||||
evt["blockNumber"],
|
evt["blockNumber"],
|
||||||
)
|
)
|
||||||
|
if self.state is None:
|
||||||
|
raise Exception("State is not initialized")
|
||||||
processed = self.state.process_event(block_when, evt)
|
processed = self.state.process_event(block_when, evt)
|
||||||
all_processed.append(processed)
|
all_processed.append(processed)
|
||||||
|
|
||||||
|
@ -377,14 +391,16 @@ class EventScanner:
|
||||||
|
|
||||||
# Scan in chunks, commit between
|
# Scan in chunks, commit between
|
||||||
chunk_size = start_chunk_size
|
chunk_size = start_chunk_size
|
||||||
last_scan_duration = last_logs_found = 0
|
last_scan_duration = last_logs_found = 0.0
|
||||||
total_chunks_scanned = 0
|
total_chunks_scanned = 0
|
||||||
|
|
||||||
# All processed entries we got on this scan cycle
|
# All processed entries we got on this scan cycle
|
||||||
all_processed = []
|
all_processed = []
|
||||||
|
|
||||||
while current_block <= end_block:
|
while current_block <= end_block:
|
||||||
self.state.start_chunk(current_block, chunk_size)
|
if self.state is None:
|
||||||
|
raise Exception("State is not initialized")
|
||||||
|
self.state.start_chunk(current_block, chunk_size) # type: ignore
|
||||||
|
|
||||||
# Print some diagnostics to logs to try to fiddle with real world JSON-RPC API performance
|
# Print some diagnostics to logs to try to fiddle with real world JSON-RPC API performance
|
||||||
estimated_end_block = current_block + chunk_size
|
estimated_end_block = current_block + chunk_size
|
||||||
|
|
|
@ -149,7 +149,7 @@ class MoonstreamEthereumStateProvider(EthereumStateProvider):
|
||||||
block = self._get_block_from_db(block_number)
|
block = self._get_block_from_db(block_number)
|
||||||
if block is None:
|
if block is None:
|
||||||
logger.debug(f"{log_prefix} - not found in db or cache, fetching from web3")
|
logger.debug(f"{log_prefix} - not found in db or cache, fetching from web3")
|
||||||
block = self.w3.eth.getBlock(block_number, full_transactions=True)
|
block = self.w3.eth.get_block(block_number, full_transactions=True)
|
||||||
self.metrics["web3_get_block_calls"] += 1
|
self.metrics["web3_get_block_calls"] += 1
|
||||||
else:
|
else:
|
||||||
logger.debug(f"{log_prefix} - found in db")
|
logger.debug(f"{log_prefix} - found in db")
|
||||||
|
|
|
@ -33,7 +33,7 @@ def init_web3(ipc_path: str) -> Web3:
|
||||||
def init_contract(web3: Web3, abi: Dict[str, Any], address: Optional[str]) -> Contract:
|
def init_contract(web3: Web3, abi: Dict[str, Any], address: Optional[str]) -> Contract:
|
||||||
checksum_address: Optional[ChecksumAddress] = None
|
checksum_address: Optional[ChecksumAddress] = None
|
||||||
if address is not None:
|
if address is not None:
|
||||||
checksum_address = web3.toChecksumAddress(address)
|
checksum_address = web3.to_checksum_address(address)
|
||||||
return web3.eth.contract(address=checksum_address, abi=abi)
|
return web3.eth.contract(address=checksum_address, abi=abi)
|
||||||
|
|
||||||
def make_function_call(contract: Contract, function_name: str, *args):
|
def make_function_call(contract: Contract, function_name: str, *args):
|
||||||
|
@ -102,7 +102,7 @@ def handle_args(args: argparse.Namespace):
|
||||||
if args.contract_address is None:
|
if args.contract_address is None:
|
||||||
print("Contract address was not passed from arguments")
|
print("Contract address was not passed from arguments")
|
||||||
args.contract_address = input("Enter contract address you want to call: ")
|
args.contract_address = input("Enter contract address you want to call: ")
|
||||||
contract_address = web3.toChecksumAddress(args.contract_address)
|
contract_address = web3.to_checksum_address(args.contract_address)
|
||||||
contract = web3.eth.contract(address=contract_address, abi=CONTRACT_ABI)
|
contract = web3.eth.contract(address=contract_address, abi=CONTRACT_ABI)
|
||||||
function_name = kwargs["function_name"]
|
function_name = kwargs["function_name"]
|
||||||
del kwargs["function_name"]
|
del kwargs["function_name"]
|
||||||
|
@ -116,7 +116,7 @@ def handle_args(args: argparse.Namespace):
|
||||||
if args.contract_address is None:
|
if args.contract_address is None:
|
||||||
print("Contract address was not passed from arguments")
|
print("Contract address was not passed from arguments")
|
||||||
args.contract_address = input("Enter contract address you want to transact: ")
|
args.contract_address = input("Enter contract address you want to transact: ")
|
||||||
contract_address = web3.toChecksumAddress(args.contract_address)
|
contract_address = web3.to_checksum_address(args.contract_address)
|
||||||
contract = web3.eth.contract(address=contract_address, abi=CONTRACT_ABI)
|
contract = web3.eth.contract(address=contract_address, abi=CONTRACT_ABI)
|
||||||
function_name = kwargs["function_name"]
|
function_name = kwargs["function_name"]
|
||||||
del kwargs["function_name"]
|
del kwargs["function_name"]
|
||||||
|
@ -153,7 +153,7 @@ def handle_args(args: argparse.Namespace):
|
||||||
deployer_private_key=pk,
|
deployer_private_key=pk,
|
||||||
constructor_arguments=constructor_args,
|
constructor_arguments=constructor_args,
|
||||||
)
|
)
|
||||||
print(f"Tx hash of deployment: {{web3.toHex(tx_hash)}}")
|
print(f"Tx hash of deployment: {{web3.to_hex(tx_hash)}}")
|
||||||
print(f"Address of deployed_contract: {{contract_address}}")
|
print(f"Address of deployed_contract: {{contract_address}}")
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
|
|
@ -6,7 +6,7 @@ from typing import Any, Dict, Union
|
||||||
|
|
||||||
from eth_typing.evm import Address, ChecksumAddress
|
from eth_typing.evm import Address, ChecksumAddress
|
||||||
from web3 import Web3
|
from web3 import Web3
|
||||||
from web3.contract import ContractFunction
|
from web3.contract.contract import ContractFunction
|
||||||
|
|
||||||
from .web3_util import *
|
from .web3_util import *
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
MOONWORM_VERSION = "0.6.2"
|
MOONWORM_VERSION = "0.7.0"
|
||||||
|
|
|
@ -119,13 +119,13 @@ def watch_contract(
|
||||||
state,
|
state,
|
||||||
state_provider,
|
state_provider,
|
||||||
contract_abi,
|
contract_abi,
|
||||||
[web3.toChecksumAddress(contract_address)],
|
[web3.to_checksum_address(contract_address)],
|
||||||
)
|
)
|
||||||
|
|
||||||
event_abis = [item for item in contract_abi if item["type"] == "event"]
|
event_abis = [item for item in contract_abi if item["type"] == "event"]
|
||||||
|
|
||||||
if start_block is None:
|
if start_block is None:
|
||||||
current_block = web3.eth.blockNumber - num_confirmations * 2
|
current_block = web3.eth.block_number - num_confirmations * 2
|
||||||
else:
|
else:
|
||||||
current_block = start_block
|
current_block = start_block
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ def watch_contract(
|
||||||
while end_block is None or current_block <= end_block:
|
while end_block is None or current_block <= end_block:
|
||||||
time.sleep(sleep_time)
|
time.sleep(sleep_time)
|
||||||
until_block = min(
|
until_block = min(
|
||||||
web3.eth.blockNumber - num_confirmations,
|
web3.eth.block_number - num_confirmations,
|
||||||
current_block + current_batch_size,
|
current_block + current_batch_size,
|
||||||
)
|
)
|
||||||
if end_block is not None:
|
if end_block is not None:
|
||||||
|
|
|
@ -7,7 +7,8 @@ from eth_account.account import Account # type: ignore
|
||||||
from eth_typing.evm import ChecksumAddress
|
from eth_typing.evm import ChecksumAddress
|
||||||
from hexbytes.main import HexBytes
|
from hexbytes.main import HexBytes
|
||||||
from web3 import Web3
|
from web3 import Web3
|
||||||
from web3.contract import Contract, ContractFunction
|
from web3.contract import Contract
|
||||||
|
from web3.contract.contract import ContractFunction
|
||||||
from web3.providers.ipc import IPCProvider
|
from web3.providers.ipc import IPCProvider
|
||||||
from web3.providers.rpc import HTTPProvider
|
from web3.providers.rpc import HTTPProvider
|
||||||
from web3.types import ABI, Nonce, TxParams, TxReceipt, Wei
|
from web3.types import ABI, Nonce, TxParams, TxReceipt, Wei
|
||||||
|
@ -33,7 +34,7 @@ def build_transaction(
|
||||||
- maxPriorityFeePerGas: Optional the part of the fee that goes to the miner
|
- maxPriorityFeePerGas: Optional the part of the fee that goes to the miner
|
||||||
"""
|
"""
|
||||||
|
|
||||||
transaction = builder.buildTransaction(
|
transaction = builder.build_transaction(
|
||||||
{
|
{
|
||||||
"from": sender,
|
"from": sender,
|
||||||
"nonce": get_nonce(web3, sender),
|
"nonce": get_nonce(web3, sender),
|
||||||
|
@ -105,7 +106,7 @@ def deploy_contract(
|
||||||
transaction_hash = submit_transaction(web3, transaction, deployer_private_key)
|
transaction_hash = submit_transaction(web3, transaction, deployer_private_key)
|
||||||
transaction_receipt = wait_for_transaction_receipt(web3, transaction_hash)
|
transaction_receipt = wait_for_transaction_receipt(web3, transaction_hash)
|
||||||
contract_address = transaction_receipt.contractAddress
|
contract_address = transaction_receipt.contractAddress
|
||||||
return transaction_hash, web3.toChecksumAddress(contract_address)
|
return transaction_hash, web3.to_checksum_address(contract_address)
|
||||||
|
|
||||||
|
|
||||||
def deploy_contract_from_constructor_function(
|
def deploy_contract_from_constructor_function(
|
||||||
|
@ -134,7 +135,7 @@ def deploy_contract_from_constructor_function(
|
||||||
transaction_hash = submit_transaction(web3, transaction, deployer_private_key)
|
transaction_hash = submit_transaction(web3, transaction, deployer_private_key)
|
||||||
transaction_receipt = wait_for_transaction_receipt(web3, transaction_hash)
|
transaction_receipt = wait_for_transaction_receipt(web3, transaction_hash)
|
||||||
contract_address = transaction_receipt.contractAddress
|
contract_address = transaction_receipt.contractAddress
|
||||||
return transaction_hash, web3.toChecksumAddress(contract_address)
|
return transaction_hash, web3.to_checksum_address(contract_address)
|
||||||
|
|
||||||
|
|
||||||
def decode_transaction_input(web3: Web3, transaction_input: str, abi: Dict[str, Any]):
|
def decode_transaction_input(web3: Web3, transaction_input: str, abi: Dict[str, Any]):
|
||||||
|
@ -145,7 +146,7 @@ def decode_transaction_input(web3: Web3, transaction_input: str, abi: Dict[str,
|
||||||
def read_keys_from_cli() -> Tuple[ChecksumAddress, str]:
|
def read_keys_from_cli() -> Tuple[ChecksumAddress, str]:
|
||||||
private_key = getpass.getpass(prompt="Enter private key of your address:")
|
private_key = getpass.getpass(prompt="Enter private key of your address:")
|
||||||
account = Account.from_key(private_key)
|
account = Account.from_key(private_key)
|
||||||
return (Web3.toChecksumAddress(account.address), private_key)
|
return (Web3.to_checksum_address(account.address), private_key)
|
||||||
|
|
||||||
|
|
||||||
def read_keys_from_env() -> Tuple[ChecksumAddress, str]:
|
def read_keys_from_env() -> Tuple[ChecksumAddress, str]:
|
||||||
|
@ -156,7 +157,7 @@ def read_keys_from_env() -> Tuple[ChecksumAddress, str]:
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
account = Account.from_key(private_key)
|
account = Account.from_key(private_key)
|
||||||
return (Web3.toChecksumAddress(account.address), private_key)
|
return (Web3.to_checksum_address(account.address), private_key)
|
||||||
except:
|
except:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Failed to initiate account from MOONWORM_ETHEREUM_ADDRESS_PRIVATE_KEY"
|
"Failed to initiate account from MOONWORM_ETHEREUM_ADDRESS_PRIVATE_KEY"
|
||||||
|
@ -193,7 +194,7 @@ def cast_to_python_type(evm_type: str) -> Callable:
|
||||||
elif evm_type == "string":
|
elif evm_type == "string":
|
||||||
return str
|
return str
|
||||||
elif evm_type == "address":
|
elif evm_type == "address":
|
||||||
return Web3.toChecksumAddress
|
return Web3.to_checksum_address
|
||||||
elif evm_type == "bool":
|
elif evm_type == "bool":
|
||||||
return bool
|
return bool
|
||||||
else:
|
else:
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -18,7 +18,7 @@ setup(
|
||||||
"pysha3<2.0.0,>=1.0.0",
|
"pysha3<2.0.0,>=1.0.0",
|
||||||
"tqdm",
|
"tqdm",
|
||||||
"typing-extensions",
|
"typing-extensions",
|
||||||
"web3>=5.27.0",
|
"web3>=6.1.0",
|
||||||
],
|
],
|
||||||
extras_require={
|
extras_require={
|
||||||
"dev": ["isort", "mypy", "wheel", "web3>=5.27.0"],
|
"dev": ["isort", "mypy", "wheel", "web3>=5.27.0"],
|
||||||
|
|
Ładowanie…
Reference in New Issue