From dae2168d8f19d166e5029d017beadc3d76ba0a45 Mon Sep 17 00:00:00 2001 From: Jon Michael Aanes Date: Sun, 13 Apr 2025 01:19:47 +0200 Subject: [PATCH] Ruff --- pbc_client/__init__.py | 102 ++++++++++++++++++++++++++-------------- pbc_client/pbc_types.py | 32 +++++++------ test/test_init.py | 2 +- 3 files changed, 86 insertions(+), 50 deletions(-) diff --git a/pbc_client/__init__.py b/pbc_client/__init__.py index 9b3fc94..e3c7d3b 100644 --- a/pbc_client/__init__.py +++ b/pbc_client/__init__.py @@ -1,31 +1,37 @@ -""" # Partisia Blockchain Client +"""# Partisia Blockchain Client Unofficial library for reading contract states from Partisia Blockchain. This library is not officially associated with Partisia Blockchain nor Partisia Group ApS. """ + +import base64 import dataclasses import datetime -import base64 import email.utils +import hashlib import json import logging -import ecdsa -import hashlib -import pbcabi -from collections.abc import Mapping import time +from collections.abc import Mapping from decimal import Decimal from typing import Any +import ecdsa +import pbcabi import requests from frozendict import frozendict -from .pbc_types import (Address, Signature, HashSha256, Transaction, -SignedTransaction, SignedTransactionInnerPart) - -from ._version import __version__ #noqa: F401 +from ._version import __version__ # noqa: F401 +from .pbc_types import ( + Address, + HashSha256, + Signature, + SignedTransaction, + SignedTransactionInnerPart, + Transaction, +) logger = logging.getLogger(__name__) @@ -62,12 +68,15 @@ class Balances: mpc: Decimal byoc: Mapping[str, Decimal] + @dataclasses.dataclass(frozen=True) class SenderAuthentication: secret_key: str def sender_address(self) -> Address: - verifying_key_repr = self._signing_key().get_verifying_key().to_string("uncompressed") + verifying_key_repr = ( + self._signing_key().get_verifying_key().to_string('uncompressed') + ) hashed = HashSha256.of_bytes(verifying_key_repr) return Address(b'\0' + hashed._bytes[-20:]) @@ -76,10 +85,15 @@ class SenderAuthentication: def _signing_key(self): secret_exponent = int(self.secret_key, 16) - return ecdsa.SigningKey.from_secret_exponent(secret_exponent , curve=ecdsa.SECP256k1) + return ecdsa.SigningKey.from_secret_exponent( + secret_exponent, + curve=ecdsa.SECP256k1, + ) + TRANSACTION_VALIDITY_DURATION = 60 + def sign_transaction( sender_authentication: SenderAuthentication, nonce: int, @@ -91,16 +105,17 @@ def sign_transaction( sender = sender_authentication.sender_address valid_to_time: int = int(time.time() + TRANSACTION_VALIDITY_DURATION) * 1000 - inner: SignedTransactionInnerPart = SignedTransactionInnerPart(nonce, - valid_to_time, - gas_cost, - Transaction(Address.from_string(contract_address), - transaction_rpc)) + inner: SignedTransactionInnerPart = SignedTransactionInnerPart( + nonce, + valid_to_time, + gas_cost, + Transaction(Address.from_string(contract_address), transaction_rpc), + ) transaction_hash_bytes = inner.rpc_serialize() + chain_id.encode('utf8') transaction_hash: HashSha256 = HashSha256.of_bytes(transaction_hash_bytes) - signature : Signature = sender_authentication.sign_hash(transaction_hash) + signature: Signature = sender_authentication.sign_hash(transaction_hash) return SignedTransaction(inner, signature, transaction_hash) @@ -117,29 +132,38 @@ class PbcClient: if self.sender_authentication is not None: assert isinstance(self.sender_authentication, SenderAuthentication) - def send_transaction(self, contract_address: str, rpc: bytes, gas_cost: int): if self.sender_authentication is None: - msg = "PbcClient.sender_authentication required for send_transaction" + msg = 'PbcClient.sender_authentication required for send_transaction' raise Exception(msg) - signed_transaction = sign_transaction(self.sender_authentication, - self.get_sender_authentication_nonce(), - gas_cost, - self.get_chain_id(), - contract_address, rpc) + signed_transaction = sign_transaction( + self.sender_authentication, + self.get_sender_authentication_nonce(), + gas_cost, + self.get_chain_id(), + contract_address, + rpc, + ) return self.send_signed_transaction(signed_transaction) def send_signed_transaction(self, signed_transaction: SignedTransaction): url = URL_TRANSACTION.format( hostname=self.hostname, - shard=shard_id_for_address(signed_transaction.inner.transaction.contract_address), + shard=shard_id_for_address( + signed_transaction.inner.transaction.contract_address, + ), ) - transaction_payload: str = base64.b64encode(signed_transaction.rpc_serialize()).decode('utf8') - self._get_json(url, data = {'transactionPayload':transaction_payload }, method = 'PUT') - + transaction_payload: str = base64.b64encode( + signed_transaction.rpc_serialize(), + ).decode('utf8') + self._get_json( + url, + data={'transactionPayload': transaction_payload}, + method='PUT', + ) def _get_json( self, @@ -226,7 +250,6 @@ class PbcClient: ) return self._get_json(url, method='GET')[0]['nonce'] - def get_contract_state(self, address: str) -> tuple[dict, datetime.datetime]: # TODO: Rename to get_contract_state_json url = URL_CONTRACT_STATE.format( @@ -244,11 +267,15 @@ class PbcClient: file_abi = self.get_contract_abi(address) state, server_time = self.get_contract_state(address) state_bytes = base64.b64decode(state['state']['data']) - state_deserialized = file_abi.contract.read_state(state_bytes) + state_deserialized = file_abi.contract.read_state(state_bytes) return state_deserialized, server_time - def get_typed_contract_avl_tree(self, address: str, avl_tree_id: pbcabi.model.AvlTreeId) -> tuple[dict, datetime.datetime]: + def get_typed_contract_avl_tree( + self, + address: str, + avl_tree_id: pbcabi.model.AvlTreeId, + ) -> tuple[dict, datetime.datetime]: file_abi = self.get_contract_abi(address) state, server_time = self.get_contract_state(address) for avl_tree in state['avlTrees']: @@ -260,8 +287,14 @@ class PbcClient: key_bytes = base64.b64decode(key_and_value['key']['data']['data']) value_bytes = base64.b64decode(key_and_value['value']['data']) - key = file_abi.contract.read_state(key_bytes, avl_tree_id.type_spec.type_key) - value = file_abi.contract.read_state(value_bytes, avl_tree_id.type_spec.type_value) + key = file_abi.contract.read_state( + key_bytes, + avl_tree_id.type_spec.type_key, + ) + value = file_abi.contract.read_state( + value_bytes, + avl_tree_id.type_spec.type_value, + ) data[key] = value @@ -269,7 +302,6 @@ class PbcClient: return data, server_time - def get_contract_abi(self, address: str) -> pbcabi.model.FileAbi: url = URL_CONTRACT_STATE.format( hostname=self.hostname, diff --git a/pbc_client/pbc_types.py b/pbc_client/pbc_types.py index ba27ddf..b6941d6 100644 --- a/pbc_client/pbc_types.py +++ b/pbc_client/pbc_types.py @@ -1,22 +1,11 @@ import dataclasses -import datetime -import base64 -import email.utils -import json -import logging import hashlib -import pbcabi -from collections.abc import Mapping -import time -from decimal import Decimal -from typing import Any def size_prefixed(_bytes: bytes) -> bytes: return len(_bytes).to_bytes(4, 'big') + _bytes - @dataclasses.dataclass(frozen=True) class Address: _bytes: bytes @@ -50,6 +39,7 @@ class Signature: def __str__(self) -> str: return self._bytes.hex() + @dataclasses.dataclass(frozen=True) class HashSha256: _bytes: bytes @@ -67,6 +57,7 @@ class HashSha256: def __str__(self) -> str: return self._bytes.hex() + @dataclasses.dataclass(frozen=True) class Transaction: contract_address: Address @@ -76,7 +67,10 @@ class Transaction: assert isinstance(self.contract_address, Address), self.contract_address def rpc_serialize(self) -> bytes: - return self.contract_address.rpc_serialize() + size_prefixed(self.transaction_rpc) + return self.contract_address.rpc_serialize() + size_prefixed( + self.transaction_rpc, + ) + @dataclasses.dataclass(frozen=True) class SignedTransactionInnerPart: @@ -86,7 +80,13 @@ class SignedTransactionInnerPart: transaction: Transaction def rpc_serialize(self) -> bytes: - return self.nonce.to_bytes(4, 'big') + self.valid_to_time.to_bytes(8, 'big') + self.gas_cost.to_bytes(8, 'big') + self.transaction.rpc_serialize() + return ( + self.nonce.to_bytes(4, 'big') + + self.valid_to_time.to_bytes(8, 'big') + + self.gas_cost.to_bytes(8, 'big') + + self.transaction.rpc_serialize() + ) + @dataclasses.dataclass(frozen=True) class SignedTransaction: @@ -95,4 +95,8 @@ class SignedTransaction: hash: HashSha256 def rpc_serialize(self) -> bytes: - return self.inner.rpc_serialize() + self.signature.rpc_serialize() + self.hash.rpc_serialize() + return ( + self.inner.rpc_serialize() + + self.signature.rpc_serialize() + + self.hash.rpc_serialize() + ) diff --git a/test/test_init.py b/test/test_init.py index 95640db..3df0c58 100644 --- a/test/test_init.py +++ b/test/test_init.py @@ -1,2 +1,2 @@ def test_init(): - import pbc_client #noqa: F401 + import pbc_client # noqa: F401