Repository: multiversx/mx-sdk-py-cli (language: python)

Issue:
Fix vm repository name



Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index ee06ff85..2f359c4d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,7 +5,6 @@ __pycache__
 *.py[cod]
 *$py.class
 .pytest_cache/
-erdpy/tests/testdata-out
 .idea
 
 
diff --git a/erdpy/CHANGELOG.md b/erdpy/CHANGELOG.md
index 968f54ee..9d2cf064 100644
--- a/erdpy/CHANGELOG.md
+++ b/erdpy/CHANGELOG.md
@@ -7,6 +7,12 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
 ## [Unreleased]
  - TBD
 
+## [3.0.3]
+ - Fixes after repository migrations
+
+## [3.0.2]
+ - Fixes after repository migrations
+
 ## [3.0.1]
  - [Contract verify: fix CLI arguments & json request](https://github.com/ElrondNetwork/elrond-sdk-erdpy/pull/171)
 
diff --git a/erdpy/_version.py b/erdpy/_version.py
index 05527687..8d1c8625 100644
--- a/erdpy/_version.py
+++ b/erdpy/_version.py
@@ -1,1 +1,1 @@
-__version__ = "3.0.1"
+__version__ = "3.0.3"
diff --git a/erdpy/accounts.py b/erdpy/accounts.py
index e3d4ce5b..e7293501 100644
--- a/erdpy/accounts.py
+++ b/erdpy/accounts.py
@@ -1,11 +1,12 @@
 import logging
 from pathlib import Path
-from typing import Any, Optional
+from typing import Any, Optional, Protocol
 
 import nacl.signing
 
 from erdpy import constants, errors
 from erdpy.interfaces import IAccount, IAddress, ITransaction
+from erdpy_network_providers.accounts import AccountOnNetwork
 from erdpy.ledger.config import compare_versions
 from erdpy.ledger.ledger_app_handler import SIGN_USING_HASH_VERSION
 from erdpy.ledger.ledger_functions import do_get_ledger_address, do_sign_transaction_with_ledger, do_get_ledger_version, \
@@ -16,6 +17,11 @@
 logger = logging.getLogger("accounts")
 
 
+class INetworkProvider(Protocol):
+    def get_account(self, address: IAddress) -> AccountOnNetwork:
+        ...
+
+
 class Account(IAccount):
     def __init__(self,
                  address: Any = None,
@@ -39,9 +45,9 @@ def __init__(self,
             self.secret_key = secret_key.hex()
             self.address = Address(address_from_key_file)
 
-    def sync_nonce(self, proxy: Any):
+    def sync_nonce(self, proxy: INetworkProvider):
         logger.info("Account.sync_nonce()")
-        self.nonce = proxy.get_account_nonce(self.address)
+        self.nonce = proxy.get_account(self.address).nonce
         logger.info(f"Account.sync_nonce() done: {self.nonce}")
 
     def sign_transaction(self, transaction: ITransaction) -> str:
diff --git a/erdpy/accounts_repository.py b/erdpy/accounts_repository.py
index f9e106fc..df336e90 100644
--- a/erdpy/accounts_repository.py
+++ b/erdpy/accounts_repository.py
@@ -1,16 +1,22 @@
 import logging
 from multiprocessing.pool import ThreadPool
 from pathlib import Path
-from typing import List, Set, Union
+from typing import List, Set, Union, Protocol
 
 from erdpy import utils
 from erdpy.accounts import Account, Address
-from erdpy.interfaces import IElrondProxy
+from erdpy_network_providers.accounts import AccountOnNetwork
+from erdpy.interfaces import IAddress
 from erdpy.wallet import pem
 
 logger = logging.getLogger("accounts")
 
 
+class INetworkProvider(Protocol):
+    def get_account(self, address: IAddress) -> AccountOnNetwork:
+        ...
+
+
 class AccountsRepository:
     def __init__(self, accounts: List[Account]):
         self.accounts = accounts
@@ -66,7 +72,7 @@ def get_all(self) -> List[Account]:
     def __len__(self):
         return len(self.accounts)
 
-    def sync_nonces(self, proxy: IElrondProxy, num_parallel: int = 10):
+    def sync_nonces(self, proxy: INetworkProvider, num_parallel: int = 10):
         logger.info("Sync nonces for", len(self.accounts), "accounts")
 
         def sync_nonce(account: Account):
diff --git a/erdpy/cli.py b/erdpy/cli.py
index 23d1b369..c451695e 100644
--- a/erdpy/cli.py
+++ b/erdpy/cli.py
@@ -24,9 +24,9 @@
 logger = logging.getLogger("cli")
 
 
-def main():
+def main(cli_args: List[str] = []):
     try:
-        _do_main()
+        _do_main(cli_args)
     except errors.KnownError as err:
         logger.critical(err.get_pretty())
         return 1
@@ -36,11 +36,11 @@ def main():
     return 0
 
 
-def _do_main():
+def _do_main(cli_args: List[str]):
     logging.basicConfig(level=logging.INFO)
     scope.initialize()
 
-    argv_with_config_args = config.add_config_args(sys.argv[1:])
+    argv_with_config_args = config.add_config_args(cli_args)
     parser = setup_parser(argv_with_config_args)
     args = parser.parse_args(argv_with_config_args)
 
@@ -55,7 +55,7 @@ def _do_main():
         args.func(args)
 
 
-def setup_parser(args: List[str] = sys.argv[1:]):
+def setup_parser(args: List[str]):
     parser = ArgumentParser(
         prog="erdpy",
         usage="erdpy [-h] [-v] [--verbose] COMMAND-GROUP [-h] COMMAND ...",
@@ -108,5 +108,5 @@ def setup_parser(args: List[str] = sys.argv[1:]):
 
 
 if __name__ == "__main__":
-    ret = main()
+    ret = main(sys.argv[1:])
     sys.exit(ret)
diff --git a/erdpy/cli_accounts.py b/erdpy/cli_accounts.py
index 28b4ea50..6dfc2f75 100644
--- a/erdpy/cli_accounts.py
+++ b/erdpy/cli_accounts.py
@@ -3,7 +3,7 @@
 
 from erdpy import cli_shared, utils
 from erdpy.accounts import Address
-from erdpy.proxy.core import ElrondProxy
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
 
 logger = logging.getLogger("cli.accounts")
 
@@ -39,25 +39,24 @@ def _add_address_arg(sub: Any):
 def get_account(args: Any):
     proxy_url = args.proxy
     address = args.address
-    proxy = ElrondProxy(proxy_url)
+    proxy = ProxyNetworkProvider(proxy_url)
     account = proxy.get_account(Address(address))
-    omit_fields = cli_shared.parse_omit_fields_arg(args)
 
     if args.balance:
-        print(account.get("balance", 0))
+        print(account.balance)
     elif args.nonce:
-        print(account.get("nonce", 0))
+        print(account.nonce)
     elif args.username:
-        print(account.get("username", 0))
+        print(account.username)
     else:
-        utils.omit_fields(account, omit_fields)
-        utils.dump_out_json(account)
+        utils.dump_out_json(account.to_dictionary())
 
 
 def get_account_transactions(args: Any):
     proxy_url = args.proxy
     address = args.address
-    proxy = ElrondProxy(proxy_url)
+    proxy = ProxyNetworkProvider(proxy_url)
 
     response = proxy.get_account_transactions(Address(address))
-    utils.dump_out_json(response, args.outfile)
+    transactions_as_dictionaries = [tx.to_dictionary() for tx in response]
+    utils.dump_out_json(transactions_as_dictionaries, args.outfile)
diff --git a/erdpy/cli_block.py b/erdpy/cli_block.py
index d1bc42fb..6e0ef57e 100644
--- a/erdpy/cli_block.py
+++ b/erdpy/cli_block.py
@@ -1,7 +1,7 @@
 from typing import Any
 
 from erdpy import cli_shared, utils
-from erdpy.proxy.core import ElrondProxy
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
 
 
 def setup_parser(subparsers: Any) -> Any:
@@ -18,6 +18,14 @@ def setup_parser(subparsers: Any) -> Any:
 
 def get_hyperblock(args: Any) -> Any:
     proxy_url = args.proxy
-    proxy = ElrondProxy(proxy_url)
-    response = proxy.get_hyperblock(args.key)
+    proxy = ProxyNetworkProvider(proxy_url)
+    key =  args.key
+
+    url = f"hyperblock/by-hash/{key}"
+    if str(key).isnumeric():
+        url = f"hyperblock/by-nonce/{key}"
+
+    response = proxy.do_get_generic(url)
+    response = response.get("hyperblock", {})
+
     utils.dump_out_json(response)
diff --git a/erdpy/cli_contracts.py b/erdpy/cli_contracts.py
index 091be35b..8ba7e729 100644
--- a/erdpy/cli_contracts.py
+++ b/erdpy/cli_contracts.py
@@ -11,7 +11,7 @@
 from erdpy.contracts import CodeMetadata, SmartContract
 from erdpy.projects import load_project
 from erdpy.projects.core import get_project_paths_recursively
-from erdpy.proxy.core import ElrondProxy
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
 from erdpy.transactions import Transaction
 from erdpy.docker import is_docker_installed, run_docker
 from erdpy.errors import DockerMissingError
@@ -337,7 +337,7 @@ def _prepare_sender(args: Any) -> Account:
 
     sender.nonce = args.nonce
     if args.recall_nonce:
-        sender.sync_nonce(ElrondProxy(args.proxy))
+        sender.sync_nonce(ProxyNetworkProvider(args.proxy))
 
     return sender
 
@@ -408,7 +408,7 @@ def query(args: Any):
     arguments = args.arguments
 
     contract = SmartContract(contract_address)
-    result = contract.query(ElrondProxy(args.proxy), function, arguments)
+    result = contract.query(ProxyNetworkProvider(args.proxy), function, arguments)
     utils.dump_out_json(result)
 
 
diff --git a/erdpy/cli_delegation.py b/erdpy/cli_delegation.py
index b7d64cf5..2a8488c1 100644
--- a/erdpy/cli_delegation.py
+++ b/erdpy/cli_delegation.py
@@ -1,10 +1,8 @@
-import binascii
 from typing import Any, List
 
 from erdpy import cli_shared, errors, utils
-from erdpy.accounts import Address
 from erdpy.delegation import staking_provider
-from erdpy.proxy import ElrondProxy
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
 from erdpy.transactions import do_prepare_transaction
 
 
@@ -27,7 +25,6 @@ def setup_parser(args: List[str], subparsers: Any) -> Any:
     sub.add_argument("--create-tx-hash", required=True, help="the hash")
     sub.add_argument("--sender", required=False, help="the sender address")
     cli_shared.add_proxy_arg(sub)
-    cli_shared.add_omit_fields_arg(sub)
     sub.set_defaults(func=get_contract_address_by_deploy_tx_hash)
 
     # add a new node
@@ -150,13 +147,16 @@ def do_create_delegation_contract(args: Any):
 
 def get_contract_address_by_deploy_tx_hash(args: Any):
     args = utils.as_object(args)
-    omit_fields = cli_shared.parse_omit_fields_arg(args)
 
-    proxy = ElrondProxy(args.proxy)
+    proxy = ProxyNetworkProvider(args.proxy)
 
-    transaction = proxy.get_transaction(args.create_tx_hash, with_results=True)
-    utils.omit_fields(transaction, omit_fields)
-    _get_sc_address_from_tx(transaction)
+    transaction = proxy.get_transaction(args.create_tx_hash)
+    transaction_events = transaction.logs.events
+    if len(transaction_events) == 1:
+        contract_address = transaction_events[0].address
+        print(contract_address.bech32())
+    else:
+        raise errors.ProgrammingError("Tx has more than one event. Make sure it's a staking provider SC Deploy transaction.")
 
 
 def add_new_nodes(args: Any):
@@ -255,29 +255,3 @@ def set_metadata(args: Any):
     tx = do_prepare_transaction(args)
 
     cli_shared.send_or_simulate(tx, args)
-
-
-def _get_sc_address_from_tx(data: Any):
-    if not isinstance(data, dict):
-        raise errors.ProgrammingError("error")
-
-    sc_results = data.get('smartContractResults')
-    if sc_results is None:
-        raise errors.ProgrammingError("smart contract results missing")
-
-    # TODO improve robustness of this code in case of failed transaction
-    try:
-        sc_result = sc_results[0]
-        data_field = sc_result['data']
-
-        data_field_split = data_field.split('@')
-        arg_1 = binascii.unhexlify(data_field_split[1])
-        if not arg_1 == b'ok':
-            raise errors.ProgrammingError(arg_1.decode("utf-8"))
-
-        sc_address = binascii.unhexlify(data_field_split[2])
-        address = Address(sc_address)
-        print("Contract address: ", address)
-    except Exception:
-        raise errors.ProgrammingError(
-            "cannot get the smart contract address from transaction results, please try again")
diff --git a/erdpy/cli_dns.py b/erdpy/cli_dns.py
index 69090a01..6bec3f09 100644
--- a/erdpy/cli_dns.py
+++ b/erdpy/cli_dns.py
@@ -2,9 +2,10 @@
 from prettytable import PrettyTable
 
 from erdpy import cli_shared
-from erdpy.dns import name_hash, dns_address_for_name, register, resolve, registration_cost, validate_name, version, compute_dns_address_for_shard_id
+from erdpy.dns import (name_hash, dns_address_for_name, register, resolve, registration_cost,
+                        validate_name, version, compute_dns_address_for_shard_id)
 from erdpy.accounts import Address
-from erdpy.proxy.core import ElrondProxy
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
 
 
 def setup_parser(args: List[str], subparsers: Any) -> Any:
@@ -66,13 +67,13 @@ def _add_name_arg(sub: Any):
 
 
 def dns_resolve(args: Any):
-    addr = resolve(args.name, ElrondProxy(args.proxy))
+    addr = resolve(args.name, ProxyNetworkProvider(args.proxy))
     if addr.hex() != Address.zero().hex():
         print(addr.bech32())
 
 
 def dns_validate_name(args: Any):
-    validate_name(args.name, args.shard_id, ElrondProxy(args.proxy))
+    validate_name(args.name, args.shard_id, ProxyNetworkProvider(args.proxy))
 
 
 def get_name_hash(args: Any):
@@ -92,11 +93,11 @@ def get_dns_address_for_name_hex(args: Any):
 
 
 def get_registration_cost(args: Any):
-    print(registration_cost(args.shard_id, ElrondProxy(args.proxy)))
+    print(registration_cost(args.shard_id, ProxyNetworkProvider(args.proxy)))
 
 
 def get_version(args: Any):
-    proxy = ElrondProxy(args.proxy)
+    proxy = ProxyNetworkProvider(args.proxy)
     if args.all:
         t = PrettyTable(['Shard ID', 'Contract address (bech32)', 'Contract address (hex)', 'Version'])
         for shard_id in range(0, 256):
diff --git a/erdpy/cli_ledger.py b/erdpy/cli_ledger.py
index fd40a503..47b78e50 100644
--- a/erdpy/cli_ledger.py
+++ b/erdpy/cli_ledger.py
@@ -20,7 +20,7 @@ def setup_parser(subparsers: Any) -> Any:
     return subparsers
 
 
-def print_addresses(args):
+def print_addresses(args: Any):
     ledger_app = ElrondLedgerApp()
     for i in range(args.num_addresses):
         address = ledger_app.get_address(0, i)
@@ -28,7 +28,7 @@ def print_addresses(args):
     ledger_app.close()
 
 
-def print_version(args):
+def print_version(args: Any):
     ledger_app = ElrondLedgerApp()
     print("Elrond App version: " + ledger_app.get_version())
     ledger_app.close()
diff --git a/erdpy/cli_network.py b/erdpy/cli_network.py
index ea1b0b00..78a38a41 100644
--- a/erdpy/cli_network.py
+++ b/erdpy/cli_network.py
@@ -1,4 +1,4 @@
-from erdpy.proxy.core import ElrondProxy
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
 from erdpy import cli_shared
 import logging
 from typing import Any
@@ -27,26 +27,26 @@ def setup_parser(subparsers: Any) -> Any:
     return subparsers
 
 
-def get_num_shards(args):
+def get_num_shards(args: Any):
     proxy_url = args.proxy
-    proxy = ElrondProxy(proxy_url)
-    num_shards = proxy.get_num_shards()
+    proxy = ProxyNetworkProvider(proxy_url)
+    num_shards = proxy.get_network_config().num_shards_without_meta
     print(num_shards)
     return num_shards
 
 
-def get_last_block_nonce(args):
+def get_last_block_nonce(args: Any):
     proxy_url = args.proxy
     shard = args.shard
-    proxy = ElrondProxy(proxy_url)
-    nonce = proxy.get_last_block_nonce(shard)
+    proxy = ProxyNetworkProvider(proxy_url)
+    nonce = proxy.get_network_status(shard).highest_final_nonce
     print(nonce)
     return nonce
 
 
-def get_chain_id(args):
+def get_chain_id(args: Any):
     proxy_url = args.proxy
-    proxy = ElrondProxy(proxy_url)
-    chain_id = proxy.get_chain_id()
+    proxy = ProxyNetworkProvider(proxy_url)
+    chain_id = proxy.get_network_config().chain_id
     print(chain_id)
     return chain_id
diff --git a/erdpy/cli_password.py b/erdpy/cli_password.py
index 3412d4ca..f05b54a2 100644
--- a/erdpy/cli_password.py
+++ b/erdpy/cli_password.py
@@ -1,6 +1,7 @@
+from typing import Any
 from getpass import getpass
 
-def load_password(args):
+def load_password(args: Any):
     if args.passfile:
         with open(args.passfile) as pass_file:
             return pass_file.read().strip()
diff --git a/erdpy/cli_shared.py b/erdpy/cli_shared.py
index c0bb1cca..7060c756 100644
--- a/erdpy/cli_shared.py
+++ b/erdpy/cli_shared.py
@@ -9,7 +9,7 @@
 from erdpy.cli_output import CLIOutputBuilder
 from erdpy.cli_password import load_password
 from erdpy.ledger.ledger_functions import do_get_ledger_address
-from erdpy.proxy.core import ElrondProxy
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
 from erdpy.simulation import Simulator
 from erdpy.transactions import Transaction
 
@@ -125,7 +125,7 @@ def prepare_nonce_in_args(args: Any):
         else:
             raise errors.NoWalletProvided()
 
-        account.sync_nonce(ElrondProxy(args.proxy))
+        account.sync_nonce(ProxyNetworkProvider(args.proxy))
         args.nonce = account.nonce
 
 
@@ -146,7 +146,7 @@ def check_broadcast_args(args: Any):
 
 
 def send_or_simulate(tx: Transaction, args: Any, dump_output: bool = True) -> CLIOutputBuilder:
-    proxy = ElrondProxy(args.proxy)
+    proxy = ProxyNetworkProvider(args.proxy)
 
     is_set_wait_result = hasattr(args, "wait_result") and args.wait_result
     is_set_send = hasattr(args, "send") and args.send
@@ -178,7 +178,7 @@ def send_or_simulate(tx: Transaction, args: Any, dump_output: bool = True) -> CL
 
 def check_if_sign_method_required(args: List[str], checked_method: str) -> bool:
     methods = ["--pem", "--keyfile", "--ledger"]
-    rest_of_methods = []
+    rest_of_methods: List[str] = []
     for method in methods:
         if method != checked_method:
             rest_of_methods.append(method)
diff --git a/erdpy/cli_transactions.py b/erdpy/cli_transactions.py
index 51162a6b..6eb02fcf 100644
--- a/erdpy/cli_transactions.py
+++ b/erdpy/cli_transactions.py
@@ -3,7 +3,7 @@
 
 from erdpy import cli_shared, utils
 from erdpy.cli_output import CLIOutputBuilder
-from erdpy.proxy.core import ElrondProxy
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
 from erdpy.transactions import Transaction, do_prepare_transaction
 
 
@@ -70,7 +70,7 @@ def send_transaction(args: Any):
     tx = Transaction.load_from_file(args.infile)
 
     try:
-        tx.send(ElrondProxy(args.proxy))
+        tx.send(ProxyNetworkProvider(args.proxy))
     finally:
         output = CLIOutputBuilder().set_emitted_transaction(tx).build()
         utils.dump_out_json(output, outfile=args.outfile)
@@ -79,8 +79,8 @@ def send_transaction(args: Any):
 def get_transaction(args: Any):
     args = utils.as_object(args)
     omit_fields = cli_shared.parse_omit_fields_arg(args)
-    proxy = ElrondProxy(args.proxy)
+    proxy = ProxyNetworkProvider(args.proxy)
 
-    transaction = proxy.get_transaction(args.hash, args.sender, args.with_results)
+    transaction = proxy.get_transaction(args.hash)
     output = CLIOutputBuilder().set_transaction_on_network(transaction, omit_fields).build()
     utils.dump_out_json(output)
diff --git a/erdpy/config.py b/erdpy/config.py
index 9c1264a3..987bc03d 100644
--- a/erdpy/config.py
+++ b/erdpy/config.py
@@ -153,7 +153,7 @@ def get_defaults() -> Dict[str, Any]:
         "chainID": "T",
         "txVersion": "1",
         "dependencies.vmtools.tag": "latest",
-        "dependencies.elrond_wasm_rs.tag": "latest",
+        "dependencies.mx_sdk_rs.tag": "latest",
         "dependencies.vmtools.urlTemplate.linux": "https://github.com/ElrondNetwork/wasm-vm/archive/{TAG}.tar.gz",
         "dependencies.vmtools.urlTemplate.osx": "https://github.com/ElrondNetwork/wasm-vm/archive/{TAG}.tar.gz",
         "dependencies.llvm.tag": "v9-19feb",
diff --git a/erdpy/contracts.py b/erdpy/contracts.py
index bca8b124..bdd7021c 100644
--- a/erdpy/contracts.py
+++ b/erdpy/contracts.py
@@ -1,14 +1,14 @@
 import base64
 import logging
-from typing import Any, List, Optional, Tuple
+from typing import Any, List, Optional, Tuple, Protocol, Sequence
 
 from Cryptodome.Hash import keccak
 
 from erdpy import config, constants, errors
 from erdpy.accounts import Account, Address
-from erdpy.interfaces import IElrondProxy
 from erdpy.transactions import Transaction
 from erdpy.utils import Object
+from erdpy_network_providers.interface import IContractQuery
 
 logger = logging.getLogger("contracts")
 
@@ -19,6 +19,11 @@
 STR_PREFIX = "str:"
 
 
+class INetworkProvider(Protocol):
+    def query_contract(self, query: Any) -> Any:
+        ...
+
+
 class QueryResult(Object):
     def __init__(self, as_base64: str, as_hex: str, as_number: int):
         self.base64 = as_base64
@@ -26,6 +31,30 @@ def __init__(self, as_base64: str, as_hex: str, as_number: int):
         self.number = as_number
 
 
+class ContractQuery(IContractQuery):
+    def __init__(self, address: Address, function: str, value: int, arguments: List[bytes], caller: Optional[Address] = None):
+        self.contract = address
+        self.function = function
+        self.caller = caller
+        self.value = value
+        self.encoded_arguments = [item.hex() for item in arguments]
+
+    def get_contract(self) -> Address:
+        return self.contract
+
+    def get_function(self) -> str:
+        return self.function
+
+    def get_encoded_arguments(self) -> Sequence[str]:
+        return self.encoded_arguments
+
+    def get_caller(self) -> Optional[Address]:
+        return self.caller
+    
+    def get_value(self) -> int:
+        return self.value
+
+
 class SmartContract:
     def __init__(self, address: Optional[Address] = None, bytecode=None, metadata=None):
         self.address = Address(address)
@@ -136,33 +165,24 @@ def prepare_upgrade_transaction_data(self, arguments: List[Any]):
 
     def query(
         self,
-        proxy: IElrondProxy,
+        proxy: INetworkProvider,
         function: str,
         arguments: List[Any],
         value: int = 0,
         caller: Optional[Address] = None
     ) -> List[Any]:
         response_data = self.query_detailed(proxy, function, arguments, value, caller)
-        return_data = response_data.get("returnData", []) or response_data.get("ReturnData", [])
+        return_data = response_data.return_data
         return [self._interpret_return_data(data) for data in return_data]
 
-    def query_detailed(self, proxy: IElrondProxy, function: str, arguments: List[Any], value: int = 0, caller: Optional[Address] = None) -> Any:
+    def query_detailed(self, proxy: INetworkProvider, function: str, arguments: List[Any],
+                        value: int = 0, caller: Optional[Address] = None) -> Any:
         arguments = arguments or []
-        prepared_arguments = [_prepare_argument(argument) for argument in arguments]
-
-        payload = {
-            "scAddress": self.address.bech32(),
-            "funcName": function,
-            "args": prepared_arguments,
-            "value": str(value)
-        }
 
-        if caller:
-            payload["caller"] = caller.bech32()
+        query = ContractQuery(self.address, function, value, arguments, caller)
 
-        response = proxy.query_contract(payload)
-        response_data = response.get("data", {})
-        return response_data
+        response = proxy.query_contract(query)
+        return response
 
     def _interpret_return_data(self, data: str) -> Any:
         if not data:
diff --git a/erdpy/dependencies/modules.py b/erdpy/dependencies/modules.py
index 679a3f18..e6aa6817 100644
--- a/erdpy/dependencies/modules.py
+++ b/erdpy/dependencies/modules.py
@@ -150,8 +150,8 @@ def __init__(self, key: str, aliases: List[str] = None):
             aliases = list()
 
         super().__init__(key, aliases)
-        self.repo_name = 'wasm-vm'
-        self.organisation = 'ElrondNetwork'
+        self.repo_name = 'mx-chain-vm-go'
+        self.organisation = 'multiversx'
 
     def _post_install(self, tag: str):
         dependencies.install_module('golang')
@@ -406,8 +406,8 @@ def _post_install(self, tag: str):
 class TestWalletsModule(StandaloneModule):
     def __init__(self, key: str):
         super().__init__(key, [])
-        self.organisation = "ElrondNetwork"
-        self.repo_name = "elrond-sdk-testwallets"
+        self.organisation = "multiversx"
+        self.repo_name = "mx-sdk-testwallets"
 
     def _post_install(self, tag: str):
         # We'll create a "latest" symlink
diff --git a/erdpy/dns.py b/erdpy/dns.py
index 6d87d44a..ba0d2930 100644
--- a/erdpy/dns.py
+++ b/erdpy/dns.py
@@ -1,20 +1,23 @@
-from typing import Any, List
+from typing import Any, List, Protocol
 
 from Cryptodome.Hash import keccak
 
 from erdpy import cli_shared, utils
 from erdpy.accounts import Account, Address
 from erdpy.contracts import SmartContract
-from erdpy.proxy.core import ElrondProxy
 from erdpy.transactions import do_prepare_transaction
-from erdpy.interfaces import IElrondProxy
 
 MaxNumShards = 256
 ShardIdentiferLen = 2
 InitialDNSAddress = bytes([1] * 32)
 
 
-def resolve(name: str, proxy: ElrondProxy) -> Address:
+class INetworkProvider(Protocol):
+    def query_contract(self, query: Any) -> Any:
+        ...
+
+
+def resolve(name: str, proxy: INetworkProvider) -> Address:
     name_arg = "0x{}".format(str.encode(name).hex())
     dns_address = dns_address_for_name(name)
     contract = SmartContract(dns_address)
@@ -24,7 +27,7 @@ def resolve(name: str, proxy: ElrondProxy) -> Address:
     return Address(result[0].hex)
 
 
-def validate_name(name: str, shard_id: int, proxy: ElrondProxy):
+def validate_name(name: str, shard_id: int, proxy: INetworkProvider):
     name_arg = "0x{}".format(str.encode(name).hex())
     dns_address = compute_dns_address_for_shard_id(shard_id)
     contract = SmartContract(dns_address)
@@ -49,7 +52,7 @@ def register(args: Any):
 
 
 def compute_all_dns_addresses() -> List[Address]:
-    addresses = []
+    addresses: List[Address] = []
     for i in range(0, 256):
         addresses.append(compute_dns_address_for_shard_id(i))
     return addresses
@@ -59,7 +62,7 @@ def name_hash(name: str) -> bytes:
     return keccak.new(digest_bits=256).update(str.encode(name)).digest()
 
 
-def registration_cost(shard_id: int, proxy: ElrondProxy) -> int:
+def registration_cost(shard_id: int, proxy: INetworkProvider) -> int:
     dns_address = compute_dns_address_for_shard_id(shard_id)
     contract = SmartContract(dns_address)
     result = contract.query(proxy, "getRegistrationCost", [])
@@ -69,7 +72,7 @@ def registration_cost(shard_id: int, proxy: ElrondProxy) -> int:
         return int("0x{}".format(result[0]))
 
 
-def version(shard_id: int, proxy: IElrondProxy) -> str:
+def version(shard_id: int, proxy: INetworkProvider) -> str:
     dns_address = compute_dns_address_for_shard_id(shard_id)
     contract = SmartContract(dns_address)
     result = contract.query(proxy, "version", [])
diff --git a/erdpy/interfaces.py b/erdpy/interfaces.py
index 5b09f9ac..8d27636f 100644
--- a/erdpy/interfaces.py
+++ b/erdpy/interfaces.py
@@ -1,4 +1,4 @@
-from typing import Any, Dict, List, Tuple
+from typing import Any, Dict
 from erdpy.utils import ISerializable
 
 
@@ -44,43 +44,9 @@ def sign_transaction(self, transaction: ITransaction) -> str:
         return ""
 
 
-class ITransactionOnNetwork(ISerializable):
-    def is_done(self) -> bool:
-        return False
-
-    def get_hash(self) -> str:
-        return ""
-
-
 class ISimulateResponse(ISerializable):
     pass
 
 
 class ISimulateCostResponse(ISerializable):
     pass
-
-
-class IElrondProxy:
-    def get_account_nonce(self, address: IAddress) -> int:
-        return 0
-
-    def get_transaction(self, tx_hash: str, sender_address: str = "", with_results: bool = False) -> ITransactionOnNetwork:
-        return ITransactionOnNetwork()
-
-    def send_transaction(self, payload: Any) -> str:
-        return ""
-
-    def simulate_transaction(self, payload: Any) -> ISimulateResponse:
-        return ISimulateResponse()
-
-    def simulate_transaction_cost(self, payload: Any) -> ISimulateCostResponse:
-        return ISimulateCostResponse()
-
-    def send_transactions(self, payload: List[Any]) -> Tuple[int, List[str]]:
-        return 0, []
-
-    def send_transaction_and_wait_for_result(self, payload: Any, num_seconds_timeout: int) -> ITransactionOnNetwork:
-        return ITransactionOnNetwork()
-
-    def query_contract(self, payload: Any) -> Any:
-        return dict()
diff --git a/erdpy/projects/eei_activation.py b/erdpy/projects/eei_activation.py
index b805416b..fdf4adc9 100644
--- a/erdpy/projects/eei_activation.py
+++ b/erdpy/projects/eei_activation.py
@@ -5,7 +5,7 @@
 import requests
 import toml
 from erdpy.diskcache import DiskCache
-from erdpy.proxy.core import ElrondProxy
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
 
 logger = logging.getLogger("eei")
 
@@ -28,8 +28,8 @@ def is_flag_active(self, flag_name: str):
 
     def _fetch_current_epoch(self):
         logger.info(f"fetch_current_epoch: {self.proxy_url}")
-        proxy = ElrondProxy(self.proxy_url)
-        return proxy.get_epoch()
+        proxy = ProxyNetworkProvider(self.proxy_url)
+        return proxy.get_network_status().epoch_number
 
     def _fetch_enable_epochs(self):
         logger.info(f"fetch_enable_epochs: {self.enable_epochs_url}")
diff --git a/erdpy/projects/templates_config.py b/erdpy/projects/templates_config.py
index c278e6b1..e2ef3553 100644
--- a/erdpy/projects/templates_config.py
+++ b/erdpy/projects/templates_config.py
@@ -7,26 +7,26 @@
 
 def get_templates_repositories():
     timestamp = int(time.time())
-    examples_rs_tag = config.get_dependency_tag('elrond_wasm_rs')
+    examples_rs_tag = config.get_dependency_tag('mx_sdk_rs')
 
     if examples_rs_tag == 'latest':
-        examples_rs_tag = query_latest_release_tag('ElrondNetwork/elrond-wasm-rs')
+        examples_rs_tag = query_latest_release_tag('multiversx/mx-sdk-rs')
 
     examples_rs_tag_no_v = remove_initial_v_from_version(examples_rs_tag)
 
     return [
         TemplatesRepository(
             key="sc-examples",
-            url=f"https://github.com/ElrondNetwork/sc-examples/archive/master.zip?t={timestamp}",
-            github="ElrondNetwork/sc-examples",
-            relative_path="sc-examples-master"
+            url=f"https://github.com/multiversx/mx-sc-examples/archive/master.zip?t={timestamp}",
+            github="multiversx/mx-sc-examples",
+            relative_path="mx-sc-examples-master"
         ),
 
         TemplatesRepository(
-            key="elrond-wasm-rs",
-            url=f"https://github.com/ElrondNetwork/elrond-wasm-rs/archive/{examples_rs_tag}.zip?t={timestamp}",
-            github="ElrondNetwork/elrond-wasm-rs",
-            relative_path=f"elrond-wasm-rs-{examples_rs_tag_no_v}/contracts/examples"
+            key="mx-sdk-rs",
+            url=f"https://github.com/multiversx/mx-sdk-rs/archive/{examples_rs_tag}.zip?t={timestamp}",
+            github="multiversx/mx-sdk-rs",
+            relative_path=f"mx-sdk-rs-{examples_rs_tag_no_v}/contracts/examples"
         )
     ]
 
diff --git a/erdpy/proxy/__init__.py b/erdpy/proxy/__init__.py
deleted file mode 100644
index c8c111f9..00000000
--- a/erdpy/proxy/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from erdpy.proxy.core import ElrondProxy
-
-__all__ = ["ElrondProxy"]
diff --git a/erdpy/proxy/core.py b/erdpy/proxy/core.py
deleted file mode 100644
index 8388a95a..00000000
--- a/erdpy/proxy/core.py
+++ /dev/null
@@ -1,167 +0,0 @@
-import logging
-import time
-from typing import Any, List, Tuple, Union, cast
-
-from erdpy.accounts import Address
-from erdpy.interfaces import IAddress, IElrondProxy, ISimulateCostResponse, ISimulateResponse, ITransactionOnNetwork
-from erdpy.proxy.http_facade import do_get, do_post
-from erdpy.proxy.messages import NetworkConfig, SimulateCostResponse, SimulateResponse, TransactionOnNetwork
-
-METACHAIN_ID = 4294967295
-ANY_SHARD_ID = 0
-AWAIT_TRANSACTION_PERIOD = 5
-
-logger = logging.getLogger("proxy")
-
-
-class ElrondProxy(IElrondProxy):
-    def __init__(self, url: str):
-        self.url = url
-
-    def get_account_nonce(self, address: IAddress) -> int:
-        url = f"{self.url}/address/{address.bech32()}"
-        response = do_get(url)
-        nonce = response.get("account").get("nonce", 0)
-        return int(nonce)
-
-    def get_account_balance(self, address: IAddress):
-        url = f"{self.url}/address/{address.bech32()}/balance"
-        response = do_get(url)
-        balance = response.get("balance", 0)
-        return int(balance)
-
-    def get_account(self, address: IAddress):
-        url = f"{self.url}/address/{address.bech32()}"
-        response = do_get(url)
-        account = response.get("account", dict())
-        return account
-
-    def get_account_transactions(self, address: Address):
-        TRUNCATE_DATA_THRESHOLD = 75
-
-        url = f"{self.url}/address/{address.bech32()}/transactions"
-        response = do_get(url)
-        transactions = response.get("transactions", [])
-        for transaction in transactions:
-            data = transaction.get("data") or ""
-            data = (data[:TRUNCATE_DATA_THRESHOLD] + ' ... truncated ...') if len(data) > TRUNCATE_DATA_THRESHOLD else data
-            transaction["data"] = data
-        return transactions
-
-    def get_esdt_tokens(self, address: str) -> List:
-        response = do_get(f"{self.url}/address/{address}/esdt")
-        esdts = response.get("esdts")
-        return cast(List, esdts)
-
-    def get_esdt_balance(self, address: str, ticker: str) -> dict:
-        response = do_get(f"{self.url}/address/{address}/esdt/{ticker}")
-        token_data = response.get("tokenData")
-        return cast(dict, token_data)
-
-    def get_all_tokens(self) -> List[str]:
-        response = do_get(f"{self.url}/network/esdts")
-        tokens = response.get("tokens", [])
-        return cast(List[str], tokens)
-
-    def get_num_shards(self):
-        network_config = self.get_network_config()
-        return network_config.num_shards
-
-    def get_epoch(self):
-        status = self._get_network_status(METACHAIN_ID)
-        nonce = status.get("erd_epoch_number", 0)
-        return nonce
-
-    def get_last_block_nonce(self, shard_id: Union[str, int]):
-        if shard_id == "metachain":
-            metrics = self._get_network_status(METACHAIN_ID)
-        else:
-            metrics = self._get_network_status(shard_id)
-
-        nonce = metrics.get("erd_highest_final_nonce", 0)
-        return nonce
-
-    def get_gas_price(self):
-        network_config = self.get_network_config()
-        return network_config.min_gas_price
-
-    def get_chain_id(self):
-        network_config = self.get_network_config()
-        return network_config.chain_id
-
-    def _get_network_status(self, shard_id: Union[str, int]):
-        url = f"{self.url}/network/status/{shard_id}"
-        response = do_get(url)
-        payload = response.get("status")
-        return payload
-
-    def get_network_config(self) -> NetworkConfig:
-        url = f"{self.url}/network/config"
-        response = do_get(url)
-        payload = response.get("config")
-        result = NetworkConfig(payload)
-        return result
-
-    def send_transaction(self, payload: Any) -> str:
-        url = f"{self.url}/transaction/send"
-        response = do_post(url, payload)
-        tx_hash = str(response.get("txHash"))
-        return tx_hash
-
-    def simulate_transaction(self, payload: Any) -> ISimulateResponse:
-        url = f"{self.url}/transaction/simulate"
-        response = do_post(url, payload)
-        return SimulateResponse(response)
-
-    def simulate_transaction_cost(self, payload: Any) -> ISimulateCostResponse:
-        url = f"{self.url}/transaction/cost"
-        response = do_post(url, payload)
-        return SimulateCostResponse(response)
-
-    def send_transactions(self, payload: List[Any]) -> Tuple[int, List[str]]:
-        url = f"{self.url}/transaction/send-multiple"
-        response = do_post(url, payload)
-        # Proxy and Observers have different response format:
-        num_sent = response.get("numOfSentTxs", 0) or response.get("txsSent", 0)
-        hashes = response.get("txsHashes")
-        return num_sent, hashes
-
-    def query_contract(self, payload: Any) -> Any:
-        url = f"{self.url}/vm-values/query"
-        response = do_post(url, payload)
-        return response
-
-    def get_transaction(self, tx_hash: str, sender_address: str = "", with_results: bool = False) -> TransactionOnNetwork:
-        url = f"{self.url}/transaction/{tx_hash}"
-        url += f"?sender={sender_address or ''}"
-        url += f"&withResults={with_results}"
-
-        response = do_get(url)
-        return TransactionOnNetwork(tx_hash, response)
-
-    def get_hyperblock(self, key) -> Any:
-        url = f"{self.url}/hyperblock/by-hash/{key}"
-        if str(key).isnumeric():
-            url = f"{self.url}/hyperblock/by-nonce/{key}"
-
-        response = do_get(url)
-        response = response.get("hyperblock", {})
-        return response
-
-    def send_transaction_and_wait_for_result(self, payload: Any, num_seconds_timeout: int = 100) -> ITransactionOnNetwork:
-        url = f"{self.url}/transaction/send"
-        response = do_post(url, payload)
-        tx_hash = response.get("txHash")
-        num_periods_to_wait = int(num_seconds_timeout / AWAIT_TRANSACTION_PERIOD)
-
-        for _ in range(0, num_periods_to_wait):
-            time.sleep(AWAIT_TRANSACTION_PERIOD)
-
-            tx = self.get_transaction(tx_hash=tx_hash, with_results=True)
-            if tx.is_done():
-                return tx
-            else:
-                logger.info("Transaction not yet done.")
-
-        return ITransactionOnNetwork()
- 
diff --git a/erdpy/proxy/http_facade.py b/erdpy/proxy/http_facade.py
deleted file mode 100644
index 02aab53b..00000000
--- a/erdpy/proxy/http_facade.py
+++ /dev/null
@@ -1,52 +0,0 @@
-from typing import Any, Dict
-import requests
-from erdpy import errors
-from erdpy.proxy.messages import GenericProxyResponse
-
-
-def do_get(url: str) -> GenericProxyResponse:
-    try:
-        response = requests.get(url)
-        response.raise_for_status()
-        parsed = response.json()
-        return get_data(parsed, url)
-    except requests.HTTPError as err:
-        error_data = _extract_error_from_response(err.response)
-        raise errors.ProxyRequestError(url, error_data)
-    except requests.ConnectionError as err:
-        raise errors.ProxyRequestError(url, err)
-    except Exception as err:
-        raise errors.ProxyRequestError(url, err)
-
-
-def do_post(url: str, payload: Any) -> GenericProxyResponse:
-    try:
-        response = requests.post(url, json=payload)
-        response.raise_for_status()
-        parsed = response.json()
-        return get_data(parsed, url)
-    except requests.HTTPError as err:
-        error_data = _extract_error_from_response(err.response)
-        raise errors.ProxyRequestError(url, error_data)
-    except requests.ConnectionError as err:
-        raise errors.ProxyRequestError(url, err)
-    except Exception as err:
-        raise errors.ProxyRequestError(url, err)
-
-
-def get_data(parsed: Dict[str, Any], url: str) -> GenericProxyResponse:
-    err = parsed.get("error")
-    code = parsed.get("code")
-
-    if not err and code == "successful":
-        data: Dict[str, Any] = parsed.get("data", dict())
-        return GenericProxyResponse(data)
-
-    raise errors.ProxyRequestError(url, f"code:{code}, error: {err}")
-
-
-def _extract_error_from_response(response: Any):
-    try:
-        return response.json()
-    except Exception:
-        return response.text
diff --git a/erdpy/proxy/messages.py b/erdpy/proxy/messages.py
deleted file mode 100644
index 72dedd8b..00000000
--- a/erdpy/proxy/messages.py
+++ /dev/null
@@ -1,141 +0,0 @@
-import base64
-from typing import Any, Dict, List, Union
-
-from erdpy.interfaces import ISimulateCostResponse, ISimulateResponse, ITransactionOnNetwork
-from erdpy.utils import ISerializable
-
-
-class GenericProxyResponse(ISerializable):
-    def __init__(self, data: Any) -> None:
-        self.__dict__.update(data)
-
-    def get(self, key: str, default: Any = None) -> Any:
-        return self.__dict__.get(key, default)
-
-
-class NetworkConfig:
-    def __init__(self, data: Dict[str, Any]) -> None:
-        self.num_shards = data.get("erd_num_shards_without_meta", 0)
-        self.min_gas_price = data.get("erd_min_gas_price", 0)
-        self.chain_id = data.get("erd_chain_id", "?")
-        self.min_tx_version = data.get("erd_min_transaction_version", 0)
-
-
-class TransactionOnNetwork(ITransactionOnNetwork):
-    def __init__(self, hash: str, response: GenericProxyResponse) -> None:
-        raw = response.get("transaction", dict())
-        contract_results: List[Dict[str, Any]] = raw.get("smartContractResults", [])
-
-        self.raw = raw
-        self.hash = hash
-        self.parsed_contract_results = [SmartContractResult(item) for item in contract_results]
-        self.parsed_logs: List[Log] = []
-
-    def is_done(self) -> bool:
-        hyperblock: int = self.raw.get("hyperblockNonce", 0)
-        return hyperblock > 0
-
-    def get_hash(self) -> str:
-        return self.hash
-
-    def to_dictionary(self) -> Dict[str, Any]:
-        result: Dict[str, Any] = dict()
-        result.update(self.raw)
-        result["parsed"] = dict()
-
-        if self.parsed_contract_results:
-            result["parsed"]["smartContractResults"] = self.parsed_contract_results
-        if self.parsed_logs:
-            result["parsed"]["logs"] = self.parsed_logs
-
-        return result
-
-
-class SmartContractResult(ISerializable):
-    def __init__(self, raw: Dict[str, Any]) -> None:
-        self.raw = raw
-        self.return_message = self._parse_return_message()
-        self.arguments = self._parse_arguments()
-        self.parsed_log = Log(raw.get("logs", {}))
-
-    def _parse_return_message(self) -> str:
-        try:
-            data_parts = self._parse_data_parts()
-            return_message_encoded = data_parts[0]
-            return_message = bytes.fromhex(return_message_encoded).decode("ascii")
-            return return_message
-        except:
-            return ""
-
-    def _parse_arguments(self) -> List[str]:
-        try:
-            data_parts = self._parse_data_parts()
-            arguments = data_parts[1:]
-            return arguments
-        except:
-            return []
-
-    def _parse_data_parts(self) -> List[str]:
-        data: str = self.raw.get("data", "").lstrip("@")
-        return data.split("@")
-
-    def to_dictionary(self) -> Dict[str, Any]:
-        result: Dict[str, Any] = dict()
-        result.update(self.raw)
-        result["parsed"] = {
-            "returnMessage": self.return_message,
-            "arguments": self.arguments,
-            "log": self.parsed_log
-        }
-
-        return result
-
-
-class Log(ISerializable):
-    def __init__(self, raw: Dict[str, Any]) -> None:
-        self.raw = raw
-
-
-class SimulateResponse(ISimulateResponse):
-    def __init__(self, response: GenericProxyResponse) -> None:
-        result: Dict[str, Any] = response.get("result") or dict()
-        contract_results: Dict[str, Any] = result.get("scResults") or dict()
-
-        self.raw = response.to_dictionary()
-        self.parsed_contract_results = [SmartContractResult(item) for item in contract_results.values()]
-
-    def to_dictionary(self) -> Dict[str, Any]:
-        result: Dict[str, Any] = dict()
-        result.update(self.raw)
-        result["parsed"] = dict()
-
-        if self.parsed_contract_results:
-            result["parsed"]["smartContractResults"] = self.parsed_contract_results
-
-        return result
-
-
-class SimulateCostResponse(ISimulateCostResponse):
-    def __init__(self, response: GenericProxyResponse) -> None:
-        contract_results: Dict[str, Any] = response.get("smartContractResults") or dict()
-
-        self.raw = response.to_dictionary()
-        self.parsed_contract_results = [SmartContractResult(item) for item in contract_results.values()]
-
-    def to_dictionary(self) -> Dict[str, Any]:
-        result: Dict[str, Any] = dict()
-        result.update(self.raw)
-        result["parsed"] = dict()
-
-        if self.parsed_contract_results:
-            result["parsed"]["smartContractResults"] = self.parsed_contract_results
-
-        return result
-
-
-def decode_hex_base64(input: Union[str, None]) -> str:
-    return bytes.fromhex(decode_base64(input)).decode('ascii') if input else ""
-
-
-def decode_base64(input: Union[str, None]) -> str:
-    return base64.b64decode(input).decode() if input else ""
diff --git a/erdpy/simulation.py b/erdpy/simulation.py
index b1a345b8..e7f352fa 100644
--- a/erdpy/simulation.py
+++ b/erdpy/simulation.py
@@ -1,9 +1,17 @@
 from collections import OrderedDict
-from typing import Any, Dict
-from erdpy.interfaces import IElrondProxy, ISimulateCostResponse, ISimulateResponse, ITransaction
+from typing import Any, Dict, Protocol
+from erdpy.interfaces import ISimulateCostResponse, ISimulateResponse, ITransaction
 from erdpy.utils import ISerializable
 
 
+class INetworkProvider(Protocol):
+    def simulate_transaction(self, transaction: Dict[str, Any]) -> ISimulateResponse:
+        ...
+    
+    def simulate_transaction_cost(self, transaction: Dict[str, Any]) -> ISimulateCostResponse:
+        ...
+
+
 class Simulation(ISerializable):
     def __init__(self, simulate_response: ISimulateResponse, simulate_cost_response: ISimulateCostResponse) -> None:
         self.simulation_response = simulate_response
@@ -17,7 +25,7 @@ def to_dictionary(self) -> Dict[str, Any]:
         return dictionary
 
 class Simulator():
-    def __init__(self, proxy: IElrondProxy) -> None:
+    def __init__(self, proxy: INetworkProvider) -> None:
         self.proxy = proxy
 
     def run(self, transaction: ITransaction) -> Simulation:
diff --git a/erdpy/transactions.py b/erdpy/transactions.py
index abeec062..0fefdb1f 100644
--- a/erdpy/transactions.py
+++ b/erdpy/transactions.py
@@ -1,17 +1,37 @@
 import base64
 import json
 import logging
+import time
 from collections import OrderedDict
-from typing import Any, Dict, List, TextIO
+from typing import Any, Dict, List, TextIO, Tuple, Protocol, Sequence
 
 from erdpy import config, errors, utils
 from erdpy.accounts import Account, Address, LedgerAccount
 from erdpy.cli_password import load_password
-from erdpy.interfaces import IElrondProxy, ITransaction, ITransactionOnNetwork
+from erdpy.interfaces import ITransaction
 
 logger = logging.getLogger("transactions")
 
 
+class ITransactionOnNetwork(Protocol):
+    hash: str
+    is_completed: bool
+
+    def to_dictionary(self) -> Dict[str, Any]:
+        ...
+
+
+class INetworkProvider(Protocol):
+    def send_transaction(self, transaction: ITransaction) -> str:
+        ...
+    
+    def send_transactions(self, transactions: Sequence[ITransaction]) -> Tuple[int, str]:
+        ...
+    
+    def get_transaction(self, tx_hash: str) -> ITransactionOnNetwork:
+        ...
+
+
 class Transaction(ITransaction):
     def __init__(self):
         self.hash: str = ""
@@ -50,7 +70,7 @@ def receiver_username_decoded(self) -> str:
         return self._field_decoded("receiverUsername")
 
     def _field_encoded(self, field: str) -> str:
-        field_bytes = self.__dict__.get(field, None).encode("utf-8")
+        field_bytes = self.__dict__.get(field, "").encode("utf-8")
         encoded = base64.b64encode(field_bytes).decode()
         return encoded
 
@@ -83,7 +103,7 @@ def serialize_as_inner(self) -> str:
     @classmethod
     def load_from_file(cls, f: TextIO):
         data_json: bytes = f.read().encode()
-        fields = json.loads(data_json).get("tx")
+        fields = json.loads(data_json).get("tx") or json.loads(data_json).get("emittedTransaction")
         instance = cls()
         instance.__dict__.update(fields)
         instance.data = instance.data_decoded()
@@ -91,25 +111,41 @@ def load_from_file(cls, f: TextIO):
         instance.receiverUsername = instance.receiver_username_encoded()
         return instance
 
-    def send(self, proxy: IElrondProxy):
+    def send(self, proxy: INetworkProvider):
         if not self.signature:
             raise errors.TransactionIsNotSigned()
 
         logger.info(f"Transaction.send: nonce={self.nonce}")
 
-        dictionary = self.to_dictionary()
-        self.hash = proxy.send_transaction(dictionary)
+        self.hash = proxy.send_transaction(self)
         logger.info(f"Hash: {self.hash}")
         utils.log_explorer_transaction(self.chainID, self.hash)
         return self.hash
 
-    def send_wait_result(self, proxy: IElrondProxy, timeout: int) -> ITransactionOnNetwork:
+    def send_wait_result(self, proxy: INetworkProvider, timeout: int) -> ITransactionOnNetwork:
         if not self.signature:
             raise errors.TransactionIsNotSigned()
 
-        txOnNetwork = proxy.send_transaction_and_wait_for_result(self.to_dictionary(), timeout)
-        self.hash = txOnNetwork.get_hash()
+        txOnNetwork = self.__send_transaction_and_wait_for_result(proxy , self, timeout)
+        self.hash = txOnNetwork.hash
         return txOnNetwork
+    
+    def __send_transaction_and_wait_for_result(self, proxy: INetworkProvider, payload: Any, num_seconds_timeout: int = 100) -> ITransactionOnNetwork:
+        AWAIT_TRANSACTION_PERIOD = 5
+
+        tx_hash = proxy.send_transaction(payload)
+        num_periods_to_wait = int(num_seconds_timeout / AWAIT_TRANSACTION_PERIOD)
+
+        for _ in range(0, num_periods_to_wait):
+            time.sleep(AWAIT_TRANSACTION_PERIOD)
+
+            tx = proxy.get_transaction(tx_hash)
+            if tx.is_completed:
+                return tx
+            else:
+                logger.info("Transaction not yet done.")
+
+        raise errors.KnownError("Took too long to get transaction.")
 
     def to_dictionary(self) -> Dict[str, Any]:
         dictionary: Dict[str, Any] = OrderedDict()
@@ -194,13 +230,12 @@ def add(self, sender: Account, receiver_address: str, nonce: Any, value: Any, da
         tx.sign(sender)
         self.transactions.append(tx)
 
-    def add_tx(self, tx):
+    def add_tx(self, tx: Transaction):
         self.transactions.append(tx)
 
-    def send(self, proxy: IElrondProxy):
+    def send(self, proxy: INetworkProvider):
         logger.info(f"BunchOfTransactions.send: {len(self.transactions)} transactions")
-        payload = [transaction.to_dictionary() for transaction in self.transactions]
-        num_sent, hashes = proxy.send_transactions(payload)
+        num_sent, hashes = proxy.send_transactions(self.transactions)
         logger.info(f"Sent: {num_sent}")
         logger.info(f"TxsHashes: {hashes}")
         return num_sent, hashes
@@ -221,8 +256,8 @@ def do_prepare_transaction(args: Any) -> Transaction:
     tx.value = args.value
     tx.receiver = args.receiver
     tx.sender = account.address.bech32()
-    tx.senderUsername = getattr(args, "sender_username", None)
-    tx.receiverUsername = getattr(args, "receiver_username", None)
+    tx.senderUsername = getattr(args, "sender_username", "")
+    tx.receiverUsername = getattr(args, "receiver_username", "")
     tx.gasPrice = int(args.gas_price)
     tx.gasLimit = int(args.gas_limit)
     tx.data = args.data
diff --git a/erdpy/utils.py b/erdpy/utils.py
index a7a639b1..1b8e765b 100644
--- a/erdpy/utils.py
+++ b/erdpy/utils.py
@@ -9,7 +9,7 @@
 import tarfile
 import zipfile
 from pathlib import Path
-from typing import Any, List, Union, Optional, cast, IO, Dict
+from typing import Any, List, Union, Optional, cast, IO, Dict, Protocol, runtime_checkable
 
 import toml
 
@@ -18,7 +18,8 @@
 
 logger = logging.getLogger("utils")
 
-class ISerializable:
+@runtime_checkable
+class ISerializable(Protocol):
     def to_dictionary(self) -> Dict[str, Any]:
         return self.__dict__
 
diff --git a/examples/airdrop.py b/examples/airdrop.py
index bf9107cc..e9e250f7 100644
--- a/examples/airdrop.py
+++ b/examples/airdrop.py
@@ -6,8 +6,7 @@
 
 from erdpy.accounts import Account, Address
 from erdpy.accounts_repository import AccountsRepository
-from erdpy.proxy import ElrondProxy
-from erdpy.proxy.core import ElrondProxy
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
 from erdpy.transactions import BunchOfTransactions, Transaction
 
 
@@ -31,7 +30,7 @@ def main():
     parser.add_argument("--value", type=int, help="value, as a number (atoms of EGLD)")
     args = parser.parse_args()
 
-    proxy = ElrondProxy(args.proxy)
+    proxy = ProxyNetworkProvider(args.proxy)
     network = proxy.get_network_config()
     accounts = AccountsRepository.create_from_folder(Path(args.accounts))
     sender = cast(Account, accounts.get_account(Address(args.sender)))
@@ -51,7 +50,7 @@ def main():
         transaction.gasPrice = network.min_gas_price
         transaction.gasLimit = 50000
         transaction.chainID = network.chain_id
-        transaction.version = network.min_tx_version
+        transaction.version = network.min_transaction_version
         transaction.sign(sender)
         sender.nonce += 1
 
diff --git a/examples/contracts.py b/examples/contracts.py
index dd22ad44..8d3c572d 100644
--- a/examples/contracts.py
+++ b/examples/contracts.py
@@ -5,7 +5,7 @@
 
 from erdpy.accounts import Account, Address
 from erdpy.contracts import CodeMetadata, SmartContract
-from erdpy.proxy.core import ElrondProxy
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
 
 logger = logging.getLogger("examples")
 
@@ -30,7 +30,7 @@
 
     logging.basicConfig(level=logging.DEBUG)
 
-    proxy = ElrondProxy(args.proxy)
+    proxy = ProxyNetworkProvider(args.proxy)
     network = proxy.get_network_config()
     user = Account(pem_file=args.pem)
 
@@ -49,7 +49,7 @@ def do_deploy():
             gas_limit=5000000,
             value=0,
             chain=network.chain_id,
-            version=network.min_tx_version
+            version=network.min_transaction_version
         )
 
         tx_on_network = tx.send_wait_result(proxy, 5000)
diff --git a/examples/staking.py b/examples/staking.py
index 7c37caf9..7bdf1873 100644
--- a/examples/staking.py
+++ b/examples/staking.py
@@ -5,8 +5,8 @@
 from erdpy.accounts import Account, Address
 from erdpy.cli_output import CLIOutputBuilder
 from erdpy.cli_password import load_password
-from erdpy.proxy.core import ElrondProxy
 from erdpy.transactions import Transaction
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
 from erdpy.validators.core import VALIDATORS_SMART_CONTRACT_ADDRESS, prepare_transaction_data_for_stake
 
 logger = logging.getLogger("examples")
@@ -35,7 +35,7 @@ def main():
     parser.add_argument("--value", type=int, required=True, help="value, as a number (atoms of EGLD)")
     args = parser.parse_args()
 
-    proxy = ElrondProxy(args.proxy)
+    proxy = ProxyNetworkProvider(args.proxy)
     network = proxy.get_network_config()
     password = load_password(args)
     node_operator = Account(key_file=args.keyfile, password=password)
@@ -52,7 +52,7 @@ def main():
     tx.gasLimit = gas_limit
     tx.data = data
     tx.chainID = network.chain_id
-    tx.version = network.min_tx_version
+    tx.version = network.min_transaction_version
     tx.sign(node_operator)
 
     utils.dump_out_json(CLIOutputBuilder().set_emitted_transaction(tx).build())
diff --git a/pyrightconfig.json b/pyrightconfig.json
new file mode 100644
index 00000000..be41aee1
--- /dev/null
+++ b/pyrightconfig.json
@@ -0,0 +1,18 @@
+{
+    "include": [
+        "erdpy"
+    ],
+    "exclude": [
+        "**/__pycache__"
+    ],
+    "ignore": [],
+    "defineConstant": {
+        "DEBUG": true
+    },
+    "venvPath": ".",
+    "venv": ".venv",
+    "stubPath": "",
+    "reportMissingImports": true,
+    "reportMissingTypeStubs": false,
+    "reportUnknownParameterType": true
+}
diff --git a/requirements.txt b/requirements.txt
index 52622e17..a0fbf32e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -17,3 +17,5 @@ pytest
 setuptools
 
 mx-sdk-build-contract-rs==4.0.0
+
+mx-sdk-erdpy-network-providers==0.6.2
diff --git a/setup.py b/setup.py
index ff091a21..b1583874 100644
--- a/setup.py
+++ b/setup.py
@@ -1,9 +1,9 @@
 import setuptools
 
 with open("README.md", "r") as fh:
-    long_description = "https://github.com/ElrondNetwork/elrond-sdk-erdpy"
+    long_description = "https://github.com/multiversx/mx-sdk-erdpy"
 
-VERSION = "3.0.1"
+VERSION = "3.0.3"
 
 try:
     with open('./erdpy/_version.py', 'wt') as versionfile:
@@ -18,7 +18,7 @@
     description="Elrond Smart Contracts Tools and Python SDK",
     long_description=long_description,
     long_description_content_type="text/markdown",
-    url="https://github.com/ElrondNetwork/elrond-sdk-erdpy",
+    url="https://github.com/multiversx/mx-sdk-erdpy",
     author="Elrond Network",
     license="GPL",
     packages=setuptools.find_packages(
@@ -36,7 +36,8 @@
         "ledgercomm[hid]",
         "semver",
         "requests-cache",
-        "mx-sdk-build-contract-rs==4.0.0"
+        "mx-sdk-build-contract-rs==4.0.0",
+        "mx-sdk-erdpy-network-providers==0.6.2"
     ],
     zip_safe=False,
     keywords=["Elrond"],


Test patch:
diff --git a/erdpy/tests/test_accounts_repository.py b/erdpy/tests/test_accounts_repository.py
index 9329e9ac..a9af78f2 100644
--- a/erdpy/tests/test_accounts_repository.py
+++ b/erdpy/tests/test_accounts_repository.py
@@ -1,12 +1,19 @@
-from erdpy.accounts import Address
+from typing import Protocol
+
+from erdpy.accounts import Address, AccountOnNetwork
 from erdpy.accounts_repository import AccountsRepository
-from erdpy.interfaces import IAddress, IElrondProxy
+from erdpy.interfaces import IAddress
 from erdpy.workstation import get_tools_folder
 
 TESTNET_USERS_FOLDER = get_tools_folder() / "testwallets" / "latest" / "users"
 DUMMY_NONCE = 42
 
 
+class INetworkProvider(Protocol):
+    def get_account(self, address: IAddress) -> AccountOnNetwork:
+        ...
+
+
 def test_create_from_folder():
     repository = AccountsRepository.create_from_folder(TESTNET_USERS_FOLDER)
     assert len(repository) == 12
@@ -49,6 +56,9 @@ def test_sync_nonces():
         assert account.nonce == DUMMY_NONCE
 
 
-class ElrondProxyStub(IElrondProxy):
-    def get_account_nonce(self, address: IAddress) -> int:
-        return DUMMY_NONCE
+class ElrondProxyStub(INetworkProvider):    
+    def get_account(self, address: IAddress) -> AccountOnNetwork:
+        account =  AccountOnNetwork()
+        account.nonce = DUMMY_NONCE
+
+        return account
diff --git a/erdpy/tests/test_proxy.py b/erdpy/tests/test_proxy.py
new file mode 100644
index 00000000..94e4ec79
--- /dev/null
+++ b/erdpy/tests/test_proxy.py
@@ -0,0 +1,140 @@
+from pathlib import Path
+from erdpy.cli import main
+from erdpy.accounts import Account
+from erdpy_network_providers.proxy_network_provider import ProxyNetworkProvider
+
+
+def test_get_transactions():
+    output_file = Path(__file__).parent / "testdata-out" / "transactions.txt"
+
+    main(
+        [
+            "account",
+            "get-transactions",
+            "--address",
+            "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th",
+            "--outfile",
+            str(output_file),
+        ]
+    )
+    assert Path.is_file(output_file) == True
+
+
+def test_get_account():
+    result = main(
+        [
+            "account",
+            "get",
+            "--address",
+            "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th",
+        ]
+    )
+    if not result:
+        assert True
+    else:
+        assert False
+
+
+def test_get_hyperblock_by_nonce():
+    result = main(
+        [
+            "hyperblock",
+            "get",
+            "--key",
+            "3895403",
+            "--proxy",
+            "https://devnet-api.elrond.com",
+        ]
+    )
+    if not result:
+        assert True
+    else:
+        assert False
+
+
+def test_get_hyperblock_by_hash():
+    result = main(
+        [
+            "hyperblock",
+            "get",
+            "--key",
+            "85ccf29f51d7acf0fbb6cfcf2e4b89eee2f2264dd989edd5a870d33dacc24743",
+            "--proxy",
+            "https://devnet-api.elrond.com",
+        ]
+    )
+    if not result:
+        assert True
+    else:
+        assert False
+
+
+def test_sync_nonce():
+    account = Account("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")
+    proxy = ProxyNetworkProvider("https://devnet-api.elrond.com")
+    account.sync_nonce(proxy)
+
+    assert account.nonce >= 11480
+
+
+def test_query_contract():
+    result = main(
+        [
+            "contract",
+            "query",
+            "erd1qqqqqqqqqqqqqpgquykqja5c4v33zdmnwglj3jphqwrelzdn396qlc9g33",
+            "--function",
+            "getSum",
+            "--proxy",
+            "https://devnet-api.elrond.com",
+        ]
+    )
+    if not result:
+        assert True
+    else:
+        assert False
+
+
+def test_get_num_shards():
+    result = main(["network", "num-shards"])
+
+    if not result:
+        assert True
+    else:
+        assert False
+
+
+def test_get_last_block_nonce():
+    result = main(["network", "block-nonce", "--shard", "4294967295"])
+
+    if not result:
+        assert True
+    else:
+        assert False
+
+
+def test_get_chain_id():
+    result = main(["network", "chain"])
+
+    if not result:
+        assert True
+    else:
+        assert False
+
+
+def test_get_transaction():
+    result = main(
+        [
+            "tx",
+            "get",
+            "--proxy",
+            "https://devnet-api.elrond.com",
+            "--hash",
+            "2cb813be9d5e5040abb2522da75fa5c8d94f72caa510ff51d7525659f398298b",
+        ]
+    )
+
+    if not result:
+        assert True
+    else:
+        assert False
diff --git a/erdpy/tests/testdata-out/.gitignore b/erdpy/tests/testdata-out/.gitignore
new file mode 100644
index 00000000..210accf2
--- /dev/null
+++ b/erdpy/tests/testdata-out/.gitignore
@@ -0,0 +1,6 @@
+# Ignore everything
+*
+
+# But not these files...
+!.gitignore
+