diff --git a/.github/workflows/dispense_volume.yml b/.github/workflows/dispense_volume.yml index e22f6dfd2..d5358963a 100644 --- a/.github/workflows/dispense_volume.yml +++ b/.github/workflows/dispense_volume.yml @@ -79,6 +79,7 @@ jobs: echo "GOERLI_RPC_URL=https://rpc.ankr.com/eth_goerli" >> $GITHUB_ENV echo "INFURA_NETWORKS=polygon,mumbai,mainnet" >> $GITHUB_ENV echo "SEPOLIA_RPC_URL=https://rpc.sepolia.org/" >> $GITHUB_ENV + echo "DATANFT_ADDR=0xc5eba5234B69dAeC98747c906658AEa31d74b3d2" >> $GITHUB_ENV - name: Make dftool executable run: chmod +x dftool @@ -90,19 +91,36 @@ jobs: ./dftool get_rate MATIC $date $now $CSV_DIR --RETRIES $RETRY_TIMES ./dftool get_rate ROSE $date $now $CSV_DIR --RETRIES $RETRY_TIMES + - name: Set block start and end numbers + if: github.event_name == 'schedule' + run: | + ./dftool set_datanft_block_numbers $date $now 1 + ./dftool set_datanft_block_numbers $date $now 137 + ./dftool set_datanft_block_numbers $date $now 23294 + + + - name: Set block start and end numbers for test network + if: github.event_name != 'schedule' + env: + DATANFT_ADDR: "0x23D41CBdceF94132edB21b7f2ae58c959B0C9bD9" + POLYGON_RPC_URL: "https://polygon-mumbai.infura.io/v3/" + run: | + ./dftool set_datanft_block_numbers $date $now 1 + + - name: Run dftool volsym run: | - ./dftool volsym $date $now 200 $CSV_DIR 1 --RETRIES $RETRY_TIMES - ./dftool volsym $date $now 200 $CSV_DIR 137 --RETRIES $RETRY_TIMES - ./dftool volsym $date $now 200 $CSV_DIR 23294 --RETRIES $RETRY_TIMES + ./dftool volsym $date $now 200 $CSV_DIR 1 --RETRIES $RETRY_TIMES --USE_DATANFT True + ./dftool volsym $date $now 200 $CSV_DIR 137 --RETRIES $RETRY_TIMES --USE_DATANFT True + ./dftool volsym $date $now 200 $CSV_DIR 23294 --RETRIES $RETRY_TIMES --USE_DATANFT True - name: Run dftool vebals run: | - ./dftool vebals $date $now 200 $CSV_DIR 1 --RETRIES $RETRY_TIMES + ./dftool vebals $date $now 200 $CSV_DIR 1 --RETRIES $RETRY_TIMES --USE_DATANFT True - name: Run dftool allocations run: | - ./dftool allocations $date $now 200 $CSV_DIR 1 --RETRIES $RETRY_TIMES + ./dftool allocations $date $now 200 $CSV_DIR 1 --RETRIES $RETRY_TIMES --USE_DATANFT True - name: Run dftool predictoor_data run: | diff --git a/df_py/conftest.py b/df_py/conftest.py index ad1fba429..351559db4 100644 --- a/df_py/conftest.py +++ b/df_py/conftest.py @@ -2,7 +2,11 @@ from df_py.util import networkutil, oceantestutil from df_py.util.base18 import to_wei -from df_py.util.oceanutil import OCEAN_token, record_dev_deployed_contracts +from df_py.util.oceanutil import ( + OCEAN_token, + create_data_nft, + record_dev_deployed_contracts, +) def pytest_sessionstart(): @@ -30,3 +34,11 @@ def account0(): @pytest.fixture def all_accounts(): return oceantestutil.get_all_accounts() + + +@pytest.fixture +# pylint: disable=redefined-outer-name +def nft_addr(w3, account0, monkeypatch): + data_NFT = create_data_nft(w3, "1", "1", account0) + monkeypatch.setenv("DATANFT_ADDR", data_NFT.contract.address) + return data_NFT.contract.address diff --git a/df_py/util/blockrange.py b/df_py/util/blockrange.py index 28d2c5fd9..b1d3d2cd1 100644 --- a/df_py/util/blockrange.py +++ b/df_py/util/blockrange.py @@ -68,8 +68,10 @@ def __str__(self): ) -def create_range(web3, st, fin, samples, rndseed) -> BlockRange: - st_block, fin_block = get_st_fin_blocks(web3, st, fin) +def create_range( + web3, st, fin, samples, rndseed, use_data_nft: bool = False +) -> BlockRange: + st_block, fin_block = get_st_fin_blocks(web3, st, fin, use_data_nft) rng = BlockRange(st_block, fin_block, samples, rndseed, web3=web3) rng.filter_by_max_block(web3.eth.get_block("latest").number - 4) diff --git a/df_py/util/blocktime.py b/df_py/util/blocktime.py index 4476551b4..0b5bfa8e6 100644 --- a/df_py/util/blocktime.py +++ b/df_py/util/blocktime.py @@ -6,6 +6,10 @@ from scipy import optimize from web3.main import Web3 +from df_py.util.datanft_blocktime import ( + get_blocknumber_from_date, +) + @enforce_types def get_block_number_thursday(web3) -> int: @@ -248,13 +252,31 @@ def eth_find_closest_block( @enforce_types -def get_fin_block(web3, FIN): +def get_block_number_from_datanft(web3, timestamp: int) -> int: + date = datetime.fromtimestamp(timestamp) + block_number = get_blocknumber_from_date(web3, date) + block_found = web3.eth.get_block(block_number) + block_timestamp = block_found.timestamp + if abs(block_timestamp - timestamp) > 60 * 15: + print("The recorded block number is too far from the target") + print("Canceling use_data_nft") + return 0 + return block_number + + +@enforce_types +def get_fin_block(web3, FIN, use_data_nft: bool = False): fin_block = 0 if FIN == "latest": - fin_block = web3.eth.get_block("latest").number - 4 - elif FIN == "thu": - fin_block = get_block_number_thursday(web3) - elif "-" in str(FIN): + return web3.eth.get_block("latest").number - 4 + if FIN == "thu": + return get_block_number_thursday(web3) + if use_data_nft: + timestamp = int(timestr_to_timestamp(FIN) if "-" in str(FIN) else int(FIN)) + block_number = get_block_number_from_datanft(web3, timestamp) + if block_number != 0: + return block_number + if "-" in str(FIN): fin_block = timestr_to_block(web3, FIN) else: fin_block = int(FIN) @@ -262,8 +284,14 @@ def get_fin_block(web3, FIN): @enforce_types -def get_st_block(web3, ST): +def get_st_block(web3, ST, use_data_nft: bool = False): st_block = 0 + + if use_data_nft: + timestamp = timestr_to_timestamp(ST) if "-" in str(ST) else int(ST) + block_number = get_block_number_from_datanft(web3, int(timestamp)) + if block_number != 0: + return block_number if "-" in str(ST): st_block = timestr_to_block(web3, ST) else: @@ -272,7 +300,7 @@ def get_st_block(web3, ST): @enforce_types -def get_st_fin_blocks(web3, ST, FIN): - st_block = get_st_block(web3, ST) - fin_block = get_fin_block(web3, FIN) +def get_st_fin_blocks(web3, ST, FIN, use_data_nft: bool = False): + st_block = get_st_block(web3, ST, use_data_nft) + fin_block = get_fin_block(web3, FIN, use_data_nft) return (st_block, fin_block) diff --git a/df_py/util/datanft_blocktime.py b/df_py/util/datanft_blocktime.py new file mode 100644 index 000000000..23d51e50e --- /dev/null +++ b/df_py/util/datanft_blocktime.py @@ -0,0 +1,96 @@ +import os +import json +from datetime import datetime +from typing import Dict, Union + +from enforce_typing import enforce_types +from web3 import Web3 + +from df_py.volume.reward_calculator import get_df_week_number +from df_py.util.contract_base import ContractBase +from df_py.util.web3 import get_web3, get_rpc_url + + +@enforce_types +def _set_data(w3, nft_addr: str, field_label: str, data: str) -> bool: + field_label_hash = Web3.keccak(text=field_label) + field_value_bytes = data.encode() + contract_instance = ContractBase(w3, "ERC721Template", nft_addr) + tx = contract_instance.contract.functions.setNewData( + field_label_hash, field_value_bytes + ).transact() + receipt = w3.eth.wait_for_transaction_receipt(tx) + return receipt is not None and receipt["status"] == 1 + + +@enforce_types +def _read_data(w3, nft_addr: str, field_label: str) -> str: + field_label_hash = Web3.keccak(text=field_label) + contract_instance = ContractBase(w3, "ERC721Template", nft_addr) + value = contract_instance.contract.functions.getData(field_label_hash).call() + value_str = value.decode("utf-8") + return value_str + + +@enforce_types +def _get_w3_object(): + # DataNFT that holds the block numbers is deployed on Polygon + w3 = get_web3(get_rpc_url("polygon")) + return w3 + + +@enforce_types +def _set_blocknumber_data( + nft_addr: str, + from_account, + blocknumbers: Dict[str, Dict[str, int]], + week_number: str, + w3=None, +) -> bool: + w3 = _get_w3_object() if w3 is None else w3 + w3.eth.default_account = from_account + # w3.middleware_onion.add(construct_sign_and_send_raw_middleware(from_account)) + data = json.dumps(blocknumbers) + return _set_data(w3, nft_addr, week_number, data) + + +@enforce_types +def _read_blocknumber_data( + nft_addr: str, week_number: str, w3 +) -> Dict[str, Dict[str, int]]: + w3 = _get_w3_object() if w3 is None else w3 + data = _read_data(w3, nft_addr, week_number) + if data == "": + return {} + return json.loads(data) + + +@enforce_types +def get_block_number_from_weeknumber( + chainid: Union[str, int], week_number: Union[str, int], w3=None +) -> int: + data = _read_blocknumber_data(os.getenv("DATANFT_ADDR"), str(week_number), w3) + week_number = str(week_number) + if week_number not in data: + return 0 + return data[week_number].get(str(chainid), 0) + + +@enforce_types +def set_blocknumber_to_datanft( + chainid: int, from_account, blocknumber: int, week_number: Union[str, int], w3=None +) -> bool: + nft_addr = os.getenv("DATANFT_ADDR") + week_number = str(week_number) + data = _read_blocknumber_data(nft_addr, week_number, w3) + if week_number not in data: + data[week_number] = {} + data[week_number][chainid] = blocknumber + return _set_blocknumber_data(nft_addr, from_account, data, str(week_number), w3) + + +@enforce_types +def get_blocknumber_from_date(w3, date: datetime) -> int: + df_week = get_df_week_number(date) + chainid = w3.eth.chain_id + return get_block_number_from_weeknumber(chainid, df_week) diff --git a/df_py/util/dftool_module.py b/df_py/util/dftool_module.py index 406159396..293e48f4d 100644 --- a/df_py/util/dftool_module.py +++ b/df_py/util/dftool_module.py @@ -3,6 +3,8 @@ import os import sys +from datetime import datetime + from enforce_typing import enforce_types from eth_account import Account from web3.main import Web3 @@ -23,7 +25,7 @@ from df_py.predictoor.queries import query_predictoor_contracts, query_predictoors from df_py.util import blockrange, dispense, get_rate, networkutil, oceantestutil from df_py.util.base18 import from_wei, to_wei -from df_py.util.blocktime import get_fin_block, timestr_to_timestamp +from df_py.util.blocktime import get_fin_block, get_st_fin_blocks, timestr_to_timestamp from df_py.util.constants import SAPPHIRE_MAINNET_CHAINID from df_py.util.contract_base import ContractBase from df_py.util.dftool_arguments import ( @@ -58,8 +60,13 @@ get_active_reward_amount_for_week_eth_by_stream, ) from df_py.volume import csvs, queries +from df_py.volume.reward_calculator import RewardShaper, get_df_week_number from df_py.util.reward_shaper import RewardShaper from df_py.volume.calc_rewards import calc_volume_rewards_from_csvs +from df_py.util.datanft_blocktime import ( + get_block_number_from_weeknumber, + set_blocknumber_to_datanft, +) @enforce_types @@ -73,6 +80,13 @@ def do_volsym(): command_name="volsym", csv_names="nftvols-CHAINID.csv, owners-CHAINID.csv, symbols-CHAINID.csv", ) + parser.add_argument( + "--USE_DATANFT", + default=False, + type=bool, + help="Use DataNFT contract for block numbers", + required=False, + ) arguments = parser.parse_args() print_arguments(arguments) @@ -93,7 +107,12 @@ def do_volsym(): # main work rng = blockrange.create_range( - web3, arguments.ST, arguments.FIN, arguments.NSAMP, SECRET_SEED + web3, + arguments.ST, + arguments.FIN, + arguments.NSAMP, + SECRET_SEED, + arguments.USE_DATANFT, ) (Vi, Ci, SYMi) = retry_function( @@ -167,6 +186,13 @@ def do_allocations(): command_name="allocations", csv_names="allocations.csv or allocations_realtime.csv", ) + parser.add_argument( + "--USE_DATANFT", + default=False, + type=bool, + help="Use DataNFT contract for block numbers", + required=False, + ) arguments = parser.parse_args() print_arguments(arguments) @@ -182,7 +208,7 @@ def do_allocations(): # main work rng = blockrange.create_range( - web3, arguments.ST, arguments.FIN, n_samp, SECRET_SEED + web3, arguments.ST, arguments.FIN, n_samp, SECRET_SEED, arguments.USE_DATANFT ) allocs = retry_function( queries.queryAllocations, arguments.RETRIES, 10, rng, chain_id @@ -205,6 +231,13 @@ def do_vebals(): command_name="vebals", csv_names="vebals.csv or vebals_realtime.csv", ) + parser.add_argument( + "--USE_DATANFT", + default=False, + type=bool, + help="Use DataNFT contract for block numbers", + required=False, + ) arguments = parser.parse_args() print_arguments(arguments) @@ -217,7 +250,7 @@ def do_vebals(): web3 = networkutil.chain_id_to_web3(chain_id) rng = blockrange.create_range( - web3, arguments.ST, arguments.FIN, n_samp, SECRET_SEED + web3, arguments.ST, arguments.FIN, n_samp, SECRET_SEED, arguments.USE_DATANFT ) balances, locked_amt, unlock_time = retry_function( @@ -358,6 +391,86 @@ def do_predictoor_data(): # ======================================================================== +@enforce_types +def do_set_datanft_block_numbers(): + parser = argparse.ArgumentParser( + description="Set the block numbers in the DataNFT \ + contract for given start and end dates if not already set" + ) + parser.add_argument("command", choices=["set_datanft_block_numbers"]) + parser.add_argument( + "ST", + type=valid_date, + help="start date -- YYYY-MM-DD", + ) + parser.add_argument( + "FIN", + type=valid_date, + help="end date -- YYYY-MM-DD", + ) + parser.add_argument( + "CHAINID", + type=chain_type, + help=f"DFRewards contract's network.{CHAINID_EXAMPLES}. If not given, uses 1 (mainnet).", + ) + + arguments = parser.parse_args() + print_arguments(arguments) + st_date = datetime.strptime(arguments.ST, "%Y-%m-%d") + start_week_number = get_df_week_number(st_date) + end_week_number = start_week_number + 1 + from_account = _getPrivateAccount() + web3 = networkutil.chain_id_to_web3(arguments.CHAINID) + + # get the block numbers + block_number_start = get_block_number_from_weeknumber( + web3.eth.chain_id, start_week_number + ) + block_number_end = get_block_number_from_weeknumber( + web3.eth.chain_id, end_week_number + ) + st_block, fin_block = get_st_fin_blocks(web3, arguments.ST, arguments.FIN, False) + print( + "Start and end block numbers:", + block_number_start, + block_number_end, + st_block, + fin_block, + ) + if block_number_start == 0: + # not set, so set it + print(f"Setting block number {st_block} for week {start_week_number}") + done = set_blocknumber_to_datanft( + web3.eth.chain_id, from_account.address, st_block, start_week_number + ) + if done: + print(f"Block number {st_block} set for week {start_week_number}") + else: + print( + f"Transaction failed for week {start_week_number} \ + while setting block number {st_block}" + ) + + if block_number_end == 0: + # not set, so set it + print(f"Setting block number {fin_block} for week {end_week_number}") + done = set_blocknumber_to_datanft( + web3.eth.chain_id, from_account.address, fin_block, end_week_number + ) + if done: + print(f"Block number {fin_block} set for week {end_week_number}") + else: + print( + f"Transaction failed for week {end_week_number} \ + while setting block number {fin_block}" + ) + + print("dftool set_datanft_block_numbers: Done") + + +# ======================================================================== + + @enforce_types def do_calc(): parser = argparse.ArgumentParser( diff --git a/df_py/util/test/test_blocktime_ganache.py b/df_py/util/test/test_blocktime_ganache.py index 0e91479ba..17bd99129 100644 --- a/df_py/util/test/test_blocktime_ganache.py +++ b/df_py/util/test/test_blocktime_ganache.py @@ -9,6 +9,7 @@ from df_py.util.blockrange import create_range from df_py.util.blocktime import ( + get_block_number_from_datanft, get_block_number_thursday, get_next_thursday_timestamp, get_st_fin_blocks, @@ -17,6 +18,9 @@ timestr_to_timestamp, BlockTimestampComparer, ) +from df_py.util.datanft_blocktime import ( + set_blocknumber_to_datanft, +) @enforce_types @@ -197,3 +201,21 @@ def test_get_st_fin_blocks(w3): # to avoid extra setup in test_blockrange.py just for one test rng = create_range(w3, 10, 5000, 100, 42) assert rng + + +def test_get_block_number_from_datanft(w3, nft_addr, account0, monkeypatch): + _ = nft_addr # linter fix - use the fixture to have the nft deployed + monkeypatch.setenv("POLYGON_RPC_URL", "http://localhost:8545") + ts_st = int(datetime.strptime("2024-03-10", "%Y-%m-%d").timestamp()) + ts_fin = int(datetime.now().timestamp()) + + block_number_st_zero = get_block_number_from_datanft(w3, ts_fin) + assert block_number_st_zero == 0 + + set_blocknumber_to_datanft(w3.eth.chain_id, account0.address, 1, 80, w3) + set_blocknumber_to_datanft(w3.eth.chain_id, account0.address, 2, 81, w3) + + block_number_st = get_block_number_from_datanft(w3, ts_st) + block_number_fin = get_block_number_from_datanft(w3, ts_fin) + assert block_number_st == 0 + assert block_number_fin == 1 diff --git a/df_py/util/test/test_datanft_blocktime.py b/df_py/util/test/test_datanft_blocktime.py new file mode 100644 index 000000000..655fa7356 --- /dev/null +++ b/df_py/util/test/test_datanft_blocktime.py @@ -0,0 +1,181 @@ +# pylint: disable=redefined-outer-name +import os +from datetime import datetime +from unittest.mock import patch + +from df_py.util.blocktime import get_fin_block, get_st_block +from df_py.volume.reward_calculator import get_df_week_number +from df_py.util.datanft_blocktime import ( + _get_w3_object, + _read_blocknumber_data, + _read_data, + _set_blocknumber_data, + _set_data, + get_block_number_from_weeknumber, + get_blocknumber_from_date, + set_blocknumber_to_datanft, +) + + +def test_datanft_write_and_read(w3, account0, nft_addr): + _ = nft_addr # linter fix - use the fixture to have the nft deployed + CHAIN_ID = 42 + week_number = 20 + + # Read the block number while it is not set, should return 0 + block_number = get_block_number_from_weeknumber(CHAIN_ID, week_number, w3) + assert block_number == 0, "non-set block number must be 0" + + assert set_blocknumber_to_datanft( + CHAIN_ID, account0.address, 100, week_number, w3 + ), "Failed to set block number data" + + # Read the block number again, should return 100 + block_number = get_block_number_from_weeknumber(CHAIN_ID, week_number, w3) + assert block_number == 100, "block number must be 100" + + +def test_multiple_chainids_write_and_read(w3, account0, nft_addr): + _ = nft_addr # linter fix - use the fixture to have the nft deployed + week_number = 20 + chain_ids_and_block_numbers = { + 1: 1000, + 2: 2000, + 3: 3000, + } + + for chain_id, block_number in chain_ids_and_block_numbers.items(): + assert set_blocknumber_to_datanft( + chain_id, account0.address, block_number, week_number, w3 + ), f"Failed to set block number for chain ID {chain_id}" + + for chain_id, expected_block_number in chain_ids_and_block_numbers.items(): + actual_block_number = get_block_number_from_weeknumber( + chain_id, week_number, w3 + ) + assert ( + actual_block_number == expected_block_number + ), f"Block number for chain ID {chain_id} must be {expected_block_number}" + + +def test_overwrite_existing_data(w3, account0, nft_addr): + _ = nft_addr # linter fix - use the fixture to have the nft deployed + CHAIN_ID = 42 + week_number = 20 + NEW_BLOCK_NUMBER = 200 + + # Set initial block number + set_blocknumber_to_datanft(CHAIN_ID, account0.address, 100, week_number, w3) + # Overwrite with a new block number + assert set_blocknumber_to_datanft( + CHAIN_ID, account0.address, NEW_BLOCK_NUMBER, week_number, w3 + ), "Failed to overwrite block number data" + + # Read back the overwritten block number + block_number = get_block_number_from_weeknumber(CHAIN_ID, week_number, w3) + assert block_number == NEW_BLOCK_NUMBER, "Overwritten block number must be 200" + + +def test_read_nonexistent_chainid(w3, nft_addr): + _ = nft_addr # linter fix - use the fixture to have the nft deployed + week_number = 20 + NON_EXISTENT_CHAIN_ID = 999 + + # Attempt to read a block number for a non-existent chain ID + block_number = get_block_number_from_weeknumber( + NON_EXISTENT_CHAIN_ID, week_number, w3 + ) + assert block_number == 0, "Block number for a non-existent chain ID must be 0" + + +@patch.dict(os.environ, {"POLYGON_RPC_URL": "http://localhost:8545"}) +def test_get_w3_object(): + w3 = _get_w3_object() + assert w3.is_connected(), "Web3 object is not connected" + + +def test_set_data(w3, nft_addr): + field_label = "test_field" + data = "test_data" + assert _set_data(w3, nft_addr, field_label, data), "Failed to set data" + + +def test_read_data(w3, nft_addr): + field_label = "test_field" + data = "test_data" + _set_data(w3, nft_addr, field_label, data) + read_data = _read_data(w3, nft_addr, field_label) + assert read_data == data, "Read data does not match set data" + + +def test_set_blocknumber_data(w3, account0, monkeypatch, nft_addr): + monkeypatch.setenv("POLYGON_RPC_URL", "http://localhost:8545") + blocknumbers = {"1": 12345, "2": 67890} + week_number = "20" + from_account = account0.address + + # Set block number data + set_result = _set_blocknumber_data( + nft_addr, from_account, blocknumbers, week_number, w3 + ) + assert set_result, "Failed to set blocknumber data" + + +def test_read_blocknumber_data(w3, account0, monkeypatch, nft_addr): + monkeypatch.setenv("POLYGON_RPC_URL", "http://localhost:8545") + blocknumbers = {"1": 12345, "2": 67890} + week_number = "20" + from_account = account0.address + + # Set block number set + _set_blocknumber_data(nft_addr, from_account, blocknumbers, week_number, w3) + + # Now, read and verify the block number data + read_result = _read_blocknumber_data(nft_addr, week_number, w3) + assert read_result == blocknumbers, "Read blocknumber data does not match expected" + + +@patch.dict(os.environ, {"POLYGON_RPC_URL": "http://localhost:8545"}) +def test_get_st_block(w3, account0, nft_addr): + _ = nft_addr # linter fix - use the fixture to have the nft deployed + last_block = w3.eth.block_number + last_block_timestamp = w3.eth.get_block(last_block).timestamp + last_block_datetime = datetime.fromtimestamp(last_block_timestamp) + week_number = get_df_week_number(last_block_datetime) + assert set_blocknumber_to_datanft( + w3.eth.chain_id, account0.address, last_block, week_number, w3 + ), "Failed to set block number data" + block = get_st_block(w3, last_block_timestamp, True) + + assert block == last_block + + +@patch.dict(os.environ, {"POLYGON_RPC_URL": "http://localhost:8545"}) +def test_get_fin_block(w3, account0, nft_addr): + _ = nft_addr # linter fix - use the fixture to have the nft deployed + last_block = w3.eth.block_number + last_block_timestamp = w3.eth.get_block(last_block).timestamp + last_block_datetime = datetime.fromtimestamp(last_block_timestamp) + week_number = get_df_week_number(last_block_datetime) + assert set_blocknumber_to_datanft( + w3.eth.chain_id, account0.address, last_block, week_number, w3 + ), "Failed to set block number data" + block = get_fin_block(w3, last_block_timestamp, True) + + assert block == last_block + + +def test_get_blocknumber_from_date(w3, account0, nft_addr, monkeypatch): + _ = nft_addr # linter fix - use the fixture to have the nft deployed + monkeypatch.setenv("POLYGON_RPC_URL", "http://localhost:8545") + st = datetime.strptime("2024-03-7", "%Y-%m-%d") + fin = datetime.strptime("2024-03-14", "%Y-%m-%d") + + set_blocknumber_to_datanft(w3.eth.chain_id, account0.address, 100, 80, w3) + set_blocknumber_to_datanft(w3.eth.chain_id, account0.address, 200, 81, w3) + + st_block = get_blocknumber_from_date(w3, st) + fin_block = get_blocknumber_from_date(w3, fin) + + assert st_block == 100 + assert fin_block == 200 diff --git a/df_py/util/test/test_dftool_ganache.py b/df_py/util/test/test_dftool_ganache.py index 5d9964633..f397eabda 100644 --- a/df_py/util/test/test_dftool_ganache.py +++ b/df_py/util/test/test_dftool_ganache.py @@ -21,8 +21,10 @@ from df_py.util import dftool_module, networkutil, oceantestutil, oceanutil from df_py.util.base18 import from_wei, to_wei from df_py.util.contract_base import ContractBase +from df_py.util.datanft_blocktime import get_block_number_from_weeknumber from df_py.util.dftool_module import do_predictoor_data from df_py.volume import csvs +from df_py.volume.reward_calculator import get_df_week_number PREV, DFTOOL_ACCT = {}, None @@ -713,6 +715,40 @@ def test_chain_info(): dftool_module.do_chain_info() +def test_set_datanft_block_numbers(nft_addr, monkeypatch, account0): + monkeypatch.setenv("POLYGON_RPC_URL", "http://localhost:8545") + monkeypatch.setenv("DATANFT_ADDR", nft_addr) + sys_argv = [ + "dftool", + "set_datanft_block_numbers", + "2024-02-15", + "2024-02-22", + str(networkutil.DEV_CHAINID), + ] + with patch( + "df_py.util.dftool_module.get_st_fin_blocks", return_value=(100, 200) + ), patch("df_py.util.dftool_module._getPrivateAccount", return_value=account0): + with sysargs_context(sys_argv): + dftool_module.do_set_datanft_block_numbers() + + ST = "2024-02-15" + ST = datetime.datetime.strptime(ST, "%Y-%m-%d") + FIN = "2024-02-22" + FIN = datetime.datetime.strptime(FIN, "%Y-%m-%d") + week_number_st = get_df_week_number(ST) + week_number_fin = get_df_week_number(FIN) + + block_number_st = get_block_number_from_weeknumber( + networkutil.DEV_CHAINID, week_number_st + ) + block_number_fin = get_block_number_from_weeknumber( + networkutil.DEV_CHAINID, week_number_fin + ) + + assert block_number_st == 100 + assert block_number_fin == 200 + + @enforce_types def setup_function(): global DFTOOL_ACCT