Skip to content

Commit

Permalink
Towards #13: add predictoor tests (#88)
Browse files Browse the repository at this point in the history
Co-authored-by: trizin <[email protected]>
  • Loading branch information
calina-c and trizin authored Aug 26, 2023
1 parent 2df74f1 commit 70bacb1
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 49 deletions.
104 changes: 58 additions & 46 deletions pdr_backend/predictoor/approach1/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,56 +40,68 @@ def process_block(block):
)
print(f"Got new block: {block['number']} with {len(topics)} topics")
for address in topics:
topic = topics[address]
if contract_map.get(address) is None:
contract_map[address] = PredictoorContract(web3_config, address)
predictoor_contract = contract_map[address]
epoch = predictoor_contract.get_current_epoch()
seconds_per_epoch = predictoor_contract.get_secondsPerEpoch()
seconds_till_epoch_end = (
epoch * seconds_per_epoch + seconds_per_epoch - block["timestamp"]
process_topic(address, block["timestamp"])


def process_topic(address, timestamp):
topic = topics[address]

if contract_map.get(address) is None:
contract_map[address] = PredictoorContract(web3_config, address)

predictoor_contract = contract_map[address]
epoch = predictoor_contract.get_current_epoch()
seconds_per_epoch = predictoor_contract.get_secondsPerEpoch()
seconds_till_epoch_end = epoch * seconds_per_epoch + seconds_per_epoch - timestamp

print(
f"\t{topic['name']} (at address {topic['address']} is at epoch "
f"{epoch}, seconds_per_epoch: {seconds_per_epoch}, "
f"seconds_till_epoch_end: {seconds_till_epoch_end}"
)

if epoch > topic["last_submited_epoch"] > 0:
# let's get the payout for previous epoch. We don't care if it fails
slot = epoch * seconds_per_epoch - seconds_per_epoch
print(
f"Contract:{predictoor_contract.contract_address} - "
f"Claiming revenue for slot:{slot}"
)
predictoor_contract.payout(slot, False)

if seconds_till_epoch_end <= int(os.getenv("SECONDS_TILL_EPOCH_END", 60)):
"""Timestamp of prediction"""
if do_prediction(topic, epoch, predictoor_contract):
topics[address]["last_submited_epoch"] = epoch


def do_prediction(topic, epoch, predictoor_contract):
"""Let's fetch the prediction"""
target_time = (epoch + 2) * predictoor_contract.get_secondsPerEpoch()
predicted_value, predicted_confidence = predict_function(topic, target_time)

if predicted_value is None or predicted_confidence <= 0:
print(
f"\t{topic['name']} (at address {topic['address']} "
f"is at epoch {epoch}, seconds_per_epoch: {seconds_per_epoch}"
f", seconds_till_epoch_end: {seconds_till_epoch_end}"
f"We do not submit, prediction function returned "
f"({predicted_value}, {predicted_confidence})"
)
return False

"""We have a prediction, let's submit it"""
stake_amount = (
os.getenv("STAKE_AMOUNT", 1) * predicted_confidence / 100
) # TODO have a customizable function to handle this

print(
f"Contract:{predictoor_contract.contract_address} - "
f"Submiting prediction for slot:{target_time}"
)

predictoor_contract.submit_prediction(
predicted_value, stake_amount, target_time, True
)

if epoch > topic["last_submited_epoch"] and topic["last_submited_epoch"] > 0:
# let's get the payout for previous epoch. We don't care if it fails...
slot = epoch * seconds_per_epoch - seconds_per_epoch
print(
f"Contract:{predictoor_contract.contract_address} - "
f"Claiming revenue for slot:{slot}"
)
predictoor_contract.payout(slot, False)

if seconds_till_epoch_end <= int(getenv("SECONDS_TILL_EPOCH_END", "60")):
# Timestamp of prediction
target_time = (epoch + 2) * seconds_per_epoch

# Fetch the prediction
(predicted_value, predicted_confidence) = predict_function(
topic, target_time
)
if predicted_value is not None and predicted_confidence > 0:
# We have a prediction, let's submit it
stake_amount = (
int(getenv("STAKE_AMOUNT", "1")) * predicted_confidence / 100
) # TO DO have a customizable function to handle this
print(
f"Contract:{predictoor_contract.contract_address} - "
f"Submitting prediction for slot:{target_time}"
)
predictoor_contract.submit_prediction(
predicted_value, stake_amount, target_time, True
)
topics[address]["last_submited_epoch"] = epoch
else:
print(
"We do not submit, prediction function returned "
f"({predicted_value}, {predicted_confidence})"
)
return True


def log_loop(blockno):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,47 @@
import pytest
from pdr_backend.predictoor.approach1.main import ( # pylint: disable=unused-import
process_block,
log_loop,
main,
process_topic,
)
import pdr_backend.predictoor.approach1.main as main
from unittest.mock import patch, Mock
from pdr_backend.models.predictoor_contract import PredictoorContract


def test_predictoor_approach1_main():
pass
@pytest.mark.skip(reason="Incomplete, skip")
@patch("pdr_backend.predictoor.approach1.main.get_all_interesting_prediction_contracts")
def test_predictoor_main_process_block(mock_topics):
mock_topics.return_value = {"0x123": "topic"}

with patch("pdr_backend.predictoor.approach1.main.process_topic") as mock_pt:
process_block({"number": 0, "timestamp": 10})
assert mock_topics.called
mock_pt.assert_called_with("0x123", 10)


@pytest.mark.skip(reason="Incomplete, skip")
def test_predictoor_main_process_topic(monkeypatch):
monkeypatch.setenv("SECONDS_TILL_EPOCH_END", "200")
main.topics["0x123"] = {
"name": "topic",
"address": "0x123",
"last_submited_epoch": 1,
}

mock_contract = Mock(spec=PredictoorContract)
mock_contract.get_current_epoch.return_value = 2
mock_contract.get_secondsPerEpoch.return_value = 60
mock_contract.contract_address = "0x123"

main.contract_map["0x123"] = mock_contract

with patch("pdr_backend.predictoor.approach1.main.do_prediction") as mock_dp:
process_topic("0x123", 10)
mock_contract.payout.assert_called_with(60, False)
mock_dp.assert_called_with(
# last submited epoch is 2 now
{"name": "topic", "address": "0x123", "last_submited_epoch": 2},
2,
mock_contract,
)
7 changes: 7 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# pytest.ini
[pytest]
env =
D:ADDRESS_FILE=~/.ocean/ocean-contracts/artifacts/address.json
D:RPC_URL=http://127.0.0.1:8545
D:SUBGRAPH_URL=http://172.15.0.15:8000/subgraphs/name/oceanprotocol/ocean-subgraph
D:PRIVATE_KEY=0xef4b441145c1d0f3b4bc6d61d29f5c6e502359481152f869247c7a4244d45209
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"pathlib",
"pylint",
"pytest",
"pytest-env",
"requests",
"web3",
"sapphire.py",
Expand Down

0 comments on commit 70bacb1

Please sign in to comment.