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

Integrate skale-contracts library #555

Merged
merged 19 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ jobs:
PIP_USERNAME: ${{ secrets.PIP_USERNAME }}
PIP_PASSWORD: ${{ secrets.PIP_PASSWORD }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
uses: actions/setup-python@v4
with:
cache: 'pip'
python-version: ${{ matrix.python-version }}
- name: Install host dependencies
run: |
Expand Down
20 changes: 11 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ jobs:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
MANAGER_TAG: "1.10.0-v1.10.0.0"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
submodules: true
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
uses: actions/setup-python@v4
with:
cache: 'pip'
python-version: ${{ matrix.python-version }}

- name: Install python dependencies
Expand All @@ -30,7 +31,7 @@ jobs:
- name: Launch hardhat node
working-directory: hardhat-node
run: |
docker-compose up -d && sleep 20
docker-compose up -d && sleep 20

- name: Deploy manager
run: |
Expand All @@ -39,7 +40,7 @@ jobs:

- name: Show stats before tests
if: always()
run: |
run: |
sudo lsblk -f
sudo free -h

Expand All @@ -52,7 +53,7 @@ jobs:

- name: Show stats after tests
if: always()
run: |
run: |
sudo lsblk -f
sudo free -h

Expand All @@ -67,13 +68,14 @@ jobs:
MANAGER_TAG: "1.9.0-develop.20"
ALLOCATOR_TAG: "2.2.2-develop.0"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
submodules: true

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
uses: actions/setup-python@v4
with:
cache: 'pip'
python-version: ${{ matrix.python-version }}

- name: Install host dependencies
Expand All @@ -85,7 +87,7 @@ jobs:
- name: Launch hardhat node
working-directory: hardhat-node
run: |
docker-compose up -d && sleep 20
docker-compose up -d && sleep 20

- name: Deploy manager contracts
run: |
Expand All @@ -103,6 +105,6 @@ jobs:

- name: Show stats after tests
if: always()
run: |
run: |
sudo lsblk -f
sudo free -h
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

setup(
name='skale.py',
version='6.2',
version='7',
description='SKALE client tools',
long_description_markdown_filename='README.md',
author='SKALE Labs',
Expand All @@ -43,8 +43,9 @@
install_requires=[
"asyncio==3.4.3",
"pyyaml==6.0",
"sgx.py==0.9dev2",
"redis==4.4.4",
"sgx.py==0.9dev2",
"skale-contracts==1.0.1a5",
"typing-extensions==4.9.0",
"web3==6.13.0"
],
Expand Down
8 changes: 3 additions & 5 deletions skale/contracts/allocator/escrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
def beneficiary_escrow(transaction):
@functools.wraps(transaction)
def wrapper(self, *args, beneficiary_address, **kwargs):
self.contract = self.init_beneficiary_contract(beneficiary_address)
self.contract = self.skale.instance.get_contract('Escrow', beneficiary_address)

Check warning on line 30 in skale/contracts/allocator/escrow.py

View check run for this annotation

Codecov / codecov/patch

skale/contracts/allocator/escrow.py#L30

Added line #L30 was not covered by tests
return transaction(self, *args, **kwargs)
return wrapper

Expand All @@ -38,10 +38,8 @@
def allocator(self):
return self.skale.allocator

def init_beneficiary_contract(self, beneficiary_address: str):
beneficiary_escrow_address = self.allocator.get_escrow_address(beneficiary_address)
return Escrow(self.skale, f'escrow_{beneficiary_address}', beneficiary_escrow_address,
self.contract.abi).contract
def init_contract(self, skale, address, abi) -> None:
self.contract = None

Check warning on line 42 in skale/contracts/allocator/escrow.py

View check run for this annotation

Codecov / codecov/patch

skale/contracts/allocator/escrow.py#L42

Added line #L42 was not covered by tests

@beneficiary_escrow
@transaction_method
Expand Down
5 changes: 4 additions & 1 deletion skale/contracts/base_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,10 @@ def __init__(self, skale, name, address, abi):
self.skale = skale
self.name = name
self.address = Web3.to_checksum_address(address)
self.contract = skale.web3.eth.contract(address=self.address, abi=abi)
self.init_contract(skale, address, abi)

def init_contract(self, skale, address, abi) -> None:
self.contract = skale.web3.eth.contract(address=address, abi=abi)

def __getattr__(self, attr):
"""Fallback for contract calls"""
Expand Down
17 changes: 16 additions & 1 deletion skale/skale_allocator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with SKALE.py. If not, see <https://www.gnu.org/licenses/>.
from __future__ import annotations

import logging
from typing import TYPE_CHECKING
from web3.constants import ADDRESS_ZERO

from skale.skale_base import SkaleBase
import skale.contracts.allocator as contracts
Expand All @@ -26,6 +29,9 @@
from skale.utils.contract_types import ContractTypes
from skale.utils.helper import get_contracts_info

if TYPE_CHECKING:
from eth_typing import ChecksumAddress

Check warning on line 33 in skale/skale_allocator.py

View check run for this annotation

Codecov / codecov/patch

skale/skale_allocator.py#L33

Added line #L33 was not covered by tests


logger = logging.getLogger(__name__)

Expand All @@ -45,6 +51,15 @@


class SkaleAllocator(SkaleBase):
"""Represents skale-allocator smart contracts"""
@property
def project_name(self) -> str:
return 'skale-allocator'

Check warning on line 57 in skale/skale_allocator.py

View check run for this annotation

Codecov / codecov/patch

skale/skale_allocator.py#L57

Added line #L57 was not covered by tests

def get_contract_address(self, name) -> ChecksumAddress:
if name == 'Escrow':
return ADDRESS_ZERO
return super().get_contract_address(name)

Check warning on line 62 in skale/skale_allocator.py

View check run for this annotation

Codecov / codecov/patch

skale/skale_allocator.py#L60-L62

Added lines #L60 - L62 were not covered by tests

def set_contracts_info(self):
self.init_contract_manager()
self._SkaleBase__contracts_info = get_contracts_info(CONTRACTS_INFO)
75 changes: 47 additions & 28 deletions skale/skale_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,23 @@
# You should have received a copy of the GNU Affero General Public License
# along with SKALE.py. If not, see <https://www.gnu.org/licenses/>.

from __future__ import annotations

import abc
import logging
from typing import TYPE_CHECKING

from skale_contracts import skale_contracts

from skale.wallets import BaseWallet
from skale.utils.abi_utils import get_contract_address_by_name, get_contract_abi_by_name
from skale.utils.exceptions import InvalidWalletError, EmptyWalletError
from skale.utils.web3_utils import default_gas_price, init_web3

from skale.utils.helper import get_abi
from skale.contracts.contract_manager import ContractManager

if TYPE_CHECKING:
from eth_typing import Address, ChecksumAddress

Check warning on line 35 in skale/skale_base.py

View check run for this annotation

Codecov / codecov/patch

skale/skale_base.py#L35

Added line #L35 was not covered by tests


logger = logging.getLogger(__name__)

Expand All @@ -39,23 +45,30 @@
class SkaleBase:
__metaclass__ = abc.ABCMeta

def __init__(self, endpoint, abi_filepath,
def __init__(self, endpoint, alias_or_address: str,
wallet=None, state_path=None,
ts_diff=None, provider_timeout=30):
logger.info(f'Initing skale.py, endpoint: {endpoint}, '
f'wallet: {type(wallet).__name__}')
self._abi_filepath = abi_filepath
logger.info('Initializing skale.py, endpoint: %s, wallet: %s',
endpoint, type(wallet).__name__)
self._endpoint = endpoint
self.web3 = init_web3(endpoint,
state_path=state_path,
ts_diff=ts_diff,
provider_timeout=provider_timeout)
self.network = skale_contracts.get_network_by_provider(self.web3.provider)
self.project = self.network.get_project(self.project_name)
self.instance = self.project.get_instance(alias_or_address)
self.__contracts = {}
self.__contracts_info = {}
self.set_contracts_info()
if wallet:
self.wallet = wallet

@property
@abc.abstractmethod
def project_name(self) -> str:
"""Name of smart contracts project"""

@property
def gas_price(self):
return default_gas_price(self.web3)
Expand All @@ -82,46 +95,52 @@
return

def init_contract_manager(self):
abi = get_abi(self._abi_filepath)
self.add_lib_contract('contract_manager', ContractManager, abi)
self.add_lib_contract('contract_manager', ContractManager, 'ContractManager')

def __init_contract_from_info(self, abi, contract_info):
def __init_contract_from_info(self, contract_info):
if contract_info.upgradeable:
self.init_upgradeable_contract(contract_info, abi)
self.init_upgradeable_contract(contract_info)
else:
self.add_lib_contract(contract_info.name, contract_info.contract_class,
abi)
self.add_lib_contract(
contract_info.name,
contract_info.contract_class,
contract_info.contract_name
)

def init_upgradeable_contract(self, contract_info, abi):
def init_upgradeable_contract(self, contract_info):
address = self.get_contract_address(contract_info.contract_name)
self.add_lib_contract(contract_info.name, contract_info.contract_class,
abi, address)

def add_lib_contract(self, name, contract_class,
abi, contract_address=None):
address = contract_address or get_contract_address_by_name(
abi, name)
logger.debug(f'Fetching abi for {name}, address {address}')
contract_abi = get_contract_abi_by_name(abi, name)
self.add_lib_contract(
contract_info.name,
contract_info.contract_class,
contract_info.contract_name,
address
)

def add_lib_contract(self, name: str, contract_class,
contract_name: str, contract_address: Address = None):
address = contract_address or self.instance.get_contract_address(contract_name)
logger.debug('Fetching abi for %s, address %s', name, address)
contract_abi = self.instance.abi[contract_name]
self.add_contract(name, contract_class(
self, name, address, contract_abi))

def add_contract(self, name, contract):
self.__contracts[name] = contract

def get_contract_address(self, name):
return self.contract_manager.get_contract_address(name)
def get_contract_address(self, name) -> ChecksumAddress:
return self.web3.to_checksum_address(
self.instance.get_contract_address(name)
)

def __get_contract_by_name(self, name):
return self.__contracts[name]

def __getattr__(self, name):
if name not in self.__contracts:
if not self.__contracts_info.get(name):
logger.warning(f'{name} method/contract wasn\'t found')
logger.warning("%s method/contract wasn't found", name)
return None
logger.debug(f'Contract {name} wasn\'t inited, creating now')
logger.debug("Contract %s wasn't inited, creating now", name)
contract_info = self.__contracts_info[name]
abi = get_abi(self._abi_filepath)
self.__init_contract_from_info(abi, contract_info)
self.__init_contract_from_info(contract_info)
return self.__get_contract_by_name(name)
21 changes: 8 additions & 13 deletions skale/skale_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from skale.contracts.contract_manager import ContractManager
from skale.utils.contract_info import ContractInfo
from skale.utils.contract_types import ContractTypes
from skale.utils.helper import get_abi, get_contracts_info
from skale.utils.helper import get_contracts_info


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -60,21 +60,16 @@
ContractTypes.API, False),
ContractInfo('distributor', 'Distributor', contracts.Distributor,
ContractTypes.API, False),
ContractInfo('slashing_table', 'Distributor', contracts.SlashingTable,
ContractInfo('slashing_table', 'SlashingTable', contracts.SlashingTable,
ContractTypes.API, False),
ContractInfo('wallets', 'Wallets', contracts.Wallets,
ContractTypes.API, True),
ContractInfo('bounty_v2', 'Bounty', contracts.BountyV2,
ContractInfo('bounty_v2', 'BountyV2', contracts.BountyV2,
ContractTypes.API, True),
ContractInfo('punisher', 'Punisher', contracts.Punisher,
ContractTypes.API, True),
ContractInfo('sync_manager', 'SyncManager', contracts.SyncManager,
ContractTypes.API, False),
]


DEBUG_CONTRACTS_INFO = [

ContractInfo('time_helpers_with_debug', 'TimeHelpersWithDebug', contracts.TimeHelpersWithDebug,
ContractTypes.API, False)
]
Expand All @@ -86,11 +81,11 @@ def spawn_skale_manager_lib(skale):


class SkaleManager(SkaleBase):
"""Represents skale-manager smart contracts"""
@property
def project_name(self) -> str:
return 'skale-manager'

def set_contracts_info(self):
self.init_contract_manager()
abi = get_abi(self._abi_filepath)
self._SkaleBase__contracts_info = get_contracts_info(CONTRACTS_INFO)
if self._SkaleBase__is_debug_contracts(abi):
logger.info('Debug contracts found in ABI file')
self._SkaleBase__contracts_info.update(
get_contracts_info(DEBUG_CONTRACTS_INFO))
Loading
Loading