Skip to content

Commit 56d4b19

Browse files
committed
Merge branch 'feat/next' into get-commands
2 parents 672c0f0 + 2876207 commit 56d4b19

15 files changed

Lines changed: 214 additions & 80 deletions
Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from pathlib import Path
33
from typing import Any
44

5+
from multiversx_sdk_cli.constants import SDK_PATH
56
from multiversx_sdk_cli.errors import (
67
AliasAlreadyExistsError,
78
AliasProtectedError,
@@ -10,18 +11,38 @@
1011
)
1112
from multiversx_sdk_cli.utils import read_json_file, write_json_file
1213

13-
SDK_PATH = Path("~/multiversx-sdk").expanduser().resolve()
1414
LOCAL_ADDRESS_CONFIG_PATH = Path("addresses.mxpy.json").resolve()
1515
GLOBAL_ADDRESS_CONFIG_PATH = SDK_PATH / "addresses.mxpy.json"
1616

1717

1818
def get_defaults() -> dict[str, str]:
19+
"""
20+
Not all values are required for a config to be valid.
21+
22+
Valid config for PEM wallets:
23+
```
24+
{
25+
"kind": "pem",
26+
"path": "/path/to/wallet.pem",
27+
"index": "0" # optional, defaults to 0
28+
}
29+
```
30+
31+
Valid config for KEYSTORE wallets:
32+
```
33+
{
34+
"kind": "keystore",
35+
"path": "/path/to/wallet.json",
36+
"index": "0" # optional, defaults to 0
37+
}
38+
```
39+
40+
For keystore wallets, you'll be prompted to enter the password when using the wallet.
41+
"""
1942
return {
2043
"kind": "",
2144
"path": "",
2245
"index": "",
23-
"password": "",
24-
"passwordPath": "",
2546
}
2647

2748

@@ -41,6 +62,7 @@ def _guard_valid_name(name: str):
4162

4263

4364
def get_active_address() -> dict[str, str]:
65+
"""Returns the active address configuration."""
4466
data = read_address_config_file()
4567
addresses: dict[str, Any] = data.get("addresses", {})
4668
active_address: str = data.get("active", "default")
@@ -65,25 +87,27 @@ def resolve_address_config_path() -> Path:
6587

6688

6789
def set_value(name: str, value: Any):
90+
"""Sets a key-value pair in the active address config."""
6891
_guard_valid_name(name)
6992
data = read_address_config_file()
7093
active_env = data.get("active", "default")
7194
data.setdefault("addresses", {})
7295
data["addresses"].setdefault(active_env, {})
7396
data["addresses"][active_env][name] = value
74-
write_file(data)
97+
_write_file(data)
7598

7699

77-
def write_file(data: dict[str, Any]):
100+
def _write_file(data: dict[str, Any]):
78101
env_path = resolve_address_config_path()
79102
write_json_file(str(env_path), data)
80103

81104

82105
def set_active(name: str):
106+
"""Switches to the address configuration with the given name."""
83107
data = read_address_config_file()
84108
_guard_valid_address_name(data, name)
85109
data["active"] = name
86-
write_file(data)
110+
_write_file(data)
87111

88112

89113
def _guard_valid_address_name(env: Any, name: str):
@@ -93,6 +117,7 @@ def _guard_valid_address_name(env: Any, name: str):
93117

94118

95119
def create_new_address_config(name: str, template: str):
120+
"""Creates a new address config with the given name and optional template."""
96121
data = read_address_config_file()
97122
_guard_alias_unique(data, name)
98123
new_address = {}
@@ -103,7 +128,7 @@ def create_new_address_config(name: str, template: str):
103128
data["active"] = name
104129
data.setdefault("addresses", {})
105130
data["addresses"][name] = new_address
106-
write_file(data)
131+
_write_file(data)
107132

108133

109134
def _guard_alias_unique(env: Any, name: str):
@@ -120,16 +145,17 @@ def delete_config_value(name: str):
120145
data.setdefault("addresses", {})
121146
data["addresses"].setdefault(active_env, {})
122147
del data["addresses"][active_env][name]
123-
write_file(data)
148+
_write_file(data)
124149

125150

126151
def delete_alias(name: str):
152+
"""Deletes the address configuration with the given name."""
127153
_guard_valid_alias_deletion(name)
128154
data = read_address_config_file()
129155
data["addresses"].pop(name, None)
130156
if data["active"] == name:
131157
data["active"] = "default"
132-
write_file(data)
158+
_write_file(data)
133159

134160

135161
def _guard_valid_alias_deletion(name: str):

multiversx_sdk_cli/cli.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import multiversx_sdk_cli.version
3131
from multiversx_sdk_cli import config, errors, utils, ux
3232
from multiversx_sdk_cli.cli_shared import set_proxy_from_config_if_not_provided
33+
from multiversx_sdk_cli.constants import SDK_PATH
3334
from multiversx_sdk_cli.env import get_address_hrp
3435

3536
logger = logging.getLogger("cli")
@@ -49,7 +50,7 @@ def main(cli_args: list[str] = sys.argv[1:]):
4950

5051

5152
def _do_main(cli_args: list[str]):
52-
utils.ensure_folder(config.SDK_PATH)
53+
utils.ensure_folder(SDK_PATH)
5354
parser = setup_parser(cli_args)
5455
argcomplete.autocomplete(parser)
5556

multiversx_sdk_cli/cli_address.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Any
44

55
from multiversx_sdk_cli import cli_shared
6-
from multiversx_sdk_cli.address import (
6+
from multiversx_sdk_cli.address_config import (
77
create_new_address_config,
88
delete_alias,
99
delete_config_value,

multiversx_sdk_cli/cli_password.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,35 @@
1+
import logging
12
from getpass import getpass
23
from typing import Any
34

5+
logger = logging.getLogger("cli.password")
6+
47

58
def load_password(args: Any) -> str:
69
if args.passfile:
10+
logger.warning(
11+
"Using a password file is DEPRECATED and will be removed in a future version. Instead, you'll be prompted to enter the password when using keystore wallets."
12+
)
713
with open(args.passfile) as pass_file:
814
return pass_file.read().strip()
915
return getpass("Keyfile's password: ")
1016

1117

1218
def load_guardian_password(args: Any) -> str:
1319
if args.guardian_passfile:
20+
logger.warning(
21+
"Using a password file is DEPRECATED and will be removed in a future version. Instead, you'll be prompted to enter the password when using keystore wallets."
22+
)
1423
with open(args.guardian_passfile) as pass_file:
1524
return pass_file.read().strip()
1625
return getpass("Keyfile's password: ")
1726

1827

1928
def load_relayer_password(args: Any) -> str:
2029
if args.relayer_passfile:
30+
logger.warning(
31+
"Using a password file is DEPRECATED and will be removed in a future version. Instead, you'll be prompted to enter the password when using keystore wallets."
32+
)
2133
with open(args.relayer_passfile) as pass_file:
2234
return pass_file.read().strip()
2335
return getpass("Keyfile's password: ")

multiversx_sdk_cli/cli_shared.py

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import sys
66
from argparse import FileType
77
from functools import cache
8+
from getpass import getpass
89
from pathlib import Path
910
from typing import Any, Optional, Text, Union, cast
1011

@@ -21,7 +22,7 @@
2122
)
2223

2324
from multiversx_sdk_cli import config, utils
24-
from multiversx_sdk_cli.address import (
25+
from multiversx_sdk_cli.address_config import (
2526
get_active_address,
2627
read_address_config_file,
2728
resolve_address_config_path,
@@ -47,6 +48,7 @@
4748
LedgerError,
4849
NoWalletProvided,
4950
UnknownAddressAliasError,
51+
WalletError,
5052
)
5153
from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData
5254
from multiversx_sdk_cli.interfaces import IAccount
@@ -181,7 +183,7 @@ def add_wallet_args(args: list[str], sub: Any):
181183
)
182184
sub.add_argument(
183185
"--passfile",
184-
help="🔑 a file containing keyfile's password, if keyfile provided. If not provided, you'll be prompted to enter the password.",
186+
help="DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter the password.",
185187
)
186188
sub.add_argument(
187189
"--ledger",
@@ -225,7 +227,7 @@ def add_guardian_wallet_args(args: list[str], sub: Any):
225227
)
226228
sub.add_argument(
227229
"--guardian-passfile",
228-
help="🔑 a file containing keyfile's password, if keyfile provided. If not provided, you'll be prompted to enter the password.",
230+
help="DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter the password.",
229231
)
230232
sub.add_argument(
231233
"--guardian-ledger",
@@ -246,7 +248,7 @@ def add_relayed_v3_wallet_args(args: list[str], sub: Any):
246248
sub.add_argument("--relayer-keyfile", help="🔑 a JSON keyfile, if PEM not provided")
247249
sub.add_argument(
248250
"--relayer-passfile",
249-
help="🔑 a file containing keyfile's password, if keyfile provided. If not provided, you'll be prompted to enter the password.",
251+
help="DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter the password.",
250252
)
251253
sub.add_argument(
252254
"--relayer-ledger",
@@ -357,12 +359,10 @@ def prepare_account(args: Any):
357359
password = load_password(args)
358360
index = args.sender_wallet_index if args.sender_wallet_index != 0 else None
359361

360-
return Account.new_from_keystore(
361-
file_path=Path(args.keyfile),
362-
password=password,
363-
address_index=index,
364-
hrp=hrp,
365-
)
362+
try:
363+
return Account.new_from_keystore(Path(args.keyfile), password=password, address_index=index, hrp=hrp)
364+
except Exception as e:
365+
raise WalletError(str(e))
366366
elif args.ledger:
367367
try:
368368
return LedgerAccount(address_index=args.sender_wallet_index)
@@ -377,11 +377,11 @@ def prepare_account(args: Any):
377377
def load_wallet_by_alias(alias: str, hrp: str) -> Account:
378378
file_path = resolve_address_config_path()
379379
if not file_path.is_file():
380-
raise AddressConfigFileError("The address config file was not found")
380+
raise AddressConfigFileError("The address config file was not found.")
381381

382382
file = read_address_config_file()
383383
if file == dict():
384-
raise AddressConfigFileError("Address config file is empty")
384+
raise AddressConfigFileError("Address config file is empty.")
385385

386386
addresses: dict[str, Any] = file["addresses"]
387387
wallet = addresses.get(alias, None)
@@ -407,33 +407,28 @@ def load_default_wallet(hrp: str) -> Account:
407407
def _load_wallet_from_address_config(wallet: dict[str, str], hrp: str) -> Account:
408408
kind = wallet.get("kind", None)
409409
if not kind:
410-
raise AddressConfigFileError("'kind' field must be set in the address config")
410+
raise AddressConfigFileError("'kind' field must be set in the address config.")
411411

412412
if kind not in ["pem", "keystore"]:
413413
raise InvalidAddressConfigValue("'kind' must be 'pem' or 'keystore'")
414414

415-
path = wallet.get("path", None)
416-
if not path:
417-
raise AddressConfigFileError("'path' field must be set in the address config")
418-
path = Path(path)
415+
wallet_path = wallet.get("path", None)
416+
if not wallet_path:
417+
raise AddressConfigFileError("'path' field must be set in the address config.")
418+
path = Path(wallet_path)
419419

420420
index = int(wallet.get("index", 0))
421421

422422
if kind == "pem":
423423
return Account.new_from_pem(file_path=path, index=index, hrp=hrp)
424424
else:
425-
password = wallet.get("password", "")
426-
password_path = wallet.get("passwordPath", None)
427-
428-
if not password and not password_path:
429-
raise AddressConfigFileError(
430-
"'password' or 'passwordPath' must be set in the address config for keystore wallets"
431-
)
432-
433-
if password_path:
434-
password = Path(password_path).read_text().splitlines()[0].strip()
435-
436-
return Account.new_from_keystore(file_path=path, password=password, address_index=index, hrp=hrp)
425+
logger.info("Using keystore wallet.")
426+
password = getpass("Please enter the wallet password: ")
427+
logger.info(f"Loading keystore wallet from path: {path}")
428+
try:
429+
return Account.new_from_keystore(file_path=path, password=password, address_index=index, hrp=hrp)
430+
except Exception as e:
431+
raise WalletError(str(e))
437432

438433

439434
def _get_address_hrp(args: Any) -> str:
@@ -480,12 +475,15 @@ def load_guardian_account(args: Any) -> Union[IAccount, None]:
480475
password = load_guardian_password(args)
481476
index = args.guardian_wallet_index if args.guardian_wallet_index != 0 else None
482477

483-
return Account.new_from_keystore(
484-
file_path=Path(args.guardian_keyfile),
485-
password=password,
486-
address_index=index,
487-
hrp=hrp,
488-
)
478+
try:
479+
return Account.new_from_keystore(
480+
Path(args.guardian_keyfile),
481+
password=password,
482+
address_index=index,
483+
hrp=hrp,
484+
)
485+
except Exception as e:
486+
raise WalletError(str(e))
489487
elif args.guardian_ledger:
490488
try:
491489
return LedgerAccount(address_index=args.guardian_wallet_index)
@@ -614,12 +612,15 @@ def load_relayer_account(args: Any) -> Union[IAccount, None]:
614612
password = load_relayer_password(args)
615613
index = args.relayer_wallet_index if args.relayer_wallet_index != 0 else None
616614

617-
return Account.new_from_keystore(
618-
file_path=Path(args.relayer_keyfile),
619-
password=password,
620-
address_index=index,
621-
hrp=hrp,
622-
)
615+
try:
616+
return Account.new_from_keystore(
617+
Path(args.relayer_keyfile),
618+
password=password,
619+
address_index=index,
620+
hrp=hrp,
621+
)
622+
except Exception as e:
623+
raise WalletError(str(e))
623624
elif args.relayer_ledger:
624625
try:
625626
return LedgerAccount(address_index=args.relayer_wallet_index)

multiversx_sdk_cli/cli_transactions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ def sign_transaction(args: Any):
162162

163163
try:
164164
sender = cli_shared.prepare_account(args)
165-
except NoWalletProvided:
165+
except:
166+
logger.info("No sender wallet provided. Will not sign for the sender.")
166167
sender = None
167168

168169
if sender and sender.address != tx.sender:

multiversx_sdk_cli/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
from multiversx_sdk import NetworkProviderConfig
77

88
from multiversx_sdk_cli import errors, utils
9+
from multiversx_sdk_cli.constants import SDK_PATH
910

10-
SDK_PATH = Path("~/multiversx-sdk").expanduser().resolve()
1111
LOCAL_CONFIG_PATH = Path("mxpy.json").resolve()
1212
GLOBAL_CONFIG_PATH = SDK_PATH / "mxpy.json"
1313

multiversx_sdk_cli/constants.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from pathlib import Path
2+
13
VM_TYPE_SYSTEM = "0001"
24
VM_TYPE_WASM_VM = "0500"
35
SC_HEX_PUBKEY_PREFIX = "0" * 16
@@ -26,3 +28,5 @@
2628
STR_PREFIX = "str:"
2729
ADDRESS_PREFIX = "addr:"
2830
MAINCHAIN_ADDRESS_HRP = "erd"
31+
32+
SDK_PATH = Path("~/multiversx-sdk").expanduser().resolve()

0 commit comments

Comments
 (0)