from typing import Any, Dict, List, Optional, Union
from pathlib import Path
from decimal import Decimal
from evrmore_rpc.commands.blockchain import BlockchainInfo, Block
from evrmore_rpc.commands.assets import AssetInfo
from evrmore_rpc.commands.network import NetworkInfo
from evrmore_rpc.commands.mining import MiningInfo
from evrmore_rpc.commands.util import UtilInfo

class EvrmoreRPCClient:
    datadir: Optional[Path]
    rpcuser: Optional[str]
    rpcpassword: Optional[str]
    rpcport: Optional[int]
    testnet: bool

    def __init__(self, 
                 datadir: Optional[Path] = None,
                 rpcuser: Optional[str] = None,
                 rpcpassword: Optional[str] = None,
                 rpcport: Optional[int] = None,
                 testnet: bool = False) -> None: ...

    # Blockchain commands
    def getbestblockhash(self) -> str: ...
    def getblock(self, blockhash: str, verbosity: int = 1) -> Union[str, Block, Dict[str, Any]]: ...
    def getblockchaininfo(self) -> BlockchainInfo: ...
    def getblockcount(self) -> int: ...
    def getblockhash(self, height: int) -> str: ...
    def getblockheader(self, blockhash: str, verbose: bool = True) -> Union[str, Dict[str, Any]]: ...
    def getchaintips(self) -> List[Dict[str, Any]]: ...
    def getdifficulty(self) -> float: ...
    def getmempoolinfo(self) -> Dict[str, Any]: ...
    def getrawmempool(self, verbose: bool = False) -> Union[List[str], Dict[str, Any]]: ...
    def gettxout(self, txid: str, n: int, include_mempool: bool = True) -> Optional[Dict[str, Any]]: ...
    def gettxoutsetinfo(self) -> Dict[str, Any]: ...
    def verifychain(self, checklevel: int = 3, nblocks: int = 6) -> bool: ...

    # Asset commands
    def getassetdata(self, asset_name: str) -> AssetInfo: ...
    def getcacheinfo(self) -> Dict[str, Any]: ...
    def issue(self, asset_name: str, qty: Union[int, float, Decimal], to_address: str, change_address: str = "", units: int = 0, reissuable: bool = True, has_ipfs: bool = False, ipfs_hash: str = "") -> str: ...
    def issueunique(self, root_name: str, asset_tags: List[str], ipfs_hashes: Optional[List[str]] = None, to_address: Optional[str] = None, change_address: Optional[str] = None) -> str: ...
    def listassets(self, asset: str = "*", verbose: bool = False, count: int = 50000, start: int = 0) -> Dict[str, Any]: ...
    def listmyassets(self, asset: str = "*", verbose: bool = False, count: int = 50000, start: int = 0) -> Dict[str, Any]: ...
    def reissue(self, asset_name: str, qty: Union[int, float, Decimal], to_address: str, change_address: str = "", reissuable: Optional[bool] = None, new_units: Optional[int] = None, new_ipfs: Optional[str] = None) -> str: ...
    def transfer(self, asset_name: str, qty: Union[int, float, Decimal], to_address: str) -> str: ...

    # Wallet commands
    def abandontransaction(self, txid: str) -> None: ...
    def addmultisigaddress(self, nrequired: int, keys: List[str], account: str = "") -> str: ...
    def addwitnessaddress(self, address: str) -> str: ...
    def backupwallet(self, destination: str) -> None: ...
    def dumpprivkey(self, address: str) -> str: ...
    def dumpwallet(self, filename: str) -> None: ...
    def encryptwallet(self, passphrase: str) -> None: ...
    def getaccount(self, address: str) -> str: ...
    def getaccountaddress(self, account: str) -> str: ...
    def getaddressesbyaccount(self, account: str) -> List[str]: ...
    def getbalance(self, account: str = "*", minconf: int = 1, include_watchonly: bool = False) -> Decimal: ...
    def getnewaddress(self, account: str = "") -> str: ...
    def getrawchangeaddress(self) -> str: ...
    def getreceivedbyaccount(self, account: str, minconf: int = 1) -> Decimal: ...
    def getreceivedbyaddress(self, address: str, minconf: int = 1) -> Decimal: ...
    def gettransaction(self, txid: str, include_watchonly: bool = False) -> Dict[str, Any]: ...
    def getunconfirmedbalance(self) -> Decimal: ...
    def getwalletinfo(self) -> Dict[str, Any]: ...
    def importaddress(self, address: str, label: str = "", rescan: bool = True, p2sh: bool = False) -> None: ...
    def importprivkey(self, privkey: str, label: str = "", rescan: bool = True) -> None: ...
    def importwallet(self, filename: str) -> None: ...
    def keypoolrefill(self, newsize: int = 100) -> None: ...
    def listaccounts(self, minconf: int = 1, include_watchonly: bool = False) -> Dict[str, Decimal]: ...
    def listaddressgroupings(self) -> List[List[List[Any]]]: ...
    def listlockunspent(self) -> List[Dict[str, Any]]: ...
    def listreceivedbyaccount(self, minconf: int = 1, include_empty: bool = False, include_watchonly: bool = False) -> List[Dict[str, Any]]: ...
    def listreceivedbyaddress(self, minconf: int = 1, include_empty: bool = False, include_watchonly: bool = False) -> List[Dict[str, Any]]: ...
    def listsinceblock(self, blockhash: Optional[str] = None, target_confirmations: int = 1, include_watchonly: bool = False) -> Dict[str, Any]: ...
    def listtransactions(self, account: str = "*", count: int = 10, skip: int = 0, include_watchonly: bool = False) -> List[Dict[str, Any]]: ...
    def listunspent(self, minconf: int = 1, maxconf: int = 9999999, addresses: Optional[List[str]] = None, include_unsafe: bool = True, query_options: Optional[Dict[str, Any]] = None) -> List[Dict[str, Any]]: ...
    def lockunspent(self, unlock: bool, transactions: Optional[List[Dict[str, Any]]] = None) -> bool: ...
    def move(self, fromaccount: str, toaccount: str, amount: Decimal, minconf: int = 1, comment: Optional[str] = None) -> bool: ...
    def sendfrom(self, fromaccount: str, toaddress: str, amount: Decimal, minconf: int = 1, comment: Optional[str] = None, comment_to: Optional[str] = None) -> str: ...
    def sendmany(self, fromaccount: str, amounts: Dict[str, Decimal], minconf: int = 1, comment: Optional[str] = None, subtractfeefrom: Optional[List[str]] = None, replaceable: bool = False, conf_target: int = 1, estimate_mode: str = "UNSET") -> str: ...
    def sendtoaddress(self, address: str, amount: Union[int, float, Decimal], comment: str = "", comment_to: str = "", subtractfeefromamount: bool = False, replaceable: bool = False, conf_target: int = 1, estimate_mode: str = "UNSET") -> str: ...
    def setaccount(self, address: str, account: str) -> None: ...
    def settxfee(self, amount: Decimal) -> bool: ...
    def signmessage(self, address: str, message: str) -> str: ...
    def walletlock(self) -> None: ...
    def walletpassphrase(self, passphrase: str, timeout: int) -> None: ...
    def walletpassphrasechange(self, oldpassphrase: str, newpassphrase: str) -> None: ... 