Reformat auxiliary files

pycryptodomex
Michał Sałaban 2 years ago
parent b13b2b14ce
commit 35c806395a

@ -19,7 +19,8 @@
# #
import os import os
import sys import sys
sys.path.insert(0, os.path.abspath('../..'))
sys.path.insert(0, os.path.abspath("../.."))
# -- General configuration ------------------------------------------------ # -- General configuration ------------------------------------------------
@ -31,33 +32,33 @@ sys.path.insert(0, os.path.abspath('../..'))
# Add any Sphinx extension module names here, as strings. They can be # Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones. # ones.
extensions = ['sphinx.ext.autodoc'] extensions = ["sphinx.ext.autodoc"]
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates'] templates_path = ["_templates"]
# The suffix(es) of source filenames. # The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string: # You can specify multiple suffix as a list of string:
# #
# source_suffix = ['.rst', '.md'] # source_suffix = ['.rst', '.md']
source_suffix = '.rst' source_suffix = ".rst"
# The master toctree document. # The master toctree document.
master_doc = 'index' master_doc = "index"
# General information about the project. # General information about the project.
project = 'Monero Python module' project = "Monero Python module"
copyright = '2018, Michal Salaban' copyright = "2018, Michal Salaban"
author = 'Michal Salaban' author = "Michal Salaban"
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '0.9' version = "0.9"
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.9' release = "0.9"
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
@ -72,7 +73,7 @@ language = None
exclude_patterns = [] exclude_patterns = []
# The name of the Pygments (syntax highlighting) style to use. # The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx' pygments_style = "sphinx"
# If true, `todo` and `todoList` produce output, else they produce nothing. # If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False todo_include_todos = False
@ -83,7 +84,7 @@ todo_include_todos = False
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
# #
html_theme = 'alabaster' html_theme = "alabaster"
# Theme options are theme-specific and customize the look and feel of a theme # Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the # further. For a list of options available for each theme, see the
@ -94,7 +95,7 @@ html_theme = 'alabaster'
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static'] html_static_path = ["_static"]
# Custom sidebar templates, must be a dictionary that maps document names # Custom sidebar templates, must be a dictionary that maps document names
# to template names. # to template names.
@ -102,21 +103,18 @@ html_static_path = ['_static']
# This is required for the alabaster theme # This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
html_sidebars = { html_sidebars = {
'index': [ "index": [
'relations.html', # needs 'show_related': True theme option to display "relations.html", # needs 'show_related': True theme option to display
'searchbox.html' "searchbox.html",
], ],
'**': [ "**": ["searchbox.html", "globaltoc.html"],
'searchbox.html',
'globaltoc.html'
]
} }
# -- Options for HTMLHelp output ------------------------------------------ # -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = 'MoneroPythonmoduledoc' htmlhelp_basename = "MoneroPythonmoduledoc"
# -- Options for LaTeX output --------------------------------------------- # -- Options for LaTeX output ---------------------------------------------
@ -125,15 +123,12 @@ latex_elements = {
# The paper size ('letterpaper' or 'a4paper'). # The paper size ('letterpaper' or 'a4paper').
# #
# 'papersize': 'letterpaper', # 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt'). # The font size ('10pt', '11pt' or '12pt').
# #
# 'pointsize': '10pt', # 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble. # Additional stuff for the LaTeX preamble.
# #
# 'preamble': '', # 'preamble': '',
# Latex figure (float) alignment # Latex figure (float) alignment
# #
# 'figure_align': 'htbp', # 'figure_align': 'htbp',
@ -143,8 +138,13 @@ latex_elements = {
# (source start file, target name, title, # (source start file, target name, title,
# author, documentclass [howto, manual, or own class]). # author, documentclass [howto, manual, or own class]).
latex_documents = [ latex_documents = [
(master_doc, 'MoneroPythonmodule.tex', 'Monero Python module Documentation', (
'Michal Salaban', 'manual'), master_doc,
"MoneroPythonmodule.tex",
"Monero Python module Documentation",
"Michal Salaban",
"manual",
),
] ]
@ -153,8 +153,13 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
(master_doc, 'moneropythonmodule', 'Monero Python module Documentation', (
[author], 1) master_doc,
"moneropythonmodule",
"Monero Python module Documentation",
[author],
1,
)
] ]
@ -164,7 +169,13 @@ man_pages = [
# (source start file, target name, title, author, # (source start file, target name, title, author,
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [
(master_doc, 'MoneroPythonmodule', 'Monero Python module Documentation', (
author, 'MoneroPythonmodule', 'One line description of project.', master_doc,
'Miscellaneous'), "MoneroPythonmodule",
"Monero Python module Documentation",
author,
"MoneroPythonmodule",
"One line description of project.",
"Miscellaneous",
),
] ]

@ -16,47 +16,48 @@ def find_version(*parts):
Figure out version number without importing the package. Figure out version number without importing the package.
https://packaging.python.org/guides/single-sourcing-package-version/ https://packaging.python.org/guides/single-sourcing-package-version/
""" """
with codecs.open(os.path.join(here, *parts), 'r', errors='ignore') as fp: with codecs.open(os.path.join(here, *parts), "r", errors="ignore") as fp:
version_file = fp.read() version_file = fp.read()
version_match = re.search(r"^__version__ = ['\"](.*)['\"]", version_match = re.search(r"^__version__ = ['\"](.*)['\"]", version_file, re.M)
version_file, re.M)
if version_match: if version_match:
return version_match.group(1) return version_match.group(1)
raise RuntimeError("Unable to find version string.") raise RuntimeError("Unable to find version string.")
version = find_version('monero', '__init__.py') version = find_version("monero", "__init__.py")
setup( setup(
name = 'monero', name="monero",
version = version, version=version,
description = 'A comprehensive Python module for handling Monero cryptocurrency', description="A comprehensive Python module for handling Monero cryptocurrency",
url = 'https://github.com/monero-ecosystem/monero-python/', url="https://github.com/monero-ecosystem/monero-python/",
long_description = open('README.rst', 'rb').read().decode('utf-8'), long_description=open("README.rst", "rb").read().decode("utf-8"),
install_requires = open('requirements.txt', 'r').read().splitlines(), install_requires=open("requirements.txt", "r").read().splitlines(),
tests_require=open( tests_require=open(
'test_requirements_py{:d}.txt'.format(sys.version_info.major), "test_requirements_py{:d}.txt".format(sys.version_info.major), "r"
'r').read().splitlines(), )
packages = find_packages('.', exclude=['tests']), .read()
include_package_data = True, .splitlines(),
author = 'Michał Sałaban', packages=find_packages(".", exclude=["tests"]),
author_email = 'michal@salaban.info', include_package_data=True,
license = 'BSD-3-Clause', author="Michał Sałaban",
classifiers = [ author_email="michal@salaban.info",
'Development Status :: 4 - Beta', license="BSD-3-Clause",
'Intended Audience :: Developers', classifiers=[
'License :: OSI Approved :: BSD License', "Development Status :: 4 - Beta",
'Operating System :: OS Independent', "Intended Audience :: Developers",
'Programming Language :: Python', "License :: OSI Approved :: BSD License",
'Programming Language :: Python :: 2.7', "Operating System :: OS Independent",
'Programming Language :: Python :: 3.6', "Programming Language :: Python",
'Programming Language :: Python :: 3.7', "Programming Language :: Python :: 2.7",
'Programming Language :: Python :: 3.8', "Programming Language :: Python :: 3.6",
'Programming Language :: Python :: 3.8', "Programming Language :: Python :: 3.7",
'Programming Language :: Python :: 3.9', "Programming Language :: Python :: 3.8",
'Programming Language :: Python :: 3.10', "Programming Language :: Python :: 3.8",
'Topic :: Software Development :: Libraries :: Python Modules', "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Topic :: Software Development :: Libraries :: Python Modules",
], ],
keywords = 'monero cryptocurrency', keywords="monero cryptocurrency",
test_suite='tests', test_suite="tests",
) )

@ -7,20 +7,34 @@ import re
from monero.backends.jsonrpc import JSONRPCDaemon from monero.backends.jsonrpc import JSONRPCDaemon
from monero.daemon import Daemon from monero.daemon import Daemon
def url_data(url): def url_data(url):
gs = re.compile( gs = re.compile(r"^(?P<host>[^:\s]+)(?::(?P<port>[0-9]+))?$").match(url).groupdict()
r'^(?P<host>[^:\s]+)(?::(?P<port>[0-9]+))?$'
).match(url).groupdict()
return dict(filter(operator.itemgetter(1), gs.items())) return dict(filter(operator.itemgetter(1), gs.items()))
def get_daemon(): def get_daemon():
argsparser = argparse.ArgumentParser(description="Display daemon info") argsparser = argparse.ArgumentParser(description="Display daemon info")
argsparser.add_argument('daemon_rpc_url', nargs='?', type=url_data, default='127.0.0.1:18081', argsparser.add_argument(
help="Daemon RPC URL [host[:port]]") "daemon_rpc_url",
argsparser.add_argument('-p', dest='proxy_url', nargs='?', type=str, default=None, help="Proxy URL") nargs="?",
argsparser.add_argument('-t', dest='timeout', type=int, default=30, help="Request timeout") type=url_data,
argsparser.add_argument('-v', dest='verbosity', action='count', default=0, default="127.0.0.1:18081",
help="Verbosity (repeat to increase; -v for INFO, -vv for DEBUG") help="Daemon RPC URL [host[:port]]",
)
argsparser.add_argument(
"-p", dest="proxy_url", nargs="?", type=str, default=None, help="Proxy URL"
)
argsparser.add_argument(
"-t", dest="timeout", type=int, default=30, help="Request timeout"
)
argsparser.add_argument(
"-v",
dest="verbosity",
action="count",
default=0,
help="Verbosity (repeat to increase; -v for INFO, -vv for DEBUG",
)
args = argsparser.parse_args() args = argsparser.parse_args()
level = logging.WARNING level = logging.WARNING
if args.verbosity == 1: if args.verbosity == 1:
@ -28,23 +42,36 @@ def get_daemon():
elif args.verbosity > 1: elif args.verbosity > 1:
level = logging.DEBUG level = logging.DEBUG
logging.basicConfig(level=level, format="%(asctime)-15s %(message)s") logging.basicConfig(level=level, format="%(asctime)-15s %(message)s")
return Daemon(JSONRPCDaemon(timeout=args.timeout, proxy_url=args.proxy_url, **args.daemon_rpc_url)) return Daemon(
JSONRPCDaemon(
timeout=args.timeout, proxy_url=args.proxy_url, **args.daemon_rpc_url
)
)
d = get_daemon() d = get_daemon()
info = d.info() info = d.info()
print("Net: {net:>20s}net\n" print(
"Net: {net:>20s}net\n"
"Height: {height:15d}\n" "Height: {height:15d}\n"
"Difficulty: {difficulty:15d}\n" "Difficulty: {difficulty:15d}\n"
"Alt blocks: {alt_blocks_count:15d}\n".format( "Alt blocks: {alt_blocks_count:15d}\n".format(
net='test' if info['testnet'] \ net="test"
else 'stage' if info['stagenet'] \ if info["testnet"]
else 'main' if info['mainnet'] else 'unknown', else "stage"
**info)) if info["stagenet"]
else "main"
if info["mainnet"]
else "unknown",
**info
)
)
print("Last 6 blocks:") print("Last 6 blocks:")
for hdr in reversed(d.headers(info['height']-6, info['height']-1)): for hdr in reversed(d.headers(info["height"] - 6, info["height"] - 1)):
print("{height:10d} {hash} {block_size_kb:6.2f} kB {num_txes:3d} txn(s) " print(
"v{major_version:d}".format( "{height:10d} {hash} {block_size_kb:6.2f} kB {num_txes:3d} txn(s) "
block_size_kb=hdr['block_size']/1024.0, **hdr)) "v{major_version:d}".format(block_size_kb=hdr["block_size"] / 1024.0, **hdr)
)
mempool = d.mempool() mempool = d.mempool()
if mempool: if mempool:
print("\n{:d} txn(s) in mempool:".format(len(mempool))) print("\n{:d} txn(s) in mempool:".format(len(mempool)))

@ -11,24 +11,46 @@ from monero.daemon import Daemon
from monero.transaction import Transaction from monero.transaction import Transaction
from monero import exceptions from monero import exceptions
def url_data(url): def url_data(url):
gs = re.compile( gs = re.compile(r"^(?P<host>[^:\s]+)(?::(?P<port>[0-9]+))?$").match(url).groupdict()
r'^(?P<host>[^:\s]+)(?::(?P<port>[0-9]+))?$'
).match(url).groupdict()
return dict(filter(operator.itemgetter(1), gs.items())) return dict(filter(operator.itemgetter(1), gs.items()))
argsparser = argparse.ArgumentParser(description="Push transaction to network") argsparser = argparse.ArgumentParser(description="Push transaction to network")
argsparser.add_argument('daemon_rpc_url', nargs='?', type=url_data, default='127.0.0.1:18081', argsparser.add_argument(
help="Daemon RPC URL [host[:port]]") "daemon_rpc_url",
argsparser.add_argument('-v', dest='verbosity', action='count', default=0, nargs="?",
help="Verbosity (repeat to increase; -v for INFO, -vv for DEBUG") type=url_data,
argsparser.add_argument('-p', dest='proxy_url', nargs='?', type=str, default=None, default="127.0.0.1:18081",
help="Proxy URL") help="Daemon RPC URL [host[:port]]",
argsparser.add_argument('-t', dest='timeout', type=int, default=30, help="Request timeout") )
argsparser.add_argument('-i', dest='tx_filenames', nargs='+', default=None, argsparser.add_argument(
help="Files with transaction data. Will read from stdin if not given.") "-v",
argsparser.add_argument('--no-relay', dest='relay', action='store_false', dest="verbosity",
help="Do not relay the transaction (it will stay at the node unless mined or expired)") action="count",
default=0,
help="Verbosity (repeat to increase; -v for INFO, -vv for DEBUG",
)
argsparser.add_argument(
"-p", dest="proxy_url", nargs="?", type=str, default=None, help="Proxy URL"
)
argsparser.add_argument(
"-t", dest="timeout", type=int, default=30, help="Request timeout"
)
argsparser.add_argument(
"-i",
dest="tx_filenames",
nargs="+",
default=None,
help="Files with transaction data. Will read from stdin if not given.",
)
argsparser.add_argument(
"--no-relay",
dest="relay",
action="store_false",
help="Do not relay the transaction (it will stay at the node unless mined or expired)",
)
args = argsparser.parse_args() args = argsparser.parse_args()
level = logging.WARNING level = logging.WARNING
if args.verbosity == 1: if args.verbosity == 1:
@ -37,20 +59,22 @@ elif args.verbosity > 1:
level = logging.DEBUG level = logging.DEBUG
logging.basicConfig(level=level, format="%(asctime)-15s %(message)s") logging.basicConfig(level=level, format="%(asctime)-15s %(message)s")
if args.tx_filenames: if args.tx_filenames:
blobs = [(f, open(f, 'rb').read()) for f in args.tx_filenames] blobs = [(f, open(f, "rb").read()) for f in args.tx_filenames]
else: else:
blobs = [('transaction', sys.stdin.buffer.read() if six.PY3 else sys.stdin.read())] blobs = [("transaction", sys.stdin.buffer.read() if six.PY3 else sys.stdin.read())]
d = Daemon(JSONRPCDaemon(timeout=args.timeout, proxy_url=args.proxy_url, **args.daemon_rpc_url)) d = Daemon(
JSONRPCDaemon(timeout=args.timeout, proxy_url=args.proxy_url, **args.daemon_rpc_url)
)
for name, blob in blobs: for name, blob in blobs:
logging.debug("Sending {}".format(name)) logging.debug("Sending {}".format(name))
tx = Transaction(blob=blob) tx = Transaction(blob=blob)
try: try:
res = d.send_transaction(tx, relay=args.relay) res = d.send_transaction(tx, relay=args.relay)
except exceptions.TransactionBroadcastError as e: except exceptions.TransactionBroadcastError as e:
print("{} not sent, reason: {}".format(name, e.details['reason'])) print("{} not sent, reason: {}".format(name, e.details["reason"]))
logging.debug(e.details) logging.debug(e.details)
continue continue
if res['not_relayed']: if res["not_relayed"]:
print("{} not relayed".format(name)) print("{} not relayed".format(name))
else: else:
print("{} successfully sent".format(name)) print("{} successfully sent".format(name))

@ -11,31 +11,66 @@ from monero.numbers import as_monero
from monero.wallet import Wallet from monero.wallet import Wallet
from monero.backends.jsonrpc import JSONRPCWallet from monero.backends.jsonrpc import JSONRPCWallet
def url_data(url): def url_data(url):
gs = re.compile( gs = (
r'^(?:(?P<user>[a-z0-9_-]+)?(?::(?P<password>[^@]+))?@)?(?P<host>[^:\s]+)(?::(?P<port>[0-9]+))?$' re.compile(
).match(url).groupdict() r"^(?:(?P<user>[a-z0-9_-]+)?(?::(?P<password>[^@]+))?@)?(?P<host>[^:\s]+)(?::(?P<port>[0-9]+))?$"
)
.match(url)
.groupdict()
)
return dict(filter(operator.itemgetter(1), gs.items())) return dict(filter(operator.itemgetter(1), gs.items()))
def destpair(s): def destpair(s):
addr, amount = s.split(':') addr, amount = s.split(":")
return (address(addr), as_monero(amount)) return (address(addr), as_monero(amount))
argsparser = argparse.ArgumentParser(description="Transfer Monero") argsparser = argparse.ArgumentParser(description="Transfer Monero")
argsparser.add_argument('-v', dest='verbosity', action='count', default=0, argsparser.add_argument(
help="Verbosity (repeat to increase; -v for INFO, -vv for DEBUG") "-v",
argsparser.add_argument('wallet_rpc_url', nargs='?', type=url_data, default='127.0.0.1:18082', dest="verbosity",
help="Wallet RPC URL [user[:password]@]host[:port]") action="count",
argsparser.add_argument('-t', dest='timeout', type=int, default=30, help="Request timeout") default=0,
argsparser.add_argument('-a', dest='account', default=0, type=int, help="Source account index") help="Verbosity (repeat to increase; -v for INFO, -vv for DEBUG",
argsparser.add_argument('-p', dest='prio', )
choices=['unimportant', 'normal', 'elevated', 'priority'], argsparser.add_argument(
default='normal') "wallet_rpc_url",
argsparser.add_argument('--save', dest='outdir', nargs='?', default=None, const='.', nargs="?",
type=url_data,
default="127.0.0.1:18082",
help="Wallet RPC URL [user[:password]@]host[:port]",
)
argsparser.add_argument(
"-t", dest="timeout", type=int, default=30, help="Request timeout"
)
argsparser.add_argument(
"-a", dest="account", default=0, type=int, help="Source account index"
)
argsparser.add_argument(
"-p",
dest="prio",
choices=["unimportant", "normal", "elevated", "priority"],
default="normal",
)
argsparser.add_argument(
"--save",
dest="outdir",
nargs="?",
default=None,
const=".",
help="Save to file, optionally follow by destination directory (default is .)\n" help="Save to file, optionally follow by destination directory (default is .)\n"
"Transaction will be not relayed to the network.") "Transaction will be not relayed to the network.",
argsparser.add_argument('destinations', metavar='address:amount', nargs='+', type=destpair, )
help="Destination address and amount (one or more pairs)") argsparser.add_argument(
"destinations",
metavar="address:amount",
nargs="+",
type=destpair,
help="Destination address and amount (one or more pairs)",
)
args = argsparser.parse_args() args = argsparser.parse_args()
prio = getattr(monero.const, "PRIO_{:s}".format(args.prio.upper())) prio = getattr(monero.const, "PRIO_{:s}".format(args.prio.upper()))
@ -48,16 +83,18 @@ logging.basicConfig(level=level, format="%(asctime)-15s %(message)s")
w = Wallet(JSONRPCWallet(timeout=args.timeout, **args.wallet_rpc_url)) w = Wallet(JSONRPCWallet(timeout=args.timeout, **args.wallet_rpc_url))
txns = w.accounts[args.account].transfer_multiple( txns = w.accounts[args.account].transfer_multiple(
args.destinations, priority=prio, args.destinations, priority=prio, relay=args.outdir is None
relay=args.outdir is None) )
for tx in txns: for tx in txns:
print(u"Transaction {hash}:\nfee: {fee:21.12f}\n" print(
u"Tx key: {key}\nSize: {size} B".format( u"Transaction {hash}:\nfee: {fee:21.12f}\n"
hash=tx.hash, fee=tx.fee, u"Tx key: {key}\nSize: {size} B".format(
key=tx.key, size=len(tx.blob) >> 1)) hash=tx.hash, fee=tx.fee, key=tx.key, size=len(tx.blob) >> 1
)
)
if args.outdir: if args.outdir:
outname = os.path.join(args.outdir, tx.hash + '.tx') outname = os.path.join(args.outdir, tx.hash + ".tx")
outfile = open(outname, 'wb') outfile = open(outname, "wb")
outfile.write(tx.blob) outfile.write(tx.blob)
outfile.close() outfile.close()
print(u"Transaction saved to {}".format(outname)) print(u"Transaction saved to {}".format(outname))

@ -8,19 +8,37 @@ from monero import exceptions
from monero.backends.jsonrpc import JSONRPCWallet, RPCError from monero.backends.jsonrpc import JSONRPCWallet, RPCError
from monero.wallet import Wallet from monero.wallet import Wallet
def url_data(url): def url_data(url):
gs = re.compile( gs = (
r'^(?:(?P<user>[a-z0-9_-]+)?(?::(?P<password>[^@]+))?@)?(?P<host>[^:\s]+)(?::(?P<port>[0-9]+))?$' re.compile(
).match(url).groupdict() r"^(?:(?P<user>[a-z0-9_-]+)?(?::(?P<password>[^@]+))?@)?(?P<host>[^:\s]+)(?::(?P<port>[0-9]+))?$"
)
.match(url)
.groupdict()
)
return dict(filter(operator.itemgetter(1), gs.items())) return dict(filter(operator.itemgetter(1), gs.items()))
def get_wallet(): def get_wallet():
argsparser = argparse.ArgumentParser(description="Display wallet contents") argsparser = argparse.ArgumentParser(description="Display wallet contents")
argsparser.add_argument('wallet_rpc_url', nargs='?', type=url_data, default='127.0.0.1:18082', argsparser.add_argument(
help="Wallet RPC URL [user[:password]@]host[:port]") "wallet_rpc_url",
argsparser.add_argument('-v', dest='verbosity', action='count', default=0, nargs="?",
help="Verbosity (repeat to increase; -v for INFO, -vv for DEBUG") type=url_data,
argsparser.add_argument('-t', dest='timeout', type=int, default=30, help="Request timeout") default="127.0.0.1:18082",
help="Wallet RPC URL [user[:password]@]host[:port]",
)
argsparser.add_argument(
"-v",
dest="verbosity",
action="count",
default=0,
help="Verbosity (repeat to increase; -v for INFO, -vv for DEBUG",
)
argsparser.add_argument(
"-t", dest="timeout", type=int, default=30, help="Request timeout"
)
args = argsparser.parse_args() args = argsparser.parse_args()
level = logging.WARNING level = logging.WARNING
if args.verbosity == 1: if args.verbosity == 1:
@ -30,76 +48,95 @@ def get_wallet():
logging.basicConfig(level=level, format="%(asctime)-15s %(message)s") logging.basicConfig(level=level, format="%(asctime)-15s %(message)s")
return Wallet(JSONRPCWallet(timeout=args.timeout, **args.wallet_rpc_url)) return Wallet(JSONRPCWallet(timeout=args.timeout, **args.wallet_rpc_url))
_TXHDR = "timestamp height id/hash " \
" amount fee {dir:95s} payment_id" _TXHDR = (
"timestamp height id/hash "
" amount fee {dir:95s} payment_id"
)
def pmt2str(pmt): def pmt2str(pmt):
res = ["{time} {height:7d} {hash} {amount:17.12f} {fee:13.12f} {addr} {payment_id}".format( res = [
time=pmt.timestamp.strftime("%d-%m-%y %H:%M:%S") if getattr(pmt, 'timestamp', None) else None, "{time} {height:7d} {hash} {amount:17.12f} {fee:13.12f} {addr} {payment_id}".format(
height=pmt.transaction.height or 0, time=pmt.timestamp.strftime("%d-%m-%y %H:%M:%S")
hash=pmt.transaction.hash, if getattr(pmt, "timestamp", None)
amount=pmt.amount, else None,
fee=pmt.transaction.fee or 0, height=pmt.transaction.height or 0,
payment_id=pmt.payment_id, hash=pmt.transaction.hash,
addr=getattr(pmt, 'local_address', None) or '')] amount=pmt.amount,
fee=pmt.transaction.fee or 0,
payment_id=pmt.payment_id,
addr=getattr(pmt, "local_address", None) or "",
)
]
try: try:
for dest in pmt.destinations: for dest in pmt.destinations:
res.append(" {amount:17.12f} to {address}".format(address=dest[0], amount=dest[1])) res.append(
" {amount:17.12f} to {address}".format(
address=dest[0], amount=dest[1]
)
)
except AttributeError: except AttributeError:
pass pass
return "\n".join(res) return "\n".join(res)
def a2str(a): def a2str(a):
return "{addr} {label}".format( return "{addr} {label}".format(addr=a, label=a.label or "")
addr=a,
label=a.label or "")
w = get_wallet() w = get_wallet()
masteraddr = w.address() masteraddr = w.address()
print( print(
"Master address: {addr}\n" \ "Master address: {addr}\n"
"Balance: {total:16.12f} ({unlocked:16.12f} unlocked)".format( "Balance: {total:16.12f} ({unlocked:16.12f} unlocked)".format(
addr=a2str(masteraddr), addr=a2str(masteraddr), total=w.balance(), unlocked=w.balance(unlocked=True)
total=w.balance(), )
unlocked=w.balance(unlocked=True))) )
try: try:
seed = w.seed() seed = w.seed()
except (exceptions.WalletIsNotDeterministic, RPCError): # FIXME: Remove RPCError once PR#4563 is merged in monero except (
seed = '[--- wallet is not deterministic and has no seed ---]' exceptions.WalletIsNotDeterministic,
RPCError,
): # FIXME: Remove RPCError once PR#4563 is merged in monero
seed = "[--- wallet is not deterministic and has no seed ---]"
print( print(
"Keys:\n" \ "Keys:\n"
" private spend: {ssk}\n" \ " private spend: {ssk}\n"
" private view: {svk}\n" \ " private view: {svk}\n"
" public spend: {psk}\n" \ " public spend: {psk}\n"
" public view: {pvk}\n\n" \ " public view: {pvk}\n\n"
"Seed:\n{seed}".format( "Seed:\n{seed}".format(
ssk=w.spend_key(), ssk=w.spend_key(),
svk=w.view_key(), svk=w.view_key(),
psk=masteraddr.spend_key(), psk=masteraddr.spend_key(),
pvk=masteraddr.view_key(), pvk=masteraddr.view_key(),
seed=seed seed=seed,
)) )
)
if len(w.accounts) > 1: if len(w.accounts) > 1:
print("\nWallet has {num} account(s):".format(num=len(w.accounts))) print("\nWallet has {num} account(s):".format(num=len(w.accounts)))
for acc in w.accounts: for acc in w.accounts:
print("\nAccount {idx:02d}:".format(idx=acc.index)) print("\nAccount {idx:02d}:".format(idx=acc.index))
print("Balance: {total:16.12f} ({unlocked:16.12f} unlocked)".format( print(
total=acc.balance(), "Balance: {total:16.12f} ({unlocked:16.12f} unlocked)".format(
unlocked=acc.balance(unlocked=True))) total=acc.balance(), unlocked=acc.balance(unlocked=True)
)
)
addresses = acc.addresses() addresses = acc.addresses()
print("{num:2d} address(es):".format(num=len(addresses))) print("{num:2d} address(es):".format(num=len(addresses)))
print("\n".join(map(a2str, addresses))) print("\n".join(map(a2str, addresses)))
ins = acc.incoming(unconfirmed=True) ins = acc.incoming(unconfirmed=True)
if ins: if ins:
print("\nIncoming transactions:") print("\nIncoming transactions:")
print(_TXHDR.format(dir='received by')) print(_TXHDR.format(dir="received by"))
for tx in ins: for tx in ins:
print(pmt2str(tx)) print(pmt2str(tx))
outs = acc.outgoing(unconfirmed=True) outs = acc.outgoing(unconfirmed=True)
if outs: if outs:
print("\nOutgoing transactions:") print("\nOutgoing transactions:")
print(_TXHDR.format(dir='sent from')) print(_TXHDR.format(dir="sent from"))
for tx in outs: for tx in outs:
print(pmt2str(tx)) print(pmt2str(tx))
else: else:
@ -109,12 +146,12 @@ else:
ins = w.incoming(unconfirmed=True) ins = w.incoming(unconfirmed=True)
if ins: if ins:
print("\nIncoming transactions:") print("\nIncoming transactions:")
print(_TXHDR.format(dir='received by')) print(_TXHDR.format(dir="received by"))
for tx in ins: for tx in ins:
print(pmt2str(tx)) print(pmt2str(tx))
outs = w.outgoing(unconfirmed=True) outs = w.outgoing(unconfirmed=True)
if outs: if outs:
print("\nOutgoing transactions:") print("\nOutgoing transactions:")
print(_TXHDR.format(dir='sent from')) print(_TXHDR.format(dir="sent from"))
for tx in outs: for tx in outs:
print(pmt2str(tx)) print(pmt2str(tx))

Loading…
Cancel
Save