Skip to content

Commit

Permalink
Add tzpro api key in config
Browse files Browse the repository at this point in the history
  • Loading branch information
vkresch committed Nov 4, 2023
1 parent 0e5d37f commit 3941155
Show file tree
Hide file tree
Showing 17 changed files with 93 additions and 59 deletions.
1 change: 0 additions & 1 deletion .env.example

This file was deleted.

2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ jobs:
pip install -r requirements_developers.txt
- name: Test with pytest
env:
TZPRO_API_KEY: ${{ secrets.TZPRO_API_KEY }}
run: pytest tests/

build-documentation:
Expand Down
8 changes: 7 additions & 1 deletion docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,13 @@ Available configuration parameters are:
tz1V9SpwXaGFiYdDfGJtWjA61EumAH3DwSyT: tz1fgX6oRWQb4HYHUT6eRjW8diNFrqjEfgq7 #(redirects payment from tz1V9S... to tz1fgX...)
tz1RMmSzPSWPSSaKU193Voh4PosWSZx1C7Hs: Dexter #(indicates address is a dexter pool; TRD will send rewards to pool members)
mindelegation: TOE #(mindelegation will be shared with everyone)

**tzpro_api_key**
Generate a tzpro API key [here](https://tzpro.io/) if you want to use it as reward or block API.

Example::
tzpro_api_key: XXXXXXXXXX

**plugins**
Please consult the `plugins docs`_ for more details on the configuring the various plugins.

Expand Down
1 change: 1 addition & 0 deletions examples/tz1boot1pK9h2BVGXdyvfQSv8kd1LQM6H889.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ baking_address: tz1boot1pK9h2BVGXdyvfQSv8kd1LQM6H889
payment_address: KT1KLQbYFtFZ5mAEnfEMZaWYuNtCsGuP5cLS
rewards_type: actual
service_fee: 4.5
tzpro_api_key: XXXXXXXX
founders_map:
{'tz1boot1pK9h2BVGXdyvfQSv8kd1LQM6H889' : 0.3,
'KT1KLQbYFtFZ5mAEnfEMZaWYuNtCsGuP5cLS' : 0.7}
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ parse>=1.19.1
transitions>=0.9.0
tweepy>=4.14.0
pip>=23.3.1
python-dotenv==0.21.1
13 changes: 10 additions & 3 deletions src/api/provider_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def newRewardApi(
node_url,
node_url_public="",
api_base_url=None,
tzpro_api_key="",
):
if self.provider == "rpc":
if node_url.find("http") == -1:
Expand All @@ -28,21 +29,27 @@ def newRewardApi(
node_url_public = PUBLIC_NODE_URL[network_config["NAME"]]
return RpcRewardApiImpl(network_config, baking_address, node_url_public)
elif self.provider == "tzpro":
return TzProRewardApiImpl(network_config, baking_address)
return TzProRewardApiImpl(network_config, baking_address, tzpro_api_key)
elif self.provider == "tzkt":
return TzKTRewardApiImpl(
network_config, baking_address, base_url=api_base_url
)

raise Exception("No supported reward data provider : {}".format(self.provider))

def newBlockApi(self, network_config, node_url, api_base_url=None):
def newBlockApi(
self,
network_config,
node_url,
api_base_url=None,
tzpro_api_key="",
):
if self.provider == "rpc" or self.provider == "prpc":
if node_url.find("http") == -1:
node_url = "http://" + node_url
return RpcBlockApiImpl(network_config, node_url)
elif self.provider == "tzpro":
return TzProBlockApiImpl(network_config)
return TzProBlockApiImpl(network_config, tzpro_api_key)
elif self.provider == "tzkt":
return TzKTBlockApiImpl(network_config, base_url=api_base_url)

Expand Down
40 changes: 11 additions & 29 deletions src/blockwatch/tzpro_api_constants.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,31 @@
import os
from dotenv import load_dotenv
from log_config import verbose_logger

# TODO: Check if there are changes to the indicies!
# https://docs.tzpro.io/api/index/tables/income-table
# https://docs.tzpro.io/api/index/tables/income-table?tab=Response

# Rights
idx_income_baking_rights = 8
idx_income_blocks_baked = 14
idx_income_blocks_not_baked = 16
idx_income_active_stake = 6

# Income/Rewards Breakdown
idx_income_expected_income = 21
idx_income_total_income = 22

idx_income_total_deposits = 23
idx_income_baking_income = 24
idx_income_endorsing_income = 25
idx_income_accusation_income = 26
idx_income_seed_income = 27
idx_income_fees_income = 28
idx_income_missed_baking_income = 29 # Missing for now?
idx_income_missed_endorsing_income = 30 # Missing for now?
idx_income_stolen_baking_income = 31 # Missing for now?

idx_income_total_loss = 29
idx_income_accusation_loss = 30
idx_income_seed_loss = 31
idx_income_endorsing_loss = 32
idx_income_lost_accusation_fees = 33
idx_income_lost_accusation_rewards = 34
idx_income_lost_accusation_deposits = 35
idx_income_lost_seed_fees = 36
idx_income_lost_seed_rewards = 37

# Rights
idx_n_baking_rights = 8
idx_n_blocks_baked = 14
idx_n_blocks_not_baked = 16
idx_n_active_stake = 6

# Cycle Snapshot
idx_balance = 0
idx_baker_delegated = 1
Expand All @@ -40,16 +35,3 @@
idx_cb_delegator_id = 0
idx_cb_current_balance = 1
idx_cb_delegator_address = 2


def load_key_from_env_variables():
load_dotenv()
try:
key = os.getenv("TZPRO_API_KEY")
except:
verbose_logger.exception("Unable to load TZPRO_API_KEY from .env file!")
if key == "":
verbose_logger.exception(
"Please copy the .env.example file to .env and add your personal TZPRO_API_KEY!"
)
return key
10 changes: 7 additions & 3 deletions src/blockwatch/tzpro_block_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@
from exception.api_provider import ApiProviderException
from log_config import main_logger, verbose_logger
from Constants import TZPRO_API_URL
from blockwatch.tzpro_api_constants import load_key_from_env_variables

logger = main_logger


class TzProBlockApiImpl(BlockApi):
def __init__(self, nw):
def __init__(self, nw, tzpro_api_key):
super(TzProBlockApiImpl, self).__init__(nw)

self.head_api = TZPRO_API_URL[nw["NAME"]]
if self.head_api is None:
raise Exception("Unknown network {}".format(nw))
self.key = load_key_from_env_variables()

if tzpro_api_key == "":
raise Exception(
"Please set a tzpro api key in the config to use this block api!"
)
self.key = tzpro_api_key

def get_current_cycle_and_level(self):
uri = self.head_api + "/explorer/tip"
Expand Down
9 changes: 6 additions & 3 deletions src/blockwatch/tzpro_reward_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@
from log_config import main_logger
from model.reward_provider_model import RewardProviderModel
from blockwatch.tzpro_reward_provider_helper import TzProRewardProviderHelper
from blockwatch.tzpro_api_constants import load_key_from_env_variables
from Constants import MUTEZ_PER_TEZ
from Dexter import dexter_utils as dxtz

logger = main_logger


class TzProRewardApiImpl(RewardApi):
def __init__(self, nw, baking_address):
def __init__(self, nw, baking_address, tzpro_api_key):
super().__init__()
self.name = "tzpro"
self.logger = main_logger
self.key = load_key_from_env_variables()
if tzpro_api_key == "":
raise Exception(
"Please set a tzpro api key in the config to use this reward api!"
)
self.key = tzpro_api_key
self.helper = TzProRewardProviderHelper(nw, baking_address, self.key)

self.blocks_per_cycle = nw["BLOCKS_PER_CYCLE"]
Expand Down
10 changes: 4 additions & 6 deletions src/blockwatch/tzpro_reward_provider_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@

from log_config import main_logger, verbose_logger
from blockwatch.tzpro_api_constants import (
idx_n_baking_rights,
idx_income_baking_rights,
idx_income_expected_income,
idx_income_total_income,
idx_income_lost_accusation_fees,
idx_income_lost_accusation_rewards,
idx_cb_delegator_address,
idx_cb_current_balance,
idx_n_active_stake,
idx_income_active_stake,
idx_income_lost_accusation_deposits,
idx_income_lost_seed_fees,
idx_income_lost_seed_rewards,
idx_income_missed_baking_income,
idx_income_missed_endorsing_income,
)
from Constants import TZPRO_API_URL, MUTEZ_PER_TEZ

Expand Down Expand Up @@ -94,8 +92,8 @@ def get_rewards_for_cycle(self, cycle):

resp = resp.json()[0]

root["num_baking_rights"] = resp[idx_n_baking_rights]
root["active_stake"] = resp[idx_n_active_stake]
root["num_baking_rights"] = resp[idx_income_baking_rights]
root["active_stake"] = resp[idx_income_active_stake]

# rewards earned (excluding equivocation losses and equivocation accusation income)
root["rewards_and_fees"] = int(
Expand Down
8 changes: 7 additions & 1 deletion src/config/yaml_baking_conf_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,14 @@ def __init__(
self.clnt_mngr = clnt_mngr
self.network_config = network_config
if block_api is None:
tzpro_api_key = (
self.tzpro_api_key if provider_factory.provider == "tzpro" else ""
)
block_api = provider_factory.newBlockApi(
network_config, node_url, api_base_url=api_base_url
network_config,
node_url,
api_base_url=api_base_url,
tzpro_api_key=tzpro_api_key,
)
self.block_api = block_api
self.dry_run = dry_run
Expand Down
4 changes: 4 additions & 0 deletions src/model/baking_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
REWARDS_TYPE = "rewards_type"
PAY_DENUNCIATION_REWARDS = "pay_denunciation_rewards"
MIN_PAYMENT_AMT = "min_payment_amt"
TZPRO_API_KEY = "tzpro_api_key"

# extensions
FULL_SUPPORTERS_SET = "__full_supporters_set"
Expand Down Expand Up @@ -118,3 +119,6 @@ def __repr__(self) -> str:

def get_min_payment_amount(self):
return self.get_attribute(MIN_PAYMENT_AMT)

def get_tzpro_api_key(self):
return self.get_attribute(TZPRO_API_KEY)
7 changes: 6 additions & 1 deletion src/pay/payment_producer.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,20 @@ def __init__(

self.node_url = node_url
self.client_manager = client_manager
self.tzpro_api_key = baking_cfg.get_tzpro_api_key()
self.reward_api = self.provider_factory.newRewardApi(
network_config,
self.baking_address,
self.node_url,
node_url_public,
api_base_url,
self.tzpro_api_key,
)
self.block_api = self.provider_factory.newBlockApi(
network_config, self.node_url, api_base_url
network_config,
self.node_url,
api_base_url,
self.tzpro_api_key,
)

dexter_contracts_set = baking_cfg.get_contracts_set()
Expand Down
10 changes: 6 additions & 4 deletions tests/integration/test_api_consistency.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import pytest
import requests
from src.Constants import DEFAULT_NETWORK_CONFIG_MAP, PUBLIC_NODE_URL, RewardsType
Expand All @@ -11,15 +12,14 @@
# Reward APIs
from src.tzkt.tzkt_reward_api import TzKTRewardApiImpl
from src.blockwatch.tzpro_reward_api import TzProRewardApiImpl
from src.blockwatch.tzpro_api_constants import load_key_from_env_variables

MAINNET_ADDRESS_DELEGATOR = Constants.MAINNET_ADDRESS_DELEGATOR
MAINNET_ADDRESS_STAKENOW_BAKER = Constants.MAINNET_ADDRESS_STAKENOW_BAKER
MAINNET_ADDRESS_BAKEXTZ4ME_BAKER = Constants.MAINNET_ADDRESS_BAKEXTZ4ME_BAKER
GHOSTNET_ADDRESS_STAKENOW_BAKER = Constants.GHOSTNET_ADDRESS_STAKENOW_BAKER
MAINNET_ADDRESS_BAKEXTZ4ME_PAYOUT = Constants.MAINNET_ADDRESS_BAKEXTZ4ME_PAYOUT

TZ_PRO_API_KEY = load_key_from_env_variables()
TZ_PRO_API_KEY = os.environ.get("TZ_PRO_API_KEY")

# These tests should not be mocked but test the overall consistency
# accross all tezos APIs which are available in TRD
Expand All @@ -32,7 +32,7 @@ def address_block_api_tzkt():

@pytest.fixture
def address_block_api_tzpro():
return TzProBlockApiImpl(DEFAULT_NETWORK_CONFIG_MAP["MAINNET"])
return TzProBlockApiImpl(DEFAULT_NETWORK_CONFIG_MAP["MAINNET"], TZ_PRO_API_KEY)


@pytest.fixture
Expand Down Expand Up @@ -108,7 +108,9 @@ def address_reward_api_tzkt():
@pytest.fixture
def address_reward_api_tzpro():
return TzProRewardApiImpl(
DEFAULT_NETWORK_CONFIG_MAP["MAINNET"], MAINNET_ADDRESS_BAKEXTZ4ME_BAKER
DEFAULT_NETWORK_CONFIG_MAP["MAINNET"],
MAINNET_ADDRESS_BAKEXTZ4ME_BAKER,
TZ_PRO_API_KEY,
)


Expand Down
4 changes: 3 additions & 1 deletion tests/integration/test_tzstats_block_api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import pytest
from src.blockwatch.tzpro_block_api import TzProBlockApiImpl
from unittest.mock import patch, MagicMock
Expand All @@ -6,6 +7,7 @@

MAINNET_ADDRESS_DELEGATOR = Constants.MAINNET_ADDRESS_DELEGATOR
MAINNET_ADDRESS_STAKENOW_BAKER = Constants.MAINNET_ADDRESS_STAKENOW_BAKER
TZ_PRO_API_KEY = os.environ.get("TZ_PRO_API_KEY")


class MockResponse:
Expand All @@ -19,7 +21,7 @@ def status_code(self):

@pytest.fixture
def address_api():
return TzProBlockApiImpl(DEFAULT_NETWORK_CONFIG_MAP["MAINNET"])
return TzProBlockApiImpl(DEFAULT_NETWORK_CONFIG_MAP["MAINNET"], TZ_PRO_API_KEY)


def test_get_revelation(address_api):
Expand Down
15 changes: 11 additions & 4 deletions tests/regression/test_baker_validation.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import pytest
from src.cli.client_manager import ClientManager
from src.config.yaml_baking_conf_parser import BakingYamlConfParser
Expand All @@ -8,7 +9,7 @@
from src.blockwatch.tzpro_block_api import TzProBlockApiImpl
from tests.utils import Constants


TZ_PRO_API_KEY = os.environ.get("TZ_PRO_API_KEY")
node_endpoint = PUBLIC_NODE_URL["MAINNET"]
network = {"NAME": "MAINNET"}

Expand All @@ -18,7 +19,9 @@
[
pytest.param(RpcBlockApiImpl(network, node_endpoint), id="RpcBlockApiImpl"),
pytest.param(TzKTBlockApiImpl(network), id="TzKTBlockApiImpl"),
pytest.param(TzProBlockApiImpl(network), id="TzProBlockApiImpl"),
pytest.param(
TzProBlockApiImpl(network, TZ_PRO_API_KEY), id="TzProBlockApiImpl"
),
],
)
def test_address_is_baker_address(block_api):
Expand Down Expand Up @@ -48,7 +51,9 @@ def test_address_is_baker_address(block_api):
[
pytest.param(RpcBlockApiImpl(network, node_endpoint), id="RpcBlockApiImpl"),
pytest.param(TzKTBlockApiImpl(network), id="TzKTBlockApiImpl"),
pytest.param(TzProBlockApiImpl(network), id="TzProBlockApiImpl"),
pytest.param(
TzProBlockApiImpl(network, TZ_PRO_API_KEY), id="TzProBlockApiImpl"
),
],
)
def test_address_is_not_baker_address(block_api):
Expand Down Expand Up @@ -80,7 +85,9 @@ def test_address_is_not_baker_address(block_api):
[
pytest.param(RpcBlockApiImpl(network, node_endpoint), id="RpcBlockApiImpl"),
pytest.param(TzKTBlockApiImpl(network), id="TzKTBlockApiImpl"),
pytest.param(TzProBlockApiImpl(network), id="TzProBlockApiImpl"),
pytest.param(
TzProBlockApiImpl(network, TZ_PRO_API_KEY), id="TzProBlockApiImpl"
),
],
)
def test_invalid_baking_address(block_api):
Expand Down
Loading

1 comment on commit 3941155

@jdsika
Copy link
Contributor

@jdsika jdsika commented on 3941155 Nov 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

Please sign in to comment.