Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Towards #13: tests & refactoring predictoor/ #101

Merged
merged 43 commits into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
0737408
Towards #13: tests & refactoring predictoor/
trentmc Aug 28, 2023
c9e4e16
WIP big refactor
trentmc Aug 29, 2023
5a47107
wip
trentmc Aug 29, 2023
51189ac
wip
trentmc Aug 29, 2023
15f6c31
wip
trentmc Aug 29, 2023
a01b3c8
wip
trentmc Aug 29, 2023
81808d9
wip
trentmc Aug 30, 2023
35e6f06
back out approach2 refactor. Will focus on approach1. Set up appropri…
trentmc Aug 30, 2023
8c6d504
test_predictoor_config.py is passing
trentmc Aug 30, 2023
24eb754
flesh out predictoor_config tests.
trentmc Aug 30, 2023
aab4fb7
more thorough predictoor_config tests yet. They all pass. Done these …
trentmc Aug 30, 2023
c17014b
Merge branch 'main' into issue13-tests
trentmc Aug 31, 2023
d08bcbe
Merge branch 'main' into issue13-tests
trentmc Aug 31, 2023
258573a
Now PredictoorConfig inherits from BaseConfig
trentmc Aug 31, 2023
a31b61a
wip
trentmc Aug 31, 2023
c7d49c1
git merge main
trentmc Aug 31, 2023
6df8a5a
Merge branch 'main' into issue13-tests
trentmc Aug 31, 2023
42019da
Merge branch 'main' into issue13-tests
trentmc Aug 31, 2023
64982d0
wip
trentmc Aug 31, 2023
b31bfb4
wip
trentmc Aug 31, 2023
4066bbd
wip. test_predictoor_agent1.py is passing on a basic test
trentmc Aug 31, 2023
6bcfda3
wip
trentmc Aug 31, 2023
75871e4
wip
trentmc Aug 31, 2023
5d101ef
wip
trentmc Aug 31, 2023
c16c21e
wip
trentmc Aug 31, 2023
ba869a7
Add StrMixin, better logging
trentmc Aug 31, 2023
15f04ed
wip logging
trentmc Aug 31, 2023
182dd9a
Better logging, add payout() mock
trentmc Aug 31, 2023
9c34a01
wip
trentmc Aug 31, 2023
b161d92
Better core to track time/epoch in the test. Much better logging.
trentmc Sep 1, 2023
2cae408
wip
trentmc Sep 1, 2023
a976bff
Track contract calls to make predictions and do payouts. Raise errors…
trentmc Sep 1, 2023
a1bb625
wip
trentmc Sep 1, 2023
89b8eb2
wip
trentmc Sep 1, 2023
5ef8698
wip
trentmc Sep 1, 2023
103cf75
wip
trentmc Sep 1, 2023
5b842e2
Merge branch 'main' into issue13-tests
trentmc Sep 1, 2023
d481023
black
trentmc Sep 1, 2023
11471e6
bug fixes
trentmc Sep 1, 2023
08d5d22
fix mypy complaint in predictoor_batcher
trentmc Sep 1, 2023
7aa226e
linting wip
trentmc Sep 1, 2023
40c98ab
all linters happy
trentmc Sep 1, 2023
e371d37
touch
trentmc Sep 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
git merge main
  • Loading branch information
trentmc committed Aug 31, 2023
commit c7d49c19c98b59058cbc031322a7cc9d2261246e
29 changes: 28 additions & 1 deletion pdr_backend/conftest_ganache.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import os

import pytest

from pdr_backend.models.token import Token
from pdr_backend.models.predictoor_batcher import PredictoorBatcher
from pdr_backend.models.predictoor_contract import PredictoorContract
from pdr_backend.publisher.publish import publish
from pdr_backend.util.contract import get_address
Expand Down Expand Up @@ -82,3 +82,30 @@ def predictoor_contract():
)
dt_addr = logs["newTokenAddress"]
return PredictoorContract(config, dt_addr)


@pytest.fixture(scope="module")
def predictoor_contract2():
config = Web3Config(_rpc_url(), _private_key())
_, _, _, _, logs = publish(
s_per_epoch=SECONDS_PER_EPOCH,
s_per_subscription=SECONDS_PER_EPOCH * 24,
base="ETH",
quote="USDT",
source="kraken",
timeframe="5m",
trueval_submitter_addr=config.owner,
feeCollector_addr=config.owner,
rate=3,
cut=0.2,
web3_config=config,
)
dt_addr = logs["newTokenAddress"]
return PredictoorContract(config, dt_addr)


# pylint: disable=redefined-outer-name
@pytest.fixture(scope="module")
def predictoor_batcher():
predictoor_batcher_addr = get_address(_chain_id(), "PredictoorHelper")
return PredictoorBatcher(_web3_config(), predictoor_batcher_addr)
4 changes: 2 additions & 2 deletions pdr_backend/dfbuyer/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from pdr_backend.dfbuyer.subgraph import get_consume_so_far
from pdr_backend.models.predictoor_contract import PredictoorContract
from pdr_backend.util.env import getenv_or_exit
from pdr_backend.util.subgraph import query_predictContracts
from pdr_backend.util.subgraph import query_feed_contracts
from pdr_backend.util.web3_config import Web3Config

rpc_url = getenv_or_exit("RPC_URL")
Expand Down Expand Up @@ -65,7 +65,7 @@ def process_block(block):
"""Process each contract and see if we need to submit"""
global topics
if not topics:
topics = query_predictContracts(
topics = query_feed_contracts(
subgraph_url,
pair_filters,
timeframe_filter,
Expand Down
10 changes: 6 additions & 4 deletions pdr_backend/models/base_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

from enforce_typing import enforce_types

from pdr_backend.models.feed import dictToFeed, Feed
from pdr_backend.models.predictoor_contract import PredictoorContract
from pdr_backend.models.slot import Slot
from pdr_backend.util.env import getenv_or_exit, parse_filters
from pdr_backend.util.subgraph import get_pending_slots, query_predictContracts
from pdr_backend.util.subgraph import get_pending_slots, query_feed_contracts
from pdr_backend.util.web3_config import Web3Config


Expand Down Expand Up @@ -35,16 +36,17 @@ def get_pending_slots(self, timestamp: int) -> List[Slot]:
self.source_filter,
)

def get_feeds(self) -> Dict[str, dict]:
def get_feeds(self) -> Dict[str, Feed]:
"""Return dict of [feed_addr] : {"name":.., "pair":.., ..}"""
feeds_dict = query_predictContracts(
feed_dicts = query_feed_contracts(
self.subgraph_url,
self.pair_filters,
self.timeframe_filter,
self.source_filter,
self.owner_addresses,
)
return feeds_dict
feeds = {addr: dictToFeed(feed_dict) for addr, feed_dict in feed_dicts.items()}
return feeds

def get_contracts(self, feed_addrs: List[str]) -> Dict[str, PredictoorContract]:
"""Return dict of [feed_addr] : PredictoorContract}"""
Expand Down
14 changes: 14 additions & 0 deletions pdr_backend/models/data_nft.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from typing import Union

import hashlib
import json

from enforce_typing import enforce_types
from web3 import Web3
from web3.types import TxReceipt, HexBytes

from pdr_backend.util.web3_config import Web3Config
from pdr_backend.util.contract import get_contract_abi
Expand Down Expand Up @@ -67,3 +70,14 @@ def set_ddo(self, ddo, wait_for_receipt=True):
if wait_for_receipt:
self.config.w3.eth.wait_for_transaction_receipt(tx)
return tx

def add_to_create_erc20_list(
self, addr: str, wait_for_receipt=True
) -> Union[HexBytes, TxReceipt]:
gasPrice = self.config.w3.eth.gas_price
tx = self.contract_instance.functions.addToCreateERC20List(addr).transact(
{"from": self.config.owner, "gasPrice": gasPrice}
)
if not wait_for_receipt:
return tx
return self.config.w3.eth.wait_for_transaction_receipt(tx)
34 changes: 34 additions & 0 deletions pdr_backend/models/feed.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
from typing import Any, Dict

from enforce_typing import enforce_types


class Feed: # pylint: disable=too-many-instance-attributes
@enforce_types
def __init__(
self,
name: str,
Expand Down Expand Up @@ -30,3 +36,31 @@ def quote(self):
@property
def base(self):
return self.pair.split("-")[0]


@enforce_types
def dictToFeed(feed_dict: Dict[str, Any]):
"""
@description
Convert a feed_dict into Feed format

@arguments
feed_dict -- dict with values for "name", "address", etc

@return
feed -- Feed
"""
d = feed_dict
feed = Feed(
name=d["name"],
address=d["address"],
symbol=d["symbol"],
seconds_per_epoch=d["seconds_per_epoch"],
seconds_per_subscription=d["seconds_per_subscription"],
trueval_submit_timeout=d["trueval_submit_timeout"],
owner=d["owner"],
pair=d["pair"],
timeframe=d["timeframe"],
source=d["source"],
)
return feed
64 changes: 64 additions & 0 deletions pdr_backend/models/predictoor_batcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from typing import List
from enforce_typing import enforce_types
from eth_typing import ChecksumAddress
from pdr_backend.util.contract import get_contract_abi
from pdr_backend.util.web3_config import Web3Config


@enforce_types
class PredictoorBatcher:
def __init__(self, config: Web3Config, address: str):
self.config = config
self.contract_address = config.w3.to_checksum_address(address)
self.contract_instance = config.w3.eth.contract(
address=config.w3.to_checksum_address(address),
abi=get_contract_abi("PredictoorHelper"),
)
self.contract_address = config.w3.to_checksum_address(address)

def consume_multiple(
self,
addresses: List[ChecksumAddress],
times: List[int],
token_addr: str,
wait_for_receipt=True,
):
gasPrice = self.config.w3.eth.gas_price
tx = self.contract_instance.functions.consumeMultiple(
addresses, times, token_addr
).transact({"from": self.config.owner, "gasPrice": gasPrice})
if not wait_for_receipt:
return tx
return self.config.w3.eth.wait_for_transaction_receipt(tx)

def submit_truevals_contracts(
self,
contract_addrs: List[ChecksumAddress],
epoch_starts: List[List[int]],
trueVals: List[List[bool]],
cancelRounds: List[List[bool]],
wait_for_receipt=True,
):
gasPrice = self.config.w3.eth.gas_price
tx = self.contract_instance.functions.submitTruevalContracts(
contract_addrs, epoch_starts, trueVals, cancelRounds
).transact({"from": self.config.owner, "gasPrice": gasPrice})
if not wait_for_receipt:
return tx
return self.config.w3.eth.wait_for_transaction_receipt(tx)

def submit_truevals(
self,
contract_addr: ChecksumAddress,
epoch_starts: List[int],
trueVals: List[bool],
cancelRounds: List[bool],
wait_for_receipt=True,
):
gasPrice = self.config.w3.eth.gas_price
tx = self.contract_instance.functions.submitTruevals(
contract_addr, epoch_starts, trueVals, cancelRounds
).transact({"from": self.config.owner, "gasPrice": gasPrice})
if not wait_for_receipt:
return tx
return self.config.w3.eth.wait_for_transaction_receipt(tx)
7 changes: 5 additions & 2 deletions pdr_backend/models/predictoor_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,10 @@ def get_exchanges(self):
def get_stake_token(self):
return self.contract_instance.functions.stakeToken().call()

def get_price(self):
def get_price(self) -> int:
fixed_rates = self.get_exchanges()
if not fixed_rates:
return None
return 0
(fixed_rate_address, exchange_id) = fixed_rates[0]
# get datatoken price
exchange = FixedRate(self.config, fixed_rate_address)
Expand Down Expand Up @@ -361,3 +361,6 @@ def redeem_unused_slot_revenue(self, timestamp, wait_for_receipt=True):

def get_block(self, block):
return self.config.w3.eth.get_block(block)

def erc721_addr(self) -> str:
return self.contract_instance.functions.getERC721Address().call()
28 changes: 20 additions & 8 deletions pdr_backend/models/test/test_base_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,23 @@

from pdr_backend.models.base_config import BaseConfig

ADDR = "0xe8933f2950aec1080efad1ca160a6bb641ad245d" # predictoor contract addr
PRIV_KEY = "0xef4b441145c1d0f3b4bc6d61d29f5c6e502359481152f869247c7a4244d45209"

ADDR = "0xe8933f2950aec1080efad1ca160a6bb641ad245d" # predictoor contract addr

FEED_DICT = { # info inside a predictoor contract
"name": "Contract Name",
"address": ADDR,
"symbol": "test",
"seconds_per_epoch": 300,
"seconds_per_subscription": 60,
"trueval_submit_timeout": 15,
"owner": "0xowner",
"pair": "BTC-ETH",
"timeframe": "1h",
"source": "binance",
}


@enforce_types
def test_base_config_with_filters(monkeypatch):
Expand Down Expand Up @@ -58,15 +72,13 @@ def test_base_config_feeds_contracts(monkeypatch):
c = BaseConfig()

# test get_feeds()
def _mock_query_predictContracts(
*args, **kwargs
): # pylint: disable=unused-argument
feeds_dict = {ADDR: "a mock_contract"}
return feeds_dict
def _mock_query_feed_contracts(*args, **kwargs): # pylint: disable=unused-argument
feed_dicts = {ADDR: FEED_DICT}
return feed_dicts

with patch(
"pdr_backend.models.base_config.query_predictContracts",
_mock_query_predictContracts,
"pdr_backend.models.base_config.query_feed_contracts",
_mock_query_feed_contracts,
):
feeds = c.get_feeds()
feed_addrs = list(feeds.keys())
Expand Down
38 changes: 36 additions & 2 deletions pdr_backend/models/test/test_feed.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from pdr_backend.models.feed import Feed
from enforce_typing import enforce_types

from pdr_backend.models.feed import dictToFeed, Feed

def test_contract_data_initialization():

@enforce_types
def test_feed1():
feed = Feed(
"Contract Name",
"0x12345",
Expand All @@ -27,3 +30,34 @@ def test_contract_data_initialization():
assert feed.source == "binance"
assert feed.quote == "ETH"
assert feed.base == "BTC"


@enforce_types
def test_feed2():
feed_dict = {
"name": "Contract Name",
"address": "0x12345",
"symbol": "test",
"seconds_per_epoch": 300,
"seconds_per_subscription": 60,
"trueval_submit_timeout": 15,
"owner": "0xowner",
"pair": "BTC-ETH",
"timeframe": "1h",
"source": "binance",
}
feed = dictToFeed(feed_dict)
assert isinstance(feed, Feed)

assert feed.name == "Contract Name"
assert feed.address == "0x12345"
assert feed.symbol == "test"
assert feed.seconds_per_epoch == 300
assert feed.seconds_per_subscription == 60
assert feed.trueval_submit_timeout == 15
assert feed.owner == "0xowner"
assert feed.pair == "BTC-ETH"
assert feed.timeframe == "1h"
assert feed.source == "binance"
assert feed.quote == "ETH"
assert feed.base == "BTC"
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.