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

Introduce mypy type checking #17

Merged
merged 14 commits into from
Sep 13, 2021
7 changes: 2 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
SHELL := /bin/bash

.PHONY: test test37 test38 test39 mypy coverage
.PHONY: test test38 test39 mypy coverage

TOX := docker-compose run --rm app tox

test:
$(TOX)


test37:
$(TOX) -e py37

test38:
$(TOX) -e py38

Expand All @@ -27,4 +24,4 @@ coverage: .coverage
docker-compose run --rm app coverage report

coverage.xml: .coverage
docker-compose run --rm app coverage xml
docker-compose run --rm app coverage xml
19 changes: 16 additions & 3 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ install_requires =
web3 >= 5.16
httpx >= 0.16
pydantic >= 1.7

python_requires = >=3.8
setup_requires =
setuptools_scm>=3.5.0

Expand All @@ -36,8 +36,21 @@ zksync_sdk.contract_abi =
[tox:tox]
envlist = py{38,39},mypy

[testenv]
[testenv:py{38,39}]
deps = coverage
extras = test
setenv = ZK_SYNC_LIBRARY_PATH=/lib/zks-crypto-linux-x64.so
commands = coverage run -m unittest

[testenv:mypy]
extras = test
commands = mypy .

[mypy]
show_error_codes = True
no_implicit_optional = True

[mypy-setuptools.*]
ignore_missing_imports = True

[mypy-eth_account.*]
ignore_missing_imports = True
6 changes: 1 addition & 5 deletions zksync_sdk/contract_utils.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import importlib.resources as pkg_resources
import json

try:
import importlib.resources as pkg_resources
except ImportError:
# Try backported to PY<37 `importlib_resources`.
import importlib_resources as pkg_resources
from . import contract_abi

zksync_abi_cache = None
Expand Down
5 changes: 3 additions & 2 deletions zksync_sdk/ethereum_provider.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from decimal import Decimal
from typing import Optional

from web3 import Web3

Expand All @@ -13,7 +14,7 @@ def __init__(self, web3: Web3, zksync: ZkSync):
self.web3 = web3
self.zksync = zksync

async def approve_deposit(self, token: Token, limit: Decimal = None):
async def approve_deposit(self, token: Token, limit: Decimal):
contract = ERC20Contract(self.web3, self.zksync.contract_address, token.address,
self.zksync.account)
return contract.approve_deposit(token.from_decimal(limit))
Expand All @@ -30,7 +31,7 @@ async def full_exit(self, token: Token, account_id: int):
async def set_auth_pubkey_hash(self, pubkey_hash: bytes, nonce: int):
return self.zksync.set_auth_pub_key_hash(pubkey_hash, nonce)

async def is_deposit_approved(self, token: Token, threshold: int = None) -> bool:
async def is_deposit_approved(self, token: Token, threshold: int) -> bool:
contract = ERC20Contract(self.web3, self.zksync.contract_address, token.address,
self.zksync.account)
return contract.is_deposit_approved(threshold)
Expand Down
13 changes: 7 additions & 6 deletions zksync_sdk/lib.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ctypes
from ctypes import (Structure, c_ubyte, cdll)
import os
from typing import Optional

PRIVATE_KEY_LEN = 32
PUBLIC_KEY_LEN = 32
Expand Down Expand Up @@ -48,9 +49,9 @@ class ZksOrders(Structure):

class ZkSyncLibrary:

def __init__(self, library_path: str = None):
def __init__(self, library_path: Optional[str] = None):
if library_path is None:
library_path = os.getenv("ZK_SYNC_LIBRARY_PATH")
library_path = os.environ["ZK_SYNC_LIBRARY_PATH"]
self.lib = cdll.LoadLibrary(library_path)

def private_key_from_seed(self, seed: bytes):
Expand All @@ -68,17 +69,17 @@ def get_public_key(self, private_key: bytes):
def get_pubkey_hash(self, public_key: bytes):
assert len(public_key) == PUBLIC_KEY_LEN
public_key_hash = ctypes.pointer(ZksPubkeyHash())
public_key = ctypes.pointer(
public_key_ptr = ctypes.pointer(
ZksPackedPublicKey(data=(c_ubyte * PUBLIC_KEY_LEN)(*public_key)))
self.lib.zks_crypto_public_key_to_pubkey_hash(public_key, public_key_hash)
self.lib.zks_crypto_public_key_to_pubkey_hash(public_key_ptr, public_key_hash)
return bytes(public_key_hash.contents.data)

def sign(self, private_key: bytes, message: bytes):
assert len(private_key) == PRIVATE_KEY_LEN
signature = ctypes.pointer(ZksSignature())
private_key = ctypes.pointer(
private_key_ptr = ctypes.pointer(
ZksPrivateKey(data=(c_ubyte * PRIVATE_KEY_LEN)(*private_key)))
self.lib.zks_crypto_sign_musig(private_key, message, len(message), signature)
self.lib.zks_crypto_sign_musig(private_key_ptr, message, len(message), signature)
return bytes(signature.contents.data)

def hash_orders(self, orders: bytes):
Expand Down
2 changes: 2 additions & 0 deletions zksync_sdk/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ def remove_address_prefix(address: str) -> str:
if address.startswith('sync:'):
return address[5:]

return address


def serialize_address(address: str) -> bytes:
address = remove_address_prefix(address)
Expand Down
4 changes: 2 additions & 2 deletions zksync_sdk/transport/http.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from http.client import OK
from typing import List
from typing import List, Optional

import httpx

Expand All @@ -11,7 +11,7 @@ class HttpJsonRPCTransport(JsonRPCTransport):
def __init__(self, network: Network):
self.network = network

async def request(self, method: str, params: List):
async def request(self, method: str, params: Optional[List]):
async with httpx.AsyncClient() as client:
response = await client.post(self.network.zksync_url,
json=self.create_request(method, params))
Expand Down
1 change: 1 addition & 0 deletions zksync_sdk/types/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class Config:
alias_generator = to_camel

def get_nonce(self) -> int:
assert self.committed is not None, "`get_nonce` needs `committed` to be set"
return self.committed.nonce


Expand Down
31 changes: 17 additions & 14 deletions zksync_sdk/types/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def find_by_symbol(self, symbol: str) -> Optional[Token]:
else:
return None

def find(self, token: TokenLike) -> Token:
def find(self, token: TokenLike) -> Optional[Token]:
result = None
if isinstance(token, int):
result = self.find_by_id(token)
Expand Down Expand Up @@ -167,9 +167,9 @@ class ChangePubKey(EncodedTx):
nonce: int
valid_from: int
valid_until: int
eth_auth_data: Union[ChangePubKeyCREATE2, ChangePubKeyEcdsa] = None
eth_signature: TxEthSignature = None
signature: TxSignature = None
eth_auth_data: Union[ChangePubKeyCREATE2, ChangePubKeyEcdsa, None] = None
eth_signature: Optional[TxEthSignature] = None
signature: Optional[TxSignature] = None

def human_readable_message(self) -> str:
message = f"Set signing key: {self.new_pk_hash.replace('sync:', '').lower()}"
Expand Down Expand Up @@ -240,7 +240,7 @@ class Transfer(EncodedTx):
nonce: int
valid_from: int
valid_until: int
signature: TxSignature = None
signature: Optional[TxSignature] = None

def tx_type(self) -> int:
return 5
Expand Down Expand Up @@ -297,7 +297,7 @@ class Withdraw(EncodedTx):
valid_from: int
valid_until: int
token: Token
signature: TxSignature = None
signature: Optional[TxSignature] = None

def tx_type(self) -> int:
return 3
Expand Down Expand Up @@ -351,7 +351,7 @@ class ForcedExit(EncodedTx):
nonce: int
valid_from: int
valid_until: int
signature: TxSignature = None
signature: Optional[TxSignature] = None

def tx_type(self) -> int:
return 8
Expand Down Expand Up @@ -387,7 +387,7 @@ def dict(self):
}

@dataclass
class Order:
class Order(EncodedTx):
account_id: int
recipient: str
nonce: int
Expand All @@ -397,8 +397,11 @@ class Order:
ratio: Fraction
valid_from: int
valid_until: int
signature: TxSignature = None
ethSignature: TxEthSignature = None
signature: Optional[TxSignature] = None
eth_signature: Optional[TxEthSignature] = None

def tx_type(self) -> int:
raise NotImplementedError

def msg_type(self) -> int:
return b'o'[0]
Expand Down Expand Up @@ -446,7 +449,7 @@ def dict(self):
"validFrom": self.valid_from,
"validUntil": self.valid_until,
"signature": self.signature.dict() if self.signature else None,
"ethSignature": self.ethSignature.dict() if self.ethSignature else None,
"ethSignature": self.eth_signature.dict() if self.eth_signature else None,
}

@dataclass
Expand All @@ -458,7 +461,7 @@ class Swap(EncodedTx):
fee_token: Token
fee: int
nonce: int
signature: TxSignature = None
signature: Optional[TxSignature] = None

def tx_type(self) -> int:
return 11
Expand Down Expand Up @@ -511,7 +514,7 @@ class MintNFT(EncodedTx):
fee: int
fee_token: Token
nonce: int
signature: TxSignature = None
signature: Optional[TxSignature] = None

def tx_type(self) -> int:
return 9
Expand Down Expand Up @@ -557,7 +560,7 @@ class WithdrawNFT(EncodedTx):
valid_from: int
valid_until: int
token_id: int
signature: TxSignature = None
signature: Optional[TxSignature] = None

def tx_type(self) -> int:
return 10
Expand Down
Loading