Skip to content

Commit 027e549

Browse files
Merge pull request #18 from ElrondNetwork/testnet-and-typing-fixes
Testnet and typing fixes
2 parents 4880527 + 289acb4 commit 027e549

42 files changed

Lines changed: 519 additions & 292 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ __pycache__
55
*.py[cod]
66
*$py.class
77
.pytest_cache/
8+
erdpy/tests/testdata-out
89

910
# mypy
1011
.mypy_cache/

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ build-erdpy: clean
66

77
publish-erdpy: build-erdpy
88
twine upload dist/*
9+
10+
test:
11+
python3 -m unittest discover -s erdpy/tests
12+
pytest ./erdpy/tests/test_testnet.py -s
13+
source ./erdpy/tests/test_cli_all.sh && testAll || return 1

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ Elrond Python Command Line Tools and SDK for interacting with the Elrond Network
55
[docs.elrond.com](https://docs.elrond.com/sdk-and-tools/erdpy/erdpy/)
66

77
## CLI
8-
[CLI](CLI.md)
8+
[CLI](erdpy/CLI.md)
99

1010
## Distribution
1111
[erdpy-up](https://docs.elrond.com/sdk-and-tools/erdpy/installing-erdpy/) and [PyPi](https://pypi.org/project/erdpy/#history)
1212

1313
## CHANGELOG
14-
[CHANGELOG](CHANGELOG.md)
14+
[CHANGELOG](erdpy/CHANGELOG.md)

erdpy/accounts.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import os
33
from binascii import unhexlify
44
from os import path
5-
from typing import Any, Union
5+
from typing import Any, Optional
66

77
from erdpy import constants, errors, utils
88
from erdpy.errors import LedgerError
@@ -45,15 +45,20 @@ def get_all(self):
4545

4646

4747
class Account(IAccount):
48-
def __init__(self, address: Any = None, pem_file: Union[str, None] = None, pem_index: int = 0, key_file: str = "", pass_file: str = "",
48+
def __init__(self,
49+
address: Any = None,
50+
pem_file: Optional[str] = None,
51+
pem_index: int = 0,
52+
key_file: str = "",
53+
pass_file: str = "",
4954
ledger: bool = False):
5055
self.address = Address(address)
5156
self.pem_file = pem_file
5257
self.pem_index = int(pem_index)
5358
self.nonce: int = 0
5459
self.ledger = ledger
5560

56-
if pem_file:
61+
if self.pem_file:
5762
seed, pubkey = pem.parse(self.pem_file, self.pem_index)
5863
self.private_key_seed = seed.hex()
5964
self.address = Address(pubkey)
@@ -79,9 +84,10 @@ class Address(IAddress):
7984
PUBKEY_LENGTH = 32
8085
PUBKEY_STRING_LENGTH = PUBKEY_LENGTH * 2 # hex-encoded
8186
BECH32_LENGTH = 62
87+
_value_hex: str
8288

8389
def __init__(self, value):
84-
self._value_hex = None
90+
self._value_hex = ''
8591

8692
if not value:
8793
return
@@ -107,7 +113,9 @@ def hex(self) -> str:
107113
def bech32(self) -> str:
108114
self._assert_validity()
109115
pubkey = self.pubkey()
110-
return bech32.bech32_encode(self.HRP, bech32.convertbits(pubkey, 8, 5))
116+
b32 = bech32.bech32_encode(self.HRP, bech32.convertbits(pubkey, 8, 5))
117+
assert isinstance(b32, str)
118+
return b32
111119

112120
def pubkey(self):
113121
self._assert_validity()
@@ -118,7 +126,7 @@ def is_contract_address(self):
118126
return self.hex().startswith(constants.SC_HEX_PUBKEY_PREFIX)
119127

120128
def _assert_validity(self):
121-
if self._value_hex is None:
129+
if self._value_hex == '':
122130
raise errors.EmptyAddressError()
123131

124132
def __repr__(self):

erdpy/cli_contracts.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import os
33
from typing import Any
44

5+
from pathlib import Path
6+
57
from erdpy import cli_shared, errors, projects, utils
68
from erdpy.accounts import Account, Address
79
from erdpy.contracts import CodeMetadata, SmartContract
@@ -110,8 +112,10 @@ def _add_project_arg(sub: Any):
110112

111113
def _add_project_or_bytecode_arg(sub: Any):
112114
group = sub.add_mutually_exclusive_group(required=True)
113-
group.add_argument("--project", default=os.getcwd(), help="🗀 the project directory (default: current directory)")
114-
group.add_argument("--bytecode", help="the WASM file")
115+
group.add_argument("--project", default=os.getcwd(),
116+
help="🗀 the project directory (default: current directory)")
117+
group.add_argument("--bytecode", type=str,
118+
help="the file containing the WASM bytecode")
115119

116120

117121
def _add_contract_arg(sub: Any):
@@ -217,8 +221,8 @@ def dump_tx_and_result(tx: Any, result: Any, args: Any):
217221

218222

219223
def _prepare_contract(args: Any) -> SmartContract:
220-
if args.bytecode:
221-
bytecode = utils.read_file(args.bytecode, binary=True).hex()
224+
if len(args.bytecode):
225+
bytecode = utils.read_binary_file(Path(args.bytecode)).hex()
222226
else:
223227
project = load_project(args.project)
224228
bytecode = project.get_bytecode()

erdpy/config.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ def get_dependency_url(key: str, tag: str, platform: str) -> str:
5454
def get_value(name: str) -> str:
5555
_guard_valid_name(name)
5656
data = get_active()
57-
return data.get(name, get_defaults()[name])
57+
value = data.get(name, get_defaults()[name])
58+
assert isinstance(value, str)
59+
return value
5860

5961

6062
def set_value(name: str, value: Any):
@@ -133,6 +135,7 @@ def get_defaults() -> Dict[str, Any]:
133135
"chainID": "T",
134136
"txVersion": "1",
135137
"dependencies.arwentools.tag": "v1.1.2",
138+
"dependencies.elrond_wasm_rs.tag": "v0.12.0",
136139
"dependencies.arwentools.urlTemplate.linux": "https://github.com/ElrondNetwork/arwen-wasm-vm/archive/{TAG}.tar.gz",
137140
"dependencies.arwentools.urlTemplate.osx": "https://github.com/ElrondNetwork/arwen-wasm-vm/archive/{TAG}.tar.gz",
138141
"dependencies.llvm.tag": "v9-19feb",
@@ -155,7 +158,6 @@ def get_defaults() -> Dict[str, Any]:
155158
"dependencies.mcl_signer.tag": "v1.0.0",
156159
"dependencies.mcl_signer.urlTemplate.linux": "https://github.com/ElrondNetwork/elrond-sdk-go-tools/releases/download/{TAG}/mcl_signer_{TAG}_ubuntu-latest.tar.gz",
157160
"dependencies.mcl_signer.urlTemplate.osx": "https://github.com/ElrondNetwork/elrond-sdk-go-tools/releases/download/{TAG}/mcl_signer_{TAG}_macos-latest.tar.gz",
158-
"dependencies.elrond_wasm_rs.tag": "v0.10.2",
159161
}
160162

161163

erdpy/contracts.py

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,22 @@
44

55
from Cryptodome.Hash import keccak
66

7-
from erdpy import config, constants, errors, utils
7+
from erdpy import config, constants, errors
88
from erdpy.accounts import Account, Address
99
from erdpy.interfaces import IElrondProxy
1010
from erdpy.transactions import Transaction
1111

1212
logger = logging.getLogger("contracts")
1313

14+
HEX_PREFIX = "0X"
15+
16+
17+
class QueryResult:
18+
def __init__(self, as_base64: str, as_hex: str, as_number: int):
19+
self.base64 = as_base64
20+
self.hex = as_hex
21+
self.number = as_number
22+
1423

1524
class SmartContract:
1625
def __init__(self, address: Optional[Address] = None, bytecode=None, metadata=None):
@@ -120,7 +129,14 @@ def prepare_upgrade_transaction_data(self, arguments: List[Any]):
120129

121130
return tx_data
122131

123-
def query(self, proxy: IElrondProxy, function: str, arguments: List[Any], value: int = 0, caller: Optional[Address] = None) -> List[Any]:
132+
def query(
133+
self,
134+
proxy: IElrondProxy,
135+
function: str,
136+
arguments: List[Any],
137+
value: int = 0,
138+
caller: Optional[Address] = None
139+
) -> List[Any]:
124140
response_data = self.query_detailed(proxy, function, arguments, value, caller)
125141
return_data = response_data.get("returnData", []) or response_data.get("ReturnData", [])
126142
return [self._interpret_return_data(data) for data in return_data]
@@ -143,7 +159,7 @@ def query_detailed(self, proxy: IElrondProxy, function: str, arguments: List[Any
143159
response_data = response.get("data", {})
144160
return response_data
145161

146-
def _interpret_return_data(self, data: Any) -> Any:
162+
def _interpret_return_data(self, data: str) -> Any:
147163
if not data:
148164
return data
149165

@@ -152,34 +168,48 @@ def _interpret_return_data(self, data: Any) -> Any:
152168
as_hex = as_bytes.hex()
153169
as_number = int(as_hex, 16)
154170

155-
result = utils.Object()
156-
result.base64 = data
157-
result.hex = as_hex
158-
result.number = as_number
171+
result = QueryResult(data, as_hex, as_number)
159172
return result
160173
except Exception:
161174
logger.warn(f"Cannot interpret return data: {data}")
162175
return None
163176

164177

165178
def _prepare_argument(argument: Any):
166-
hex_prefix = "0X"
167179
as_string = str(argument).upper()
168180

169-
if as_string.startswith(hex_prefix):
170-
return as_string[len(hex_prefix):]
181+
if as_string.startswith(HEX_PREFIX):
182+
return _prepare_hexadecimal(as_string)
183+
184+
return _prepare_decimal(as_string)
171185

172-
if not as_string.isnumeric():
173-
raise errors.UnknownArgumentFormat(as_string)
174186

175-
as_number = int(as_string)
176-
as_hexstring = hex(as_number)[len(hex_prefix):]
177-
if len(as_hexstring) % 2 == 1:
178-
as_hexstring = "0" + as_hexstring
187+
def _prepare_hexadecimal(argument: str) -> str:
188+
argument = argument[len(HEX_PREFIX):]
189+
argument = ensure_even_length(argument)
190+
try:
191+
_ = int(argument, 16)
192+
except ValueError:
193+
raise errors.UnknownArgumentFormat(argument)
194+
return argument
179195

196+
197+
def _prepare_decimal(argument: str) -> str:
198+
if not argument.isnumeric():
199+
raise errors.UnknownArgumentFormat(argument)
200+
201+
as_number = int(argument)
202+
as_hexstring = hex(as_number)[len(HEX_PREFIX):]
203+
as_hexstring = ensure_even_length(as_hexstring)
180204
return as_hexstring
181205

182206

207+
def ensure_even_length(string: str) -> str:
208+
if len(string) % 2 == 1:
209+
return '0' + string
210+
return string
211+
212+
183213
class CodeMetadata:
184214
def __init__(self, upgradeable: bool = True, payable: bool = False):
185215
self.upgradeable = upgradeable

erdpy/conv/__init__.py

Lines changed: 0 additions & 3 deletions
This file was deleted.

erdpy/conv/conv.py

Lines changed: 0 additions & 21 deletions
This file was deleted.

erdpy/delegation/staking_provider.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from os import path
44

55
from erdpy.validators.validators_file import ValidatorsFile
6-
from erdpy.conv.conv import Converters
6+
from erdpy import utils
77
from erdpy.accounts import Account
88
from erdpy.config import MetaChainSystemSCsCost
99
from erdpy.validators.core import estimate_system_sc_call
@@ -15,8 +15,8 @@
1515

1616
def prepare_args_for_create_new_staking_contract(args: Any):
1717
args.data = 'createNewDelegationContract'
18-
args.data += '@' + Converters.str_int_to_hex_str(str(args.total_delegation_cap))
19-
args.data += '@' + Converters.str_int_to_hex_str(str(args.service_fee))
18+
args.data += '@' + utils.str_int_to_hex_str(str(args.total_delegation_cap))
19+
args.data += '@' + utils.str_int_to_hex_str(str(args.service_fee))
2020

2121
args.receiver = DELEGATION_MANAGER_SC_ADDRESS
2222

@@ -57,41 +57,41 @@ def prepare_args_for_remove_nodes(args: Any):
5757

5858

5959
def prepare_args_for_stake_nodes(args: Any):
60-
parsed_keys, num_keys = Converters.parse_keys(args.bls_keys)
60+
parsed_keys, num_keys = utils.parse_keys(args.bls_keys)
6161
args.data = 'stakeNodes' + parsed_keys
6262
args.receiver = args.delegation_contract
6363

6464
if args.estimate_gas:
65-
args.gas_limit = estimate_system_sc_call(args, MetaChainSystemSCsCost.DELEGATION_OPS
66-
+ MetaChainSystemSCsCost.STAKE, num_keys + 1)
65+
cost = MetaChainSystemSCsCost.DELEGATION_OPS + MetaChainSystemSCsCost.STAKE
66+
args.gas_limit = estimate_system_sc_call(args, cost, num_keys + 1)
6767

6868

6969
def prepare_args_for_unbond_nodes(args: Any):
70-
parsed_keys, num_keys = Converters.parse_keys(args.bls_keys)
70+
parsed_keys, num_keys = utils.parse_keys(args.bls_keys)
7171
args.data = 'unBondNodes' + parsed_keys
7272
args.receiver = args.delegation_contract
7373

7474
if args.estimate_gas:
75-
args.gas_limit = estimate_system_sc_call(args, MetaChainSystemSCsCost.DELEGATION_OPS
76-
+ MetaChainSystemSCsCost.UNBOND, num_keys + 1)
75+
cost = MetaChainSystemSCsCost.DELEGATION_OPS + MetaChainSystemSCsCost.UNBOND
76+
args.gas_limit = estimate_system_sc_call(args, cost, num_keys + 1)
7777

7878

7979
def prepare_args_for_unstake_nodes(args: Any):
80-
parsed_keys, num_keys = Converters.parse_keys(args.bls_keys)
80+
parsed_keys, num_keys = utils.parse_keys(args.bls_keys)
8181
args.data = 'unStakeNodes' + parsed_keys
8282
args.receiver = args.delegation_contract
8383

8484
if args.estimate_gas:
85-
args.gas_limit = estimate_system_sc_call(args, MetaChainSystemSCsCost.DELEGATION_OPS
86-
+ MetaChainSystemSCsCost.UNSTAKE, num_keys + 1)
85+
cost = MetaChainSystemSCsCost.DELEGATION_OPS + MetaChainSystemSCsCost.UNSTAKE
86+
args.gas_limit = estimate_system_sc_call(args, cost, num_keys + 1)
8787

8888

8989
def prepare_args_for_unjail_nodes(args: Any):
9090
_prepare_args("unJailNodes", args)
9191

9292

9393
def _prepare_args(command: str, args: Any):
94-
parsed_keys, num_keys = Converters.parse_keys(args.bls_keys)
94+
parsed_keys, num_keys = utils.parse_keys(args.bls_keys)
9595
args.data = command + parsed_keys
9696
args.receiver = args.delegation_contract
9797

@@ -101,7 +101,7 @@ def _prepare_args(command: str, args: Any):
101101

102102
def prepare_args_change_service_fee(args: Any):
103103
data = 'changeServiceFee'
104-
data += '@' + Converters.str_int_to_hex_str(str(args.service_fee))
104+
data += '@' + utils.str_int_to_hex_str(str(args.service_fee))
105105

106106
args.data = data
107107
args.receiver = args.delegation_contract
@@ -111,7 +111,7 @@ def prepare_args_change_service_fee(args: Any):
111111

112112
def prepare_args_modify_delegation_cap(args: Any):
113113
data = 'modifyTotalDelegationCap'
114-
data += '@' + Converters.str_int_to_hex_str(str(args.delegation_cap))
114+
data += '@' + utils.str_int_to_hex_str(str(args.delegation_cap))
115115

116116
args.data = data
117117
args.receiver = args.delegation_contract

0 commit comments

Comments
 (0)