86 lines
3.6 KiB
Python
86 lines
3.6 KiB
Python
import logging
|
|
import time
|
|
from datetime import datetime
|
|
from json import JSONDecodeError
|
|
from os import environ
|
|
from typing import List
|
|
|
|
import pytest
|
|
import pytz
|
|
import requests
|
|
from selenium.common import TimeoutException
|
|
|
|
import tests
|
|
|
|
|
|
class NetworkApi:
|
|
def __init__(self):
|
|
self.network_url = 'http://api-sepolia.arbiscan.io/api'
|
|
self.api_key = environ.get('ETHERSCAN_API_KEY')
|
|
|
|
def log(self, text: str):
|
|
tests.test_suite_data.current_test.testruns[-1].steps.append(text)
|
|
logging.info(text)
|
|
|
|
def send_etherscan_request(self, params):
|
|
params['apikey'] = self.api_key
|
|
try:
|
|
response = requests.get(url=self.network_url, params=params).json()
|
|
if response:
|
|
return response['result']
|
|
except TypeError as e:
|
|
self.log("Check response from etherscan API. Returned values do not match expected. %s" % str(e))
|
|
except JSONDecodeError as e:
|
|
self.log("No valid JSON response from Etherscan: %s " % str(e))
|
|
pass
|
|
|
|
def get_token_transactions(self, address: str) -> List[dict]:
|
|
params = {'module': 'account', 'action': 'tokentx', 'address': address, 'sort': 'desc'}
|
|
return self.send_etherscan_request(params)
|
|
|
|
def get_transactions(self, address: str) -> List[dict]:
|
|
params = {'module': 'account', 'action': 'txlist', 'address': address, 'page': 1, 'offset': 10, 'sort': 'desc'}
|
|
return self.send_etherscan_request(params)
|
|
|
|
def get_balance(self, address: str):
|
|
params = {'module': 'account', 'action': 'balance', 'address': address, 'tag': 'latest'}
|
|
balance = self.send_etherscan_request(params)
|
|
if balance:
|
|
self.log('Balance is %s Gwei' % balance)
|
|
return int(balance) / 1000000000000000000
|
|
else:
|
|
self.log('Cannot extract balance!')
|
|
|
|
def wait_for_confirmation_of_transaction(self, address, tx_time, confirmations=7, token=False):
|
|
expected_tx_timestamp = datetime.strptime(tx_time, "%Y-%m-%dT%H:%M:%S%z").replace(tzinfo=pytz.UTC)
|
|
start_time = time.time()
|
|
if token:
|
|
token_info = "token transaction"
|
|
else:
|
|
token_info = "ETH transaction"
|
|
self.log('Waiting for %s of %s to have %s confirmations' % (token_info, address, confirmations))
|
|
while round(time.time() - start_time, ndigits=2) < 600: # should be < idleTimeout capability
|
|
if token:
|
|
transaction = self.get_token_transactions(address)[0]
|
|
else:
|
|
transaction = self.get_transactions(address)[0]
|
|
tx_timestamp = datetime.fromtimestamp(int(transaction['timeStamp'])).replace(tzinfo=pytz.UTC)
|
|
if tx_timestamp > expected_tx_timestamp:
|
|
if int(transaction['confirmations']) >= confirmations:
|
|
return
|
|
time.sleep(20)
|
|
self.log(
|
|
'Expected amount of confirmations is %s, in fact %s' % (confirmations, transaction['confirmations']))
|
|
pytest.fail('The last transaction was not confirmed, address is %s, still has %s confirmations' % (
|
|
address, int(transaction['confirmations'])))
|
|
|
|
def wait_for_balance_to_be(self, address: str, expected_balance: int):
|
|
expected_balance = round(expected_balance, 4)
|
|
for _ in range(5):
|
|
balance = round(self.get_balance(address), 4)
|
|
if balance == expected_balance:
|
|
return
|
|
time.sleep(20)
|
|
raise TimeoutException(
|
|
'balance is not updated on Etherscan, it is %s but expected to be %s' % (balance, expected_balance))
|