├── .gitignore ├── .pre-commit-config.yaml ├── .travis.yml ├── CHANGELOG.rst ├── LICENSE ├── README.rst ├── coverage.sh ├── coverage.svg ├── docs ├── Makefile ├── conf.py ├── generate.py ├── index.rst ├── nano.rst ├── readme.rst ├── rpc │ ├── index.rst │ └── methods │ │ ├── account.rst │ │ ├── block.rst │ │ ├── global.rst │ │ ├── node.rst │ │ ├── utility.rst │ │ ├── wallet.rst │ │ └── work.rst └── utilities.rst ├── requirements-dev.pip ├── requirements.pip ├── setup.cfg ├── setup.py ├── src └── nano │ ├── __init__.py │ ├── accounts.py │ ├── blocks.py │ ├── conversion.py │ ├── crypto.py │ ├── ed25519_blake2.py │ ├── rpc.py │ └── version.py └── tests ├── conftest.py ├── fixtures └── rpc │ ├── account_balance.json │ ├── account_block_count.json │ ├── account_create.json │ ├── account_get.json │ ├── account_history.json │ ├── account_info.json │ ├── account_key.json │ ├── account_list.json │ ├── account_move.json │ ├── account_remove.json │ ├── account_representative.json │ ├── account_representative_set.json │ ├── account_weight.json │ ├── accounts_balances.json │ ├── accounts_create.json │ ├── accounts_frontiers.json │ ├── accounts_pending.json │ ├── available_supply.json │ ├── block.json │ ├── block_account.json │ ├── block_count.json │ ├── block_count_type.json │ ├── block_create.json │ ├── blocks.json │ ├── blocks_info.json │ ├── bootstrap.json │ ├── bootstrap_any.json │ ├── chain.json │ ├── delegators.json │ ├── delegators_count.json │ ├── deterministic_key.json │ ├── frontier_count.json │ ├── frontiers.json │ ├── history.json │ ├── keepalive.json │ ├── key_create.json │ ├── key_expand.json │ ├── krai_from_raw.json │ ├── krai_to_raw.json │ ├── ledger.json │ ├── mrai_from_raw.json │ ├── mrai_to_raw.json │ ├── password_change.json │ ├── password_enter.json │ ├── password_valid.json │ ├── payment_begin.json │ ├── payment_end.json │ ├── payment_init.json │ ├── payment_wait.json │ ├── peers.json │ ├── pending.json │ ├── pending_exists.json │ ├── process.json │ ├── rai_from_raw.json │ ├── rai_to_raw.json │ ├── receive.json │ ├── receive_minimum.json │ ├── receive_minimum_set.json │ ├── representatives.json │ ├── republish.json │ ├── search_pending.json │ ├── search_pending_all.json │ ├── send.json │ ├── stop.json │ ├── successors.json │ ├── unchecked.json │ ├── unchecked_clear.json │ ├── unchecked_get.json │ ├── unchecked_keys.json │ ├── validate_account_number.json │ ├── version.json │ ├── wallet_add.json │ ├── wallet_balance_total.json │ ├── wallet_balances.json │ ├── wallet_change_seed.json │ ├── wallet_contains.json │ ├── wallet_create.json │ ├── wallet_destroy.json │ ├── wallet_export.json │ ├── wallet_frontiers.json │ ├── wallet_key_valid.json │ ├── wallet_lock.json │ ├── wallet_locked.json │ ├── wallet_pending.json │ ├── wallet_representative.json │ ├── wallet_representative_set.json │ ├── wallet_republish.json │ ├── wallet_unlock.json │ ├── wallet_work_get.json │ ├── work_cancel.json │ ├── work_generate.json │ ├── work_get.json │ ├── work_peer_add.json │ ├── work_peers.json │ ├── work_peers_clear.json │ ├── work_set.json │ └── work_validate.json ├── test_accounts.py ├── test_conversion.py ├── test_crypto.py ├── test_mock_rpc.py ├── test_rpc.py └── test_version.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | # PyCharm 104 | .idea/ 105 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: git://github.com/pre-commit/pre-commit-hooks 3 | rev: v2.1.0 4 | hooks: 5 | - id: trailing-whitespace 6 | - id: check-added-large-files 7 | - id: check-ast 8 | - id: check-byte-order-marker 9 | - id: check-json 10 | - id: check-merge-conflict 11 | - id: check-yaml 12 | - id: debug-statements 13 | - id: detect-private-key 14 | - id: end-of-file-fixer 15 | - id: fix-encoding-pragma 16 | args: [--remove] 17 | - id: mixed-line-ending 18 | args: ['--fix=crlf'] 19 | - repo: https://github.com/ambv/black 20 | rev: 18.9b0 21 | hooks: 22 | - id: black 23 | args: [-v, --skip-string-normalization, tests, setup.py, src] 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | - "2.7" 5 | - "3.7" 6 | - "3.6" 7 | 8 | dist: xenial 9 | 10 | install: 11 | - pip install -r requirements.pip 12 | - pip install -r requirements-dev.pip 13 | - pip install -e . 14 | 15 | script: bash coverage.sh 16 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | 5 | Version 2.1.0 (2019-02-09) 6 | -------------------------- 7 | 8 | - Updates the conversion tools to current nomenclature 9 | 10 | 11 | Version 2.0.1 (2018-02-17) 12 | -------------------------- 13 | 14 | - Add "id" parameter to `nano.rpc.Client.send` method to avoiding dup sends 15 | 16 | 17 | Version 2.0.0 (2018-02-11) 18 | -------------------------- 19 | 20 | - Nano rebrand - the `raiblocks` module has been replaced with `nano` 21 | - Pypi package name is now `nano-python` 22 | - Use `import nano` instead of `import raiblocks` 23 | - rpc client has been renamed from `nano.rpc.RPCClient` to `nano.rpc.Client` 24 | 25 | 26 | Version 1.1.0 (2018-02-11) 27 | -------------------------- 28 | 29 | - RPC no longer automatically retries backend calls since this could lead to 30 | double sends when a `send` call was issued twice due to a timeout 31 | - RPC `.delegators()` now returns voting weights as integers instead of strings 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Daniel Dourvaris 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | Nano (RaiBlocks) Python Library 3 | =============================== 4 | 5 | .. image:: https://img.shields.io/pypi/l/nano-python.svg 6 | :target: https://github.com/dourvaris/nano-python/blob/master/LICENSE 7 | 8 | .. image:: https://travis-ci.org/dourvaris/nano-python.svg?branch=1.0.0rc1 9 | :target: https://travis-ci.org/dourvaris/nano-python 10 | 11 | .. image:: https://readthedocs.org/projects/nano-python/badge/?version=latest 12 | :target: http://nano-python.readthedocs.io/en/latest/?badge=latest 13 | :alt: Documentation Status 14 | 15 | .. image:: https://github.com/dourvaris/nano-python/raw/master/coverage.svg?sanitize=true 16 | :target: https://travis-ci.org/dourvaris/nano-python 17 | 18 | .. image:: https://img.shields.io/pypi/pyversions/nano-python.svg?style=flat-square 19 | :target: https://pypi.python.org/pypi/nano-python 20 | 21 | .. image:: https://img.shields.io/pypi/v/nano-python.svg 22 | :target: https://pypi.python.org/pypi/nano-python 23 | 24 | This library contains a python wrapper for the Nano (RaiBlocks) RPC server 25 | which tries to make it a little easier to work with by converting RPC responses 26 | to native python ones and exposing a pythonic api for making RPC calls. 27 | 28 | Also included are utilities such as converting rai/xrb and interesting accounts 29 | 30 | 31 | Installation 32 | ============ 33 | 34 | .. code-block:: text 35 | 36 | pip install nano-python 37 | 38 | Documentation 39 | ============= 40 | 41 | https://nano-python.readthedocs.io/ 42 | 43 | RPC client 44 | ========== 45 | 46 | You can browse the available 47 | `RPC methods list `_ 48 | or check the 49 | `RPC Client API documentation `_ 50 | for examples of usage. 51 | 52 | .. warning:: The RPC client **DOES NOT** handle timeouts or retries 53 | automatically since this could lead to unwanted retries of requests 54 | causing **double spends**. Keep this in mind when implementing retries. 55 | 56 | When using version 10.0 of the RPC node, use the send id when making spends 57 | as described at https://github.com/nanocurrency/raiblocks/wiki/RPC-protocol#highly-recommended-id 58 | 59 | .. code-block:: python 60 | 61 | >>> import nano 62 | >>> rpc = nano.rpc.Client('http://localhost:7076') 63 | >>> rpc.version() 64 | { 65 | 'rpc_version': 1, 66 | 'store_version': 10, 67 | 'node_vendor': 'RaiBlocks 9.0' 68 | } 69 | >>> rpc.peers() 70 | { 71 | '[::ffff:75.171.168.5]:7075': 4, 72 | '[::ffff:108.44.38.183]:1032': 4 73 | } 74 | 75 | Crypto/Accounts 76 | =============== 77 | 78 | .. code-block:: python 79 | >>> from nano import generate_account, verify_signature, sign_message 80 | >>> account = generate_account(seed='someseed') 81 | >>> signature = sign_message(b'this', account['private_key_bytes']) 82 | >>> verify_signature(b'this', signature, account['public_key_bytes']) 83 | True 84 | >>> verify_signature(b'that', signature, account['public_key_bytes']) 85 | False 86 | 87 | 88 | Conversion 89 | ========== 90 | 91 | .. code-block:: python 92 | 93 | >>> from nano import convert 94 | >>> convert(12, from_unit='XRB', to_unit='raw') 95 | Decimal('1.2E+31') 96 | 97 | >>> convert(0.4, from_unit='krai', to_unit='XRB') 98 | Traceback (most recent call last): 99 | File "", line 1, in 100 | ValueError: float values can lead to unexpected 101 | precision loss, please use a Decimal or string 102 | eg. convert('0.4', 'krai', 'XRB') 103 | 104 | >>> convert('0.4', from_unit='krai', to_unit='XRB') 105 | Decimal('0.0004') 106 | 107 | 108 | Known Accounts / Constants 109 | ========================== 110 | 111 | .. code-block:: python 112 | 113 | >>> from nano import GENESIS_BLOCK_HASH 114 | >>> GENESIS_BLOCK_HASH 115 | '991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948' 116 | 117 | 118 | .. code-block:: python 119 | 120 | >>> from nano import KNOWN_ACCOUNT_IDS 121 | >>> KNOWN_ACCOUNT_IDS['xrb_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est'] 122 | 'Developer Fund' 123 | 124 | 125 | .. code-block:: python 126 | 127 | >>> from nano import KNOWN_ACCOUNT_NAMES 128 | >>> KNOWN_ACCOUNT_NAMES['Burn'] 129 | 'xrb_1111111111111111111111111111111111111111111111111111hifc8npp' 130 | 131 | 132 | Development 133 | =========== 134 | 135 | Setup 136 | ----- 137 | 138 | .. code-block:: text 139 | 140 | virtualenv venv 141 | source venv/bin/activate 142 | pip install -r requirements.pip -r requirements-dev.pip 143 | python setup.py develop 144 | pre-commit autoupdate 145 | pre-commit install 146 | 147 | Running tests 148 | ------------- 149 | 150 | .. code-block:: text 151 | 152 | # regular 153 | pytest 154 | 155 | # coverage 156 | ./coverage 157 | 158 | 159 | Building docs 160 | ------------- 161 | 162 | .. code-block:: text 163 | 164 | cd docs 165 | 166 | # generate once 167 | make html 168 | 169 | # live building 170 | make live 171 | 172 | 173 | Making a release 174 | ---------------- 175 | 176 | .. code-block:: text 177 | 178 | vim CHANGELOG.rst # update changes 179 | 180 | bumpversion [major|minor|patch] 181 | 182 | python setup.py upload 183 | -------------------------------------------------------------------------------- /coverage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | pytest --cov-fail-under=99 -n auto 4 | -------------------------------------------------------------------------------- /coverage.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | coverage 17 | coverage 18 | 100% 19 | 100% 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = nano-python 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | live: 16 | sphinx-autobuild -b html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 17 | 18 | .PHONY: help Makefile 19 | 20 | # Catch-all target: route all unknown targets to Sphinx using the new 21 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 22 | %: Makefile 23 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 24 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # 2 | # nano documentation build configuration file, created by 3 | # sphinx-quickstart on Thu Jan 11 17:32:46 2018. 4 | # 5 | # This file is execfile()d with the current directory set to its 6 | # containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | # If extensions (or modules to document with autodoc) are in another directory, 15 | # add these directories to sys.path here. If the directory is relative to the 16 | # documentation root, use os.path.abspath to make it absolute, like shown here. 17 | # 18 | import os 19 | import sys 20 | 21 | sys.path.insert(0, os.path.abspath('..')) 22 | 23 | # -- General configuration ------------------------------------------------ 24 | 25 | # If your documentation needs a minimal Sphinx version, state it here. 26 | # 27 | # needs_sphinx = '1.0' 28 | 29 | # Add any Sphinx extension module names here, as strings. They can be 30 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 31 | # ones. 32 | extensions = [ 33 | 'sphinx.ext.autodoc', 34 | 'sphinx.ext.doctest', 35 | 'sphinx.ext.intersphinx', 36 | 'sphinx.ext.autosummary', 37 | 'sphinx.ext.todo', 38 | 'sphinx.ext.coverage', 39 | 'sphinx.ext.viewcode', 40 | 'sphinx.ext.githubpages', 41 | ] 42 | 43 | # Add any paths that contain templates here, relative to this directory. 44 | templates_path = ['_templates'] 45 | 46 | # The suffix(es) of source filenames. 47 | # You can specify multiple suffix as a list of string: 48 | # 49 | # source_suffix = ['.rst', '.md'] 50 | source_suffix = '.rst' 51 | 52 | # The master toctree document. 53 | master_doc = 'index' 54 | 55 | # General information about the project. 56 | project = u'nano' 57 | copyright = u'2018, Daniel Dourvaris' 58 | author = u'Daniel Dourvaris' 59 | 60 | # The version info for the project you're documenting, acts as replacement for 61 | # |version| and |release|, also used in various other places throughout the 62 | # built documents. 63 | # 64 | # The short X.Y version. 65 | version = u'1.0.0' 66 | # The full version, including alpha/beta/rc tags. 67 | release = u'1.0.0' 68 | 69 | # The language for content autogenerated by Sphinx. Refer to documentation 70 | # for a list of supported languages. 71 | # 72 | # This is also used if you do content translation via gettext catalogs. 73 | # Usually you set "language" from the command line for these cases. 74 | language = None 75 | 76 | # List of patterns, relative to source directory, that match files and 77 | # directories to ignore when looking for source files. 78 | # This patterns also effect to html_static_path and html_extra_path 79 | exclude_patterns = [] 80 | 81 | # The name of the Pygments (syntax highlighting) style to use. 82 | pygments_style = 'sphinx' 83 | 84 | # If true, `todo` and `todoList` produce output, else they produce nothing. 85 | todo_include_todos = True 86 | 87 | 88 | # -- Options for HTML output ---------------------------------------------- 89 | 90 | # The theme to use for HTML and HTML Help pages. See the documentation for 91 | # a list of builtin themes. 92 | # 93 | html_theme = 'alabaster' 94 | html_theme = "sphinx_rtd_theme" 95 | 96 | # Theme options are theme-specific and customize the look and feel of a theme 97 | # further. For a list of options available for each theme, see the 98 | # documentation. 99 | # 100 | # html_theme_options = {} 101 | 102 | # Add any paths that contain custom static files (such as style sheets) here, 103 | # relative to this directory. They are copied after the builtin static files, 104 | # so a file named "default.css" will overwrite the builtin "default.css". 105 | html_static_path = ['_static'] 106 | 107 | # Custom sidebar templates, must be a dictionary that maps document names 108 | # to template names. 109 | # 110 | # This is required for the alabaster theme 111 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars 112 | html_sidebars = { 113 | '**': [ 114 | 'relations.html', # needs 'show_related': True theme option to display 115 | 'searchbox.html', 116 | ] 117 | } 118 | 119 | 120 | # -- Options for HTMLHelp output ------------------------------------------ 121 | 122 | # Output file base name for HTML help builder. 123 | htmlhelp_basename = 'nanodoc' 124 | 125 | 126 | # -- Options for LaTeX output --------------------------------------------- 127 | 128 | latex_elements = { 129 | # The paper size ('letterpaper' or 'a4paper'). 130 | # 131 | # 'papersize': 'letterpaper', 132 | # The font size ('10pt', '11pt' or '12pt'). 133 | # 134 | # 'pointsize': '10pt', 135 | # Additional stuff for the LaTeX preamble. 136 | # 137 | # 'preamble': '', 138 | # Latex figure (float) alignment 139 | # 140 | # 'figure_align': 'htbp', 141 | } 142 | 143 | # Grouping the document tree into LaTeX files. List of tuples 144 | # (source start file, target name, title, 145 | # author, documentclass [howto, manual, or own class]). 146 | latex_documents = [ 147 | (master_doc, 'nano.tex', u'nano Documentation', u'Daniel Dourvaris', 'manual') 148 | ] 149 | 150 | 151 | # -- Options for manual page output --------------------------------------- 152 | 153 | # One entry per manual page. List of tuples 154 | # (source start file, name, description, authors, manual section). 155 | man_pages = [(master_doc, 'nano', u'nano Documentation', [author], 1)] 156 | 157 | 158 | # -- Options for Texinfo output ------------------------------------------- 159 | 160 | # Grouping the document tree into Texinfo files. List of tuples 161 | # (source start file, target name, title, author, 162 | # dir menu entry, description, category) 163 | texinfo_documents = [ 164 | ( 165 | master_doc, 166 | 'nano', 167 | u'nano Documentation', 168 | author, 169 | 'nano', 170 | 'One line description of project.', 171 | 'Miscellaneous', 172 | ) 173 | ] 174 | 175 | 176 | # Example configuration for intersphinx: refer to the Python standard library. 177 | intersphinx_mapping = {'https://docs.python.org/': None} 178 | 179 | # autosummary_generate = True 180 | # imported_members = True 181 | -------------------------------------------------------------------------------- /docs/generate.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generates docs for the rpc client 3 | """ 4 | 5 | import os 6 | import sys 7 | import inspect 8 | import textwrap 9 | 10 | from nano.rpc import Client 11 | 12 | 13 | def indent(value, n=2, character=' '): 14 | """ 15 | Indent a value by `n` `character`s 16 | 17 | :param value: string to indent 18 | :param n: number of characters to indent by 19 | :param character: character to indent with 20 | """ 21 | 22 | prefix = n * character 23 | return '\n'.join(prefix + line for line in value.splitlines()) 24 | 25 | 26 | def extract_docs(): 27 | """ 28 | Parses the nano.rpc.Client for methods that have a __doc_meta__ attribute 29 | and saves generated docs 30 | """ 31 | 32 | methods = [] 33 | 34 | def _key(entry): 35 | return 36 | 37 | sorted_entries = sorted(Client.__dict__.items(), key=lambda x: x[0]) 38 | 39 | tree = {} 40 | meta_key = '__doc_meta__' 41 | 42 | for attr_name, attr_value in sorted_entries: 43 | 44 | if not hasattr(attr_value, meta_key): 45 | continue 46 | 47 | func = attr_value 48 | meta = getattr(func, meta_key) 49 | 50 | arg_spec = inspect.getargspec(func) 51 | if arg_spec[0] and arg_spec[0][0] in ('cls', 'self'): 52 | del arg_spec[0][0] 53 | 54 | func_name = func.__name__ 55 | func_spec = func_name + inspect.formatargspec(*arg_spec) 56 | 57 | doc = textwrap.dedent((func.__doc__ or '')) 58 | doc = indent(doc, n=3) 59 | 60 | func_desc_lines = [] 61 | for i, line in enumerate(func.__doc__.splitlines()): 62 | if i == 0: 63 | continue 64 | func_desc_lines.append(line.strip()) 65 | if not line: 66 | break 67 | func_desc = ' '.join(func_desc_lines) 68 | 69 | doc = textwrap.dedent( 70 | """\ 71 | {func_name} 72 | {func_name_line} 73 | 74 | {func_desc} 75 | :py:func:`nano.rpc.Client.{func_spec} ` 76 | 77 | .. .. py:function:: nano.rpc.Client.{func_spec} 78 | 79 | .. {doc} 80 | """ 81 | ).format( 82 | func_spec=func_spec, 83 | func_name_line='-' * len(func_name), 84 | func_name=func_name, 85 | func_desc=func_desc, 86 | doc=doc, 87 | ) 88 | 89 | categories = meta['categories'] 90 | for category in categories: 91 | tree.setdefault(category, []).append(doc) 92 | 93 | directory = 'rpc/methods' 94 | for file in os.listdir(directory): 95 | if file.endswith('.rst'): 96 | os.unlink(os.path.join(directory, file)) 97 | 98 | for category, func_docs in sorted(tree.items(), key=lambda x: x[0]): 99 | category = category or 'other' 100 | file_path = os.path.join(directory, category) + '.rst' 101 | with open(file_path, 'w') as docfile: 102 | docfile.write('.. _%s-ref:\n' % category + '\n') 103 | title = '{category}'.format(category=category.capitalize()) 104 | docfile.write('%s\n' % title) 105 | docfile.write('%s\n' % (len(title) * '=')) 106 | docfile.write('\n') 107 | 108 | for func_doc in func_docs: 109 | docfile.write(func_doc + '\n') 110 | 111 | 112 | if __name__ == '__main__': 113 | extract_docs() 114 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Nano (RaiBlocks) Python Library 2 | =============================== 3 | 4 | This library contains a python wrapper for the Nano (RaiBlocks) RPC server 5 | which tries to make it a little easier to work with by converting RPC responses 6 | to native python ones and exposing a pythonic api for making RPC calls. 7 | 8 | Also included are utilities such as converting rai/xrb and interesting accounts 9 | 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | :caption: Contents: 14 | 15 | readme 16 | rpc/index 17 | utilities 18 | nano 19 | 20 | Indices and tables 21 | ================== 22 | 23 | * :ref:`genindex` 24 | * :ref:`modindex` 25 | * :ref:`search` 26 | -------------------------------------------------------------------------------- /docs/nano.rst: -------------------------------------------------------------------------------- 1 | nano package 2 | ============ 3 | 4 | Submodules 5 | ---------- 6 | 7 | nano\.accounts module 8 | --------------------- 9 | 10 | .. automodule:: nano.accounts 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | nano\.blocks module 16 | ------------------- 17 | 18 | .. automodule:: nano.blocks 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | nano\.conversion module 24 | ----------------------- 25 | 26 | .. automodule:: nano.conversion 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | nano\.rpc module 32 | ---------------- 33 | 34 | .. automodule:: nano.rpc 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | -------------------------------------------------------------------------------- /docs/readme.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | -------------------------------------------------------------------------------- /docs/rpc/index.rst: -------------------------------------------------------------------------------- 1 | .. _rpc-ref: 2 | 3 | RPC methods 4 | =========== 5 | 6 | This documents the available methods on the :py:class:`nano.rpc.Client` 7 | 8 | .. toctree:: 9 | :glob: 10 | 11 | methods/* 12 | -------------------------------------------------------------------------------- /docs/rpc/methods/global.rst: -------------------------------------------------------------------------------- 1 | .. _global-ref: 2 | 3 | Global 4 | ====== 5 | 6 | available_supply 7 | ---------------- 8 | 9 | Returns how many rai are in the public supply 10 | :py:func:`nano.rpc.Client.available_supply() ` 11 | 12 | .. .. py:function:: nano.rpc.Client.available_supply() 13 | 14 | .. 15 | Returns how many rai are in the public supply 16 | 17 | :raises: :py:exc:`nano.rpc.RPCException` 18 | 19 | >>> rpc.available_supply() 20 | 10000 21 | 22 | 23 | block_count 24 | ----------- 25 | 26 | Reports the number of blocks in the ledger and unchecked synchronizing blocks 27 | :py:func:`nano.rpc.Client.block_count() ` 28 | 29 | .. .. py:function:: nano.rpc.Client.block_count() 30 | 31 | .. 32 | Reports the number of blocks in the ledger and unchecked synchronizing 33 | blocks 34 | 35 | :raises: :py:exc:`nano.rpc.RPCException` 36 | 37 | >>> rpc.block_count() 38 | { 39 | "count": 1000, 40 | "unchecked": 10 41 | } 42 | 43 | 44 | block_count_type 45 | ---------------- 46 | 47 | Reports the number of blocks in the ledger by type (send, receive, open, change) 48 | :py:func:`nano.rpc.Client.block_count_type() ` 49 | 50 | .. .. py:function:: nano.rpc.Client.block_count_type() 51 | 52 | .. 53 | Reports the number of blocks in the ledger by type (send, receive, 54 | open, change) 55 | 56 | :raises: :py:exc:`nano.rpc.RPCException` 57 | 58 | >>> rpc.block_count_type() 59 | { 60 | "send": 1000, 61 | "receive": 900, 62 | "open": 100, 63 | "change": 50 64 | } 65 | 66 | 67 | frontier_count 68 | -------------- 69 | 70 | Reports the number of accounts in the ledger 71 | :py:func:`nano.rpc.Client.frontier_count() ` 72 | 73 | .. .. py:function:: nano.rpc.Client.frontier_count() 74 | 75 | .. 76 | Reports the number of accounts in the ledger 77 | 78 | :raises: :py:exc:`nano.rpc.RPCException` 79 | 80 | >>> rpc.frontier_count() 81 | 1000 82 | 83 | 84 | representatives 85 | --------------- 86 | 87 | Returns a list of pairs of representative and its voting weight 88 | :py:func:`nano.rpc.Client.representatives(count=None, sorting=False) ` 89 | 90 | .. .. py:function:: nano.rpc.Client.representatives(count=None, sorting=False) 91 | 92 | .. 93 | Returns a list of pairs of representative and its voting weight 94 | 95 | :param count: Max amount of representatives to return 96 | :type count: int 97 | 98 | :param sorting: If true, sorts by weight 99 | :type sorting: bool 100 | 101 | :raises: :py:exc:`nano.rpc.RPCException` 102 | 103 | >>> rpc.representatives() 104 | { 105 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": 106 | 3822372327060170000000000000000000000, 107 | "xrb_1111111111111111111111111111111111111111111111111awsq94gtecn": 108 | 30999999999999999999999999000000, 109 | "xrb_114nk4rwjctu6n6tr6g6ps61g1w3hdpjxfas4xj1tq6i8jyomc5d858xr1xi": 110 | 0 111 | } 112 | -------------------------------------------------------------------------------- /docs/rpc/methods/node.rst: -------------------------------------------------------------------------------- 1 | .. _node-ref: 2 | 3 | Node 4 | ==== 5 | 6 | bootstrap 7 | --------- 8 | 9 | Initialize bootstrap to specific **IP address** and **port** 10 | :py:func:`nano.rpc.Client.bootstrap(address, port) ` 11 | 12 | .. .. py:function:: nano.rpc.Client.bootstrap(address, port) 13 | 14 | .. 15 | Initialize bootstrap to specific **IP address** and **port** 16 | 17 | :param address: Ip address to bootstrap 18 | :type address: str 19 | 20 | :param port: Port to bootstrap 21 | :type port: int 22 | 23 | :raises: :py:exc:`nano.rpc.RPCException` 24 | 25 | >>> rpc.bootstrap(address="::ffff:138.201.94.249", port="7075") 26 | True 27 | 28 | bootstrap_any 29 | ------------- 30 | 31 | Initialize multi-connection bootstrap to random peers 32 | :py:func:`nano.rpc.Client.bootstrap_any() ` 33 | 34 | .. .. py:function:: nano.rpc.Client.bootstrap_any() 35 | 36 | .. 37 | Initialize multi-connection bootstrap to random peers 38 | 39 | :raises: :py:exc:`nano.rpc.RPCException` 40 | 41 | >>> rpc.bootstrap_any() 42 | True 43 | 44 | keepalive 45 | --------- 46 | 47 | Tells the node to send a keepalive packet to **address**:**port** 48 | :py:func:`nano.rpc.Client.keepalive(address, port) ` 49 | 50 | .. .. py:function:: nano.rpc.Client.keepalive(address, port) 51 | 52 | .. 53 | Tells the node to send a keepalive packet to **address**:**port** 54 | 55 | .. enable_control required 56 | 57 | :param address: IP address of node to send keepalive packet to 58 | :type address: str 59 | 60 | :param port: Port of node to send keepalive packet to 61 | :type port: int 62 | 63 | :raises: :py:exc:`nano.rpc.RPCException` 64 | 65 | >>> rpc.keepalive(address="::ffff:192.168.1.1", port=1024) 66 | True 67 | 68 | peers 69 | ----- 70 | 71 | Returns a list of pairs of peer IPv6:port and its node network version 72 | :py:func:`nano.rpc.Client.peers() ` 73 | 74 | .. .. py:function:: nano.rpc.Client.peers() 75 | 76 | .. 77 | Returns a list of pairs of peer IPv6:port and its node network version 78 | 79 | :raises: :py:exc:`nano.rpc.RPCException` 80 | 81 | >>> rpc.peers() 82 | { 83 | "[::ffff:172.17.0.1]:32841": 3 84 | } 85 | 86 | receive_minimum 87 | --------------- 88 | 89 | Returns receive minimum for node 90 | :py:func:`nano.rpc.Client.receive_minimum() ` 91 | 92 | .. .. py:function:: nano.rpc.Client.receive_minimum() 93 | 94 | .. 95 | Returns receive minimum for node 96 | 97 | .. enable_control required 98 | .. version 8.0 required 99 | 100 | :raises: :py:exc:`nano.rpc.RPCException` 101 | 102 | >>> rpc.receive_minimum() 103 | 1000000000000000000000000 104 | 105 | 106 | receive_minimum_set 107 | ------------------- 108 | 109 | Set **amount** as new receive minimum for node until restart 110 | :py:func:`nano.rpc.Client.receive_minimum_set(amount) ` 111 | 112 | .. .. py:function:: nano.rpc.Client.receive_minimum_set(amount) 113 | 114 | .. 115 | Set **amount** as new receive minimum for node until restart 116 | 117 | .. enable_control required 118 | .. version 8.0 required 119 | 120 | :param amount: Amount in raw to set as minimum to receive 121 | :type amount: int 122 | 123 | :raises: :py:exc:`nano.rpc.RPCException` 124 | 125 | >>> rpc.receive_minimum_set(amount=1000000000000000000000000000000) 126 | True 127 | 128 | search_pending_all 129 | ------------------ 130 | 131 | Tells the node to look for pending blocks for any account in all available wallets 132 | :py:func:`nano.rpc.Client.search_pending_all() ` 133 | 134 | .. .. py:function:: nano.rpc.Client.search_pending_all() 135 | 136 | .. 137 | Tells the node to look for pending blocks for any account in all 138 | available wallets 139 | 140 | .. enable_control required 141 | .. version 8.0 required 142 | 143 | :raises: :py:exc:`nano.rpc.RPCException` 144 | 145 | >>> rpc.search_pending_all() 146 | True 147 | 148 | 149 | stop 150 | ---- 151 | 152 | Stop the node 153 | :py:func:`nano.rpc.Client.stop() ` 154 | 155 | .. .. py:function:: nano.rpc.Client.stop() 156 | 157 | .. 158 | Stop the node 159 | 160 | .. enable_control required 161 | 162 | :raises: :py:exc:`nano.rpc.RPCException` 163 | 164 | >>> rpc.stop() 165 | True 166 | 167 | 168 | unchecked 169 | --------- 170 | 171 | Returns a list of pairs of unchecked synchronizing block hash and its json representation up to **count** 172 | :py:func:`nano.rpc.Client.unchecked(count=None) ` 173 | 174 | .. .. py:function:: nano.rpc.Client.unchecked(count=None) 175 | 176 | .. 177 | Returns a list of pairs of unchecked synchronizing block hash and its 178 | json representation up to **count** 179 | 180 | .. version 8.0 required 181 | 182 | :param count: Max amount of unchecked blocks to return 183 | :type count: int 184 | 185 | :raises: :py:exc:`nano.rpc.RPCException` 186 | 187 | >>> rpc.unchecked(count=1) 188 | { 189 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": { 190 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 191 | "work": "0000000000000000", 192 | "source": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 193 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 194 | "signature": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 195 | "type": "open" 196 | } 197 | } 198 | 199 | 200 | unchecked_clear 201 | --------------- 202 | 203 | Clear unchecked synchronizing blocks 204 | :py:func:`nano.rpc.Client.unchecked_clear() ` 205 | 206 | .. .. py:function:: nano.rpc.Client.unchecked_clear() 207 | 208 | .. 209 | Clear unchecked synchronizing blocks 210 | 211 | .. enable_control required 212 | .. version 8.0 required 213 | 214 | :raises: :py:exc:`nano.rpc.RPCException` 215 | 216 | >>> rpc.unchecked_clear() 217 | True 218 | 219 | 220 | unchecked_get 221 | ------------- 222 | 223 | Retrieves a json representation of unchecked synchronizing block by **hash** 224 | :py:func:`nano.rpc.Client.unchecked_get(hash) ` 225 | 226 | .. .. py:function:: nano.rpc.Client.unchecked_get(hash) 227 | 228 | .. 229 | Retrieves a json representation of unchecked synchronizing block by 230 | **hash** 231 | 232 | .. version 8.0 required 233 | 234 | :param hash: Hash of unchecked block to get 235 | :type hash: str 236 | 237 | :raises: :py:exc:`nano.rpc.RPCException` 238 | 239 | >>> rpc.unchecked_get( 240 | ... hash="000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 241 | ... ) 242 | { 243 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 244 | "work": "0000000000000000", 245 | "source": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 246 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 247 | "signature": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 248 | "type": "open" 249 | } 250 | 251 | 252 | unchecked_keys 253 | -------------- 254 | 255 | Retrieves unchecked database keys, blocks hashes & a json representations of unchecked pending blocks starting from **key** up to **count** 256 | :py:func:`nano.rpc.Client.unchecked_keys(key=None, count=None) ` 257 | 258 | .. .. py:function:: nano.rpc.Client.unchecked_keys(key=None, count=None) 259 | 260 | .. 261 | Retrieves unchecked database keys, blocks hashes & a json 262 | representations of unchecked pending blocks starting from **key** up 263 | to **count** 264 | 265 | .. version 8.0 required 266 | 267 | :param key: Starting key to return unchecked keys for 268 | :type key: str 269 | 270 | :param count: Max number of keys/blocks to return 271 | :type count: int 272 | 273 | :raises: :py:exc:`nano.rpc.RPCException` 274 | 275 | >>> rpc.unchecked_keys( 276 | ... key="FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 277 | ... count=1 278 | ... ) 279 | [ 280 | { 281 | "key": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 282 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 283 | "contents": { 284 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 285 | "work": "0000000000000000", 286 | "source": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 287 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 288 | "signature": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 289 | "type": "open" 290 | } 291 | } 292 | ] 293 | 294 | 295 | version 296 | ------- 297 | 298 | Returns the node's RPC version 299 | :py:func:`nano.rpc.Client.version() ` 300 | 301 | .. .. py:function:: nano.rpc.Client.version() 302 | 303 | .. 304 | Returns the node's RPC version 305 | 306 | :raises: :py:exc:`nano.rpc.RPCException` 307 | 308 | >>> rpc.version() 309 | { 310 | "rpc_version": 1, 311 | "store_version": 10, 312 | "node_vendor": "RaiBlocks 9.0" 313 | } 314 | -------------------------------------------------------------------------------- /docs/rpc/methods/utility.rst: -------------------------------------------------------------------------------- 1 | .. _utility-ref: 2 | 3 | Utility 4 | ======= 5 | 6 | deterministic_key 7 | ----------------- 8 | 9 | Derive deterministic keypair from **seed** based on **index** 10 | :py:func:`nano.rpc.Client.deterministic_key(seed, index) ` 11 | 12 | .. .. py:function:: nano.rpc.Client.deterministic_key(seed, index) 13 | 14 | .. 15 | Derive deterministic keypair from **seed** based on **index** 16 | 17 | :param seed: Seed used to get keypair 18 | :type seed: str 19 | 20 | :param index: Index of the generated keypair 21 | :type index: int 22 | 23 | :raises: :py:exc:`nano.rpc.RPCException` 24 | 25 | >>> rpc.deterministic_key( 26 | ... seed="0000000000000000000000000000000000000000000000000000000000000000", 27 | ... index=0 28 | ... ) 29 | { 30 | "private": "9F0E444C69F77A49BD0BE89DB92C38FE713E0963165CCA12FAF5712D7657120F", 31 | "public": "C008B814A7D269A1FA3C6528B19201A24D797912DB9996FF02A1FF356E45552B", 32 | "account": "xrb_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7" 33 | } 34 | 35 | 36 | key_create 37 | ---------- 38 | 39 | Generates an **adhoc random keypair** 40 | :py:func:`nano.rpc.Client.key_create() ` 41 | 42 | .. .. py:function:: nano.rpc.Client.key_create() 43 | 44 | .. 45 | Generates an **adhoc random keypair** 46 | 47 | :raises: :py:exc:`nano.rpc.RPCException` 48 | 49 | >>> rpc.key_create() 50 | { 51 | "private": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", 52 | "public": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039", 53 | "account": "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx" 54 | } 55 | 56 | 57 | key_expand 58 | ---------- 59 | 60 | Derive public key and account number from **private key** 61 | :py:func:`nano.rpc.Client.key_expand(key) ` 62 | 63 | .. .. py:function:: nano.rpc.Client.key_expand(key) 64 | 65 | .. 66 | Derive public key and account number from **private key** 67 | 68 | :param key: Private key to generate account and public key of 69 | :type key: str 70 | 71 | :raises: :py:exc:`nano.rpc.RPCException` 72 | 73 | >>> rpc.key_expand( 74 | key="781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3" 75 | ) 76 | { 77 | "private": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", 78 | "public": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039", 79 | "account": "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx" 80 | } 81 | 82 | 83 | krai_from_raw 84 | ------------- 85 | 86 | Divide a raw amount down by the krai ratio. 87 | :py:func:`nano.rpc.Client.krai_from_raw(amount) ` 88 | 89 | .. .. py:function:: nano.rpc.Client.krai_from_raw(amount) 90 | 91 | .. 92 | Divide a raw amount down by the krai ratio. 93 | 94 | :param amount: Amount in raw to convert to krai 95 | :type amount: int 96 | 97 | :raises: :py:exc:`nano.rpc.RPCException` 98 | 99 | >>> rpc.krai_from_raw(amount=1000000000000000000000000000) 100 | 1 101 | 102 | krai_to_raw 103 | ----------- 104 | 105 | Multiply an krai amount by the krai ratio. 106 | :py:func:`nano.rpc.Client.krai_to_raw(amount) ` 107 | 108 | .. .. py:function:: nano.rpc.Client.krai_to_raw(amount) 109 | 110 | .. 111 | Multiply an krai amount by the krai ratio. 112 | 113 | :param amount: Amount in krai to convert to raw 114 | :type amount: int 115 | 116 | :raises: :py:exc:`nano.rpc.RPCException` 117 | 118 | >>> rpc.krai_to_raw(amount=1) 119 | 1000000000000000000000000000 120 | 121 | 122 | mrai_from_raw 123 | ------------- 124 | 125 | Divide a raw amount down by the Mrai ratio. 126 | :py:func:`nano.rpc.Client.mrai_from_raw(amount) ` 127 | 128 | .. .. py:function:: nano.rpc.Client.mrai_from_raw(amount) 129 | 130 | .. 131 | Divide a raw amount down by the Mrai ratio. 132 | 133 | :param amount: Amount in raw to convert to Mrai 134 | :type amount: int 135 | 136 | :raises: :py:exc:`nano.rpc.RPCException` 137 | 138 | >>> rpc.mrai_from_raw(amount=1000000000000000000000000000000) 139 | 1 140 | 141 | 142 | mrai_to_raw 143 | ----------- 144 | 145 | Multiply an Mrai amount by the Mrai ratio. 146 | :py:func:`nano.rpc.Client.mrai_to_raw(amount) ` 147 | 148 | .. .. py:function:: nano.rpc.Client.mrai_to_raw(amount) 149 | 150 | .. 151 | Multiply an Mrai amount by the Mrai ratio. 152 | 153 | :param amount: Amount in Mrai to convert to raw 154 | :type amount: int 155 | 156 | :raises: :py:exc:`nano.rpc.RPCException` 157 | 158 | >>> rpc.mrai_to_raw(amount=1) 159 | 1000000000000000000000000000000 160 | 161 | 162 | rai_from_raw 163 | ------------ 164 | 165 | Divide a raw amount down by the rai ratio. 166 | :py:func:`nano.rpc.Client.rai_from_raw(amount) ` 167 | 168 | .. .. py:function:: nano.rpc.Client.rai_from_raw(amount) 169 | 170 | .. 171 | Divide a raw amount down by the rai ratio. 172 | 173 | :param amount: Amount in raw to convert to rai 174 | :type amount: int 175 | 176 | :raises: :py:exc:`nano.rpc.RPCException` 177 | 178 | >>> rpc.rai_from_raw(amount=1000000000000000000000000) 179 | 1 180 | 181 | 182 | rai_to_raw 183 | ---------- 184 | 185 | Multiply an rai amount by the rai ratio. 186 | :py:func:`nano.rpc.Client.rai_to_raw(amount) ` 187 | 188 | .. .. py:function:: nano.rpc.Client.rai_to_raw(amount) 189 | 190 | .. 191 | Multiply an rai amount by the rai ratio. 192 | 193 | :param amount: Amount in rai to convert to raw 194 | :type amount: int 195 | 196 | :raises: :py:exc:`nano.rpc.RPCException` 197 | 198 | >>> rpc.rai_to_raw(amount=1) 199 | 1000000000000000000000000 200 | -------------------------------------------------------------------------------- /docs/rpc/methods/work.rst: -------------------------------------------------------------------------------- 1 | .. _work-ref: 2 | 3 | Work 4 | ==== 5 | 6 | wallet_work_get 7 | --------------- 8 | 9 | Returns a list of pairs of account and work from **wallet** 10 | :py:func:`nano.rpc.Client.wallet_work_get(wallet) ` 11 | 12 | .. .. py:function:: nano.rpc.Client.wallet_work_get(wallet) 13 | 14 | .. 15 | Returns a list of pairs of account and work from **wallet** 16 | 17 | .. enable_control required 18 | .. version 8.0 required 19 | 20 | :param wallet: Wallet to return work for 21 | :type wallet: str 22 | 23 | :raises: :py:exc:`nano.rpc.RPCException` 24 | 25 | >>> rpc.wallet_work_get( 26 | ... wallet="000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 27 | ... ) 28 | { 29 | "xrb_1111111111111111111111111111111111111111111111111111hifc8npp": 30 | "432e5cf728c90f4f" 31 | } 32 | 33 | 34 | work_cancel 35 | ----------- 36 | 37 | Stop generating **work** for block 38 | :py:func:`nano.rpc.Client.work_cancel(hash) ` 39 | 40 | .. .. py:function:: nano.rpc.Client.work_cancel(hash) 41 | 42 | .. 43 | Stop generating **work** for block 44 | 45 | .. enable_control required 46 | 47 | :param hash: Hash to stop generating work for 48 | :type hash: str 49 | 50 | :raises: :py:exc:`nano.rpc.RPCException` 51 | 52 | >>> rpc.work_cancel( 53 | ... hash="718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2" 54 | ... ) 55 | True 56 | 57 | 58 | work_generate 59 | ------------- 60 | 61 | Generates **work** for block 62 | :py:func:`nano.rpc.Client.work_generate(hash) ` 63 | 64 | .. .. py:function:: nano.rpc.Client.work_generate(hash) 65 | 66 | .. 67 | Generates **work** for block 68 | 69 | .. enable_control required 70 | 71 | :param hash: Hash to start generating **work** for 72 | :type hash: str 73 | 74 | :raises: :py:exc:`nano.rpc.RPCException` 75 | 76 | >>> rpc.work_generate( 77 | ... hash="718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2" 78 | ... ) 79 | "2bf29ef00786a6bc" 80 | 81 | 82 | work_get 83 | -------- 84 | 85 | Retrieves work for **account** in **wallet** 86 | :py:func:`nano.rpc.Client.work_get(wallet, account) ` 87 | 88 | .. .. py:function:: nano.rpc.Client.work_get(wallet, account) 89 | 90 | .. 91 | Retrieves work for **account** in **wallet** 92 | 93 | .. enable_control required 94 | .. version 8.0 required 95 | 96 | :param wallet: Wallet to get account work for 97 | :type wallet: str 98 | 99 | :param account: Account to get work for 100 | :type account: str 101 | 102 | :raises: :py:exc:`nano.rpc.RPCException` 103 | 104 | >>> rpc.work_get( 105 | ... wallet="000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 106 | ... account="xrb_1111111111111111111111111111111111111111111111111111hifc8npp" 107 | ... ) 108 | "432e5cf728c90f4f" 109 | 110 | 111 | work_peer_add 112 | ------------- 113 | 114 | Add specific **IP address** and **port** as work peer for node until restart 115 | :py:func:`nano.rpc.Client.work_peer_add(address, port) ` 116 | 117 | .. .. py:function:: nano.rpc.Client.work_peer_add(address, port) 118 | 119 | .. 120 | Add specific **IP address** and **port** as work peer for node until 121 | restart 122 | 123 | .. enable_control required 124 | .. version 8.0 required 125 | 126 | :param address: IP address of work peer to add 127 | :type address: str 128 | 129 | :param port: Port work peer to add 130 | :type port: int 131 | 132 | :raises: :py:exc:`nano.rpc.RPCException` 133 | 134 | >>> rpc.work_peer_add(address="::ffff:172.17.0.1", port="7076") 135 | True 136 | 137 | 138 | work_peers 139 | ---------- 140 | 141 | Retrieve work peers 142 | :py:func:`nano.rpc.Client.work_peers() ` 143 | 144 | .. .. py:function:: nano.rpc.Client.work_peers() 145 | 146 | .. 147 | Retrieve work peers 148 | 149 | .. enable_control required 150 | .. version 8.0 required 151 | 152 | :raises: :py:exc:`nano.rpc.RPCException` 153 | 154 | >>> rpc.work_peers() 155 | [ 156 | "::ffff:172.17.0.1:7076" 157 | ] 158 | 159 | 160 | work_peers_clear 161 | ---------------- 162 | 163 | Clear work peers node list until restart 164 | :py:func:`nano.rpc.Client.work_peers_clear() ` 165 | 166 | .. .. py:function:: nano.rpc.Client.work_peers_clear() 167 | 168 | .. 169 | Clear work peers node list until restart 170 | 171 | .. enable_control required 172 | .. version 8.0 required 173 | 174 | :raises: :py:exc:`nano.rpc.RPCException` 175 | 176 | >>> rpc.work_peers_clear() 177 | True 178 | 179 | 180 | work_set 181 | -------- 182 | 183 | Set **work** for **account** in **wallet** 184 | :py:func:`nano.rpc.Client.work_set(wallet, account, work) ` 185 | 186 | .. .. py:function:: nano.rpc.Client.work_set(wallet, account, work) 187 | 188 | .. 189 | Set **work** for **account** in **wallet** 190 | 191 | .. enable_control required 192 | .. version 8.0 required 193 | 194 | :param wallet: Wallet to set work for account for 195 | :type wallet: str 196 | 197 | :param account: Account to set work for 198 | :type account: str 199 | 200 | :param work: Work to set for account in wallet 201 | :type work: str 202 | 203 | :raises: :py:exc:`nano.rpc.RPCException` 204 | 205 | >>> rpc.work_set( 206 | ... wallet="000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 207 | ... account="xrb_1111111111111111111111111111111111111111111111111111hifc8npp", 208 | ... work="0000000000000000" 209 | ... ) 210 | True 211 | 212 | work_validate 213 | ------------- 214 | 215 | Check whether **work** is valid for block 216 | :py:func:`nano.rpc.Client.work_validate(work, hash) ` 217 | 218 | .. .. py:function:: nano.rpc.Client.work_validate(work, hash) 219 | 220 | .. 221 | Check whether **work** is valid for block 222 | 223 | :param work: Work to validate 224 | :type work: str 225 | 226 | :param hash: Hash of block to validate work for 227 | :type hash: str 228 | 229 | :raises: :py:exc:`nano.rpc.RPCException` 230 | 231 | >>> rpc.work_validate( 232 | ... work="2bf29ef00786a6bc", 233 | ... hash="718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2" 234 | ... ) 235 | True 236 | -------------------------------------------------------------------------------- /docs/utilities.rst: -------------------------------------------------------------------------------- 1 | .. _utilities-ref: 2 | 3 | Utilities 4 | ========== 5 | 6 | 7 | Conversion tools 8 | ---------------- 9 | 10 | For converting between nano/xrb/rai amounts. 11 | 12 | The :meth:`nano.conversion.convert` function takes ``int``, ``Decimal`` or ``string`` arguments (no ``float``): 13 | 14 | .. code-block:: python 15 | 16 | >>> from nano import convert 17 | >>> convert(12, from_unit='NANO', to_unit='raw') 18 | Decimal('1.2E+31') 19 | 20 | >>> convert(0.4, from_unit='knano', to_unit='NANO') 21 | Traceback (most recent call last): 22 | File "", line 1, in 23 | ValueError: float values can lead to unexpected 24 | precision loss, please use a Decimal or string 25 | eg. convert('0.4', 'knano', 'NANO') 26 | 27 | >>> convert('0.4', from_unit='knano', to_unit='NANO') 28 | Decimal('0.0004') 29 | 30 | 31 | 32 | .. WARNING:: 33 | Careful not to mix up ``'NANO'`` and ``'nano'`` as they are different units 34 | 35 | >>> convert(2000000000000000000000000, 'raw', 'NANO') 36 | Decimal('0.000002') 37 | >>> convert(2000000000000000000000000, 'raw', 'nano') 38 | Decimal('2') 39 | 40 | For a dict of all available units and their amount in raw: 41 | 42 | >>> from nano import UNITS_TO_RAW 43 | >>> UNITS_TO_RAW 44 | {'Gnano': Decimal('1000000000000000000000000000000000'), 45 | 'Grai': Decimal('1000000000000000000000000000000000'), 46 | 'Gxrb': Decimal('1000000000000000000000000000000000'), 47 | 'Mnano': Decimal('1000000000000000000000000000000'), 48 | 'Mrai': Decimal('1000000000000000000000000000000'), 49 | 'Mxrb': Decimal('1000000000000000000000000000000'), 50 | 'NANO': Decimal('1000000000000000000000000000000'), 51 | 'XRB': Decimal('1000000000000000000000000000000'), 52 | 'knano': Decimal('1000000000000000000000000000'), 53 | 'krai': Decimal('1000000000000000000000000000'), 54 | 'kxrb': Decimal('1000000000000000000000000000'), 55 | 'mnano': Decimal('1000000000000000000000'), 56 | 'mrai': Decimal('1000000000000000000000'), 57 | 'mxrb': Decimal('1000000000000000000000'), 58 | 'nano': Decimal('1000000000000000000000000'), 59 | 'rai': Decimal('1000000000000000000000000'), 60 | 'raw': Decimal('1'), 61 | 'unano': Decimal('1000000000000000000'), 62 | 'urai': Decimal('1000000000000000000'), 63 | 'uxrb': Decimal('1000000000000000000'), 64 | 'xrb': Decimal('1000000000000000000000000')} 65 | 66 | Known Accounts / Constants 67 | -------------------------- 68 | 69 | .. code-block:: python 70 | 71 | >>> from nano import GENESIS_BLOCK_HASH, KNOWN_ACCOUNT_IDS, KNOWN_ACCOUNT_NAMES 72 | >>> KNOWN_ACCOUNT_IDS['xrb_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est'] 73 | 'Developer Fund' 74 | >>> KNOWN_ACCOUNT_NAMES['Burn'] 75 | 'xrb_1111111111111111111111111111111111111111111111111111hifc8npp' 76 | >>> GENESIS_BLOCK_HASH 77 | '991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948' 78 | -------------------------------------------------------------------------------- /requirements-dev.pip: -------------------------------------------------------------------------------- 1 | bumpversion 2 | pytest 3 | pytest-cov 4 | pytest-xdist 5 | pytest-runner 6 | requests_mock 7 | sphinx 8 | sphinx-autobuild 9 | sphinx_rtd_theme 10 | pre-commit 11 | -------------------------------------------------------------------------------- /requirements.pip: -------------------------------------------------------------------------------- 1 | certifi==2017.11.5 2 | chardet==3.0.4 3 | idna==2.6 4 | pyblake2==1.1.0 5 | requests==2.18.4 6 | six==1.11.0 7 | urllib3==1.22 8 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 2.1.0 3 | commit = True 4 | tag = True 5 | 6 | [aliases] 7 | test = pytest 8 | 9 | [bumpversion:file:src/nano/version.py] 10 | 11 | [tool:pytest] 12 | addopts = 13 | --cov=nano 14 | --cov-report term-missing 15 | --cov-report xml 16 | --failed-first 17 | --exitfirst 18 | testpaths = tests 19 | nonrecursedirs = fixtures 20 | 21 | [coverage:run] 22 | branch = True 23 | 24 | [coverage:report] 25 | # Regexes for lines to exclude from consideration 26 | exclude_lines = 27 | # Have to re-enable the standard pragma 28 | pragma: no cover 29 | 30 | # Don't complain about missing debug-only code: 31 | def __repr__ 32 | if self\.debug 33 | 34 | # Don't complain if tests don't hit defensive assertion code: 35 | raise AssertionError 36 | raise NotImplementedError 37 | 38 | # Don't complain if non-runnable code isn't run: 39 | if 0: 40 | if __name__ == .__main__.: 41 | sort = BrPart 42 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import ast 4 | import io 5 | import os 6 | import re 7 | import sys 8 | from shutil import rmtree 9 | 10 | from setuptools import find_packages, setup, Command 11 | 12 | # Package meta-data. 13 | PYPI_NAME = 'nano-python' 14 | NAME = 'nano' 15 | DESCRIPTION = 'Nano (RaiBlocks) Python RPC client for rai_node' 16 | URL = 'https://github.com/dourvaris/nano-python' 17 | EMAIL = 'dourvaris@gmail.com' 18 | AUTHOR = 'Daniel Dourvaris' 19 | 20 | with open('requirements.pip') as f: 21 | INSTALL_REQUIRES = f.read().splitlines() 22 | 23 | with open('requirements-dev.pip') as f: 24 | TESTS_REQUIRE = f.read().splitlines() 25 | 26 | here = os.path.abspath(os.path.dirname(__file__)) 27 | 28 | with io.open(os.path.join(here, 'README.rst'), encoding='utf-8') as f: 29 | long_description = '\n' + f.read() 30 | 31 | _version_re = re.compile(r'__version__\s+=\s+(.*)') 32 | with open(os.path.join(here, 'src', NAME, 'version.py'), 'rb') as f: 33 | version = str( 34 | ast.literal_eval(_version_re.search(f.read().decode('utf-8')).group(1)) 35 | ) 36 | 37 | 38 | class UploadCommand(Command): 39 | """Support setup.py upload.""" 40 | 41 | description = 'Build and publish the package.' 42 | user_options = [] 43 | 44 | @staticmethod 45 | def status(s): 46 | """Prints things in bold.""" 47 | print('\033[1m{0}\033[0m'.format(s)) 48 | 49 | def initialize_options(self): 50 | pass 51 | 52 | def finalize_options(self): 53 | pass 54 | 55 | def run(self): 56 | try: 57 | self.status('Removing previous builds…') 58 | rmtree(os.path.join(here, 'dist')) 59 | except OSError: 60 | pass 61 | 62 | self.status('Building Source and Wheel (universal) distribution…') 63 | os.system('{0} setup.py sdist bdist_wheel --universal'.format(sys.executable)) 64 | 65 | self.status('Uploading the package to PyPi via Twine…') 66 | os.system('twine upload dist/*') 67 | 68 | sys.exit() 69 | 70 | 71 | setup( 72 | name=PYPI_NAME, 73 | version=version, 74 | description=DESCRIPTION, 75 | long_description=long_description, 76 | author=AUTHOR, 77 | author_email=EMAIL, 78 | url=URL, 79 | py_modules=[NAME], 80 | # entry_points={ 81 | # 'console_scripts': ['mycli=mymodule:cli'], 82 | # }, 83 | install_requires=INSTALL_REQUIRES, 84 | tests_require=TESTS_REQUIRE, 85 | setup_requires=['pytest-runner'], 86 | include_package_data=True, 87 | packages=find_packages(where="src"), 88 | package_dir={"": "src"}, 89 | license='MIT', 90 | classifiers=[ 91 | # Trove classifiers 92 | # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers 93 | 'License :: OSI Approved :: MIT License', 94 | 'Programming Language :: Python', 95 | 'Programming Language :: Python :: 2.7', 96 | 'Programming Language :: Python :: 3', 97 | 'Programming Language :: Python :: 3.3', 98 | 'Programming Language :: Python :: 3.4', 99 | 'Programming Language :: Python :: 3.5', 100 | 'Programming Language :: Python :: 3.6', 101 | 'Programming Language :: Python :: 3.7', 102 | 'Programming Language :: Python :: Implementation :: CPython', 103 | 'Programming Language :: Python :: Implementation :: PyPy', 104 | 'Topic :: Software Development :: Libraries', 105 | 'Development Status :: 3 - Alpha', 106 | ], 107 | # $ setup.py publish support. 108 | cmdclass={'upload': UploadCommand}, 109 | ) 110 | -------------------------------------------------------------------------------- /src/nano/__init__.py: -------------------------------------------------------------------------------- 1 | from .accounts import KNOWN_ACCOUNT_IDS, KNOWN_ACCOUNT_NAMES, generate_account 2 | from .blocks import GENESIS_BLOCK_HASH 3 | from .conversion import convert, UNITS_TO_RAW 4 | from .rpc import RPCClient, RPCException 5 | from .version import __version__ 6 | -------------------------------------------------------------------------------- /src/nano/accounts.py: -------------------------------------------------------------------------------- 1 | """ 2 | Accounts module 3 | 4 | ``nano.accounts.KNOWN_ACCOUNT_IDS``: dict of account ids => names eg. 5 | 6 | >>> KNOWN_ACCOUNT_IDS['xrb_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est'] 7 | 'Developer Fund' 8 | 9 | ``nano.accounts.KNOWN_ACCOUNT_NAMES``: dict of names => account ids 10 | 11 | >>> KNOWN_ACCOUNT_NAMES['Burn'] 12 | 'xrb_1111111111111111111111111111111111111111111111111111hifc8npp' 13 | 14 | """ 15 | 16 | import random 17 | from binascii import hexlify, unhexlify 18 | 19 | from .crypto import b32xrb_encode, b32xrb_decode, address_checksum, keypair_from_seed 20 | 21 | KNOWN_ACCOUNT_IDS = { 22 | 'xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3': 'Genesis', 23 | 'xrb_13ezf4od79h1tgj9aiu4djzcmmguendtjfuhwfukhuucboua8cpoihmh8byo': 'Landing', 24 | 'xrb_35jjmmmh81kydepzeuf9oec8hzkay7msr6yxagzxpcht7thwa5bus5tomgz9': 'Faucet', 25 | 'xrb_1111111111111111111111111111111111111111111111111111hifc8npp': 'Burn', 26 | 'xrb_3wm37qz19zhei7nzscjcopbrbnnachs4p1gnwo5oroi3qonw6inwgoeuufdp': 'Developer Donations', 27 | 'xrb_1ipx847tk8o46pwxt5qjdbncjqcbwcc1rrmqnkztrfjy5k7z4imsrata9est': 'Developer Fund', 28 | 'xrb_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4': 'Official representative #1', 29 | 'xrb_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou': 'Official representative #2', 30 | 'xrb_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p': 'Official representative #3', 31 | 'xrb_3dmtrrws3pocycmbqwawk6xs7446qxa36fcncush4s1pejk16ksbmakis78m': 'Official representative #4', 32 | 'xrb_3hd4ezdgsp15iemx7h81in7xz5tpxi43b6b41zn3qmwiuypankocw3awes5k': 'Official representative #5', 33 | 'xrb_1awsn43we17c1oshdru4azeqjz9wii41dy8npubm4rg11so7dx3jtqgoeahy': 'Official representative #6', 34 | 'xrb_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs': 'Official representative #7', 35 | 'xrb_1hza3f7wiiqa7ig3jczyxj5yo86yegcmqk3criaz838j91sxcckpfhbhhra1': 'Official representative #8', 36 | 'xrb_3wu7h5in34ntmbiremyxtszx7ufgkceb3jx8orkuncyytcxwzrawuf3dy3sh': 'RaiWalletBot', 37 | 'xrb_16k5pimotz9zehjk795wa4qcx54mtusk8hc5mdsjgy57gnhbj3hj6zaib4ic': 'RaiWalletBot representative', 38 | 'xrb_39ymww61tksoddjh1e43mprw5r8uu1318it9z3agm7e6f96kg4ndqg9tuds4': 'BitGrail Representative 1', 39 | 'xrb_31a51k53fdzam7bhrgi4b67py9o7wp33rec1hi7k6z1wsgh8oagqs7bui9p1': 'BitGrail Representative 2', 40 | 'xrb_3decyj8e1kpzrthikh79x6dwhn8ei81grennibmt43mcm9o8fgxqd8t46whj': 'Mercatox Representative', 41 | 'xrb_369dmjiipkuwar1zxxiuixaqq1kfmyp9rwsttksxdbf8zi3qwit1kxiujpdo': 'RaiBlocks Community', 42 | 'xrb_1niabkx3gbxit5j5yyqcpas71dkffggbr6zpd3heui8rpoocm5xqbdwq44oh': 'KuCoin Representative', 43 | } 44 | 45 | KNOWN_ACCOUNT_NAMES = dict( 46 | (name, account) for account, name in KNOWN_ACCOUNT_IDS.items() 47 | ) 48 | 49 | 50 | def public_key_to_xrb_address(public_key): 51 | """ 52 | Convert `public_key` (bytes) to an xrb address 53 | 54 | >>> public_key_to_xrb_address(b'00000000000000000000000000000000') 55 | 'xrb_1e3i81r51e3i81r51e3i81r51e3i81r51e3i81r51e3i81r51e3imxssakuq' 56 | 57 | :param public_key: public key in bytes 58 | :type public_key: bytes 59 | 60 | :return: xrb address 61 | :rtype: str 62 | """ 63 | 64 | if not len(public_key) == 32: 65 | raise ValueError('public key must be 32 chars') 66 | 67 | padded = b'000' + public_key 68 | address = b32xrb_encode(padded)[4:] 69 | checksum = b32xrb_encode(address_checksum(public_key)) 70 | return 'xrb_' + address.decode('ascii') + checksum.decode('ascii') 71 | 72 | 73 | def xrb_address_to_public_key(address): 74 | """ 75 | Convert an xrb address to public key in bytes 76 | 77 | >>> xrb_address_to_public_key('xrb_1e3i81r51e3i81r51e3i81r51e3i'\ 78 | '81r51e3i81r51e3i81r51e3imxssakuq') 79 | b'00000000000000000000000000000000' 80 | 81 | :param address: xrb address 82 | :type address: bytes 83 | 84 | :return: public key in bytes 85 | :rtype: bytes 86 | 87 | :raises ValueError: 88 | """ 89 | 90 | address = bytearray(address, 'ascii') 91 | 92 | if not address.startswith(b'xrb_'): 93 | raise ValueError('address does not start with xrb_: %s' % address) 94 | 95 | if len(address) != 64: 96 | raise ValueError('address must be 64 chars long: %s' % address) 97 | 98 | address = bytes(address) 99 | key_b32xrb = b'1111' + address[4:56] 100 | key_bytes = b32xrb_decode(key_b32xrb)[3:] 101 | checksum = address[56:] 102 | 103 | if b32xrb_encode(address_checksum(key_bytes)) != checksum: 104 | raise ValueError('invalid address, invalid checksum: %s' % address) 105 | 106 | return key_bytes 107 | 108 | 109 | def generate_account(seed=None, index=0): 110 | """ 111 | Generates an adhoc account and keypair 112 | 113 | >>> account = generate_account(seed=unhexlify('0'*64)) 114 | {'address': u'xrb_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7', 115 | 'private_key_bytes': '\x9f\x0eDLi\xf7zI\xbd\x0b\xe8\x9d\xb9,8\xfeq>\tc\x16\\\xca\x12\xfa\xf5q-vW\x12\x0f', 116 | 'private_key_hex': '9f0e444c69f77a49bd0be89db92c38fe713e0963165cca12faf5712d7657120f', 117 | 'public_key_bytes': '\xc0\x08\xb8\x14\xa7\xd2i\xa1\xfa>> convert(value='1.5', from_unit='xrb', to_unit='krai') 59 | Decimal('0.0015') 60 | """ 61 | 62 | if isinstance(value, float): 63 | raise ValueError( 64 | "float values can lead to unexpected precision loss, please use a" 65 | " Decimal or string eg." 66 | " convert('%s', %r, %r)" % (value, from_unit, to_unit) 67 | ) 68 | 69 | if from_unit not in UNITS_TO_RAW: 70 | raise ValueError('unknown unit: %r' % from_unit) 71 | 72 | if to_unit not in UNITS_TO_RAW: 73 | raise ValueError('unknown unit: %r' % to_unit) 74 | 75 | try: 76 | value = Decimal(value) 77 | except Exception: 78 | raise ValueError('not a number: %r' % value) 79 | 80 | from_value_in_base = UNITS_TO_RAW[from_unit] 81 | to_value_in_base = UNITS_TO_RAW[to_unit] 82 | 83 | result = value * (from_value_in_base / to_value_in_base) 84 | 85 | return result.normalize() 86 | 87 | 88 | _populate_units() 89 | -------------------------------------------------------------------------------- /src/nano/crypto.py: -------------------------------------------------------------------------------- 1 | import string 2 | import struct 3 | from base64 import b32encode, b32decode 4 | 5 | from pyblake2 import blake2b 6 | 7 | from . import ed25519_blake2 8 | 9 | maketrans = hasattr(bytes, 'maketrans') and bytes.maketrans or string.maketrans 10 | B32_ALPHABET = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' 11 | XRB_ALPHABET = b'13456789abcdefghijkmnopqrstuwxyz' 12 | XRB_ENCODE_TRANS = maketrans(B32_ALPHABET, XRB_ALPHABET) 13 | XRB_DECODE_TRANS = maketrans(XRB_ALPHABET, B32_ALPHABET) 14 | 15 | 16 | def address_checksum(address): 17 | """ 18 | Returns the checksum in bytes for an address in bytes 19 | """ 20 | address_bytes = address 21 | h = blake2b(digest_size=5) 22 | h.update(address_bytes) 23 | checksum = bytearray(h.digest()) 24 | checksum.reverse() 25 | return checksum 26 | 27 | 28 | def private_to_public_key(private_key): 29 | """ 30 | Returns the public key for a private key 31 | 32 | :param private_key: private key (in bytes) to get public key for 33 | :type private_key: bytes 34 | """ 35 | return ed25519_blake2.publickey_unsafe(private_key) 36 | 37 | 38 | def keypair_from_seed(seed, index=0): 39 | """ 40 | Generates a deterministic keypair from `seed` based on `index` 41 | 42 | :param seed: bytes value of seed 43 | :type seed: bytes 44 | 45 | :param index: offset from seed 46 | :type index: int 47 | 48 | :return: dict of the form: { 49 | 'private': private_key 50 | 'public': public_key 51 | } 52 | """ 53 | 54 | h = blake2b(digest_size=32) 55 | h.update(seed + struct.pack(">L", index)) 56 | priv_key = h.digest() 57 | pub_key = private_to_public_key(priv_key) 58 | return {'private': priv_key, 'public': pub_key} 59 | 60 | 61 | def b32xrb_encode(value): 62 | """ 63 | Encodes bytes to xrb encoding which uses the base32 algorithm 64 | with a custom alphabet: '13456789abcdefghijkmnopqrstuwxyz' 65 | 66 | :param value: the value to encode 67 | :type: bytes 68 | 69 | :return: encoded value 70 | :rtype: bytes 71 | 72 | >>> b32xrb_encode(b'deadbeef') 73 | b'ejkp4s54eokpe===' 74 | """ 75 | return b32encode(value).translate(XRB_ENCODE_TRANS) 76 | 77 | 78 | def b32xrb_decode(value): 79 | """ 80 | Decodes a value in xrb encoding to bytes using base32 algorithm 81 | with a custom alphabet: '13456789abcdefghijkmnopqrstuwxyz' 82 | 83 | :param value: the value to decode 84 | :type: bytes 85 | 86 | :return: decoded value 87 | :rtype: bytes 88 | 89 | >>> b32xrb_decode(b'fxop4ya=') 90 | b'okay' 91 | """ 92 | return b32decode(value.translate(XRB_DECODE_TRANS)) 93 | 94 | 95 | def verify_signature(message, signature, public_key): 96 | """ 97 | Verifies `signature` is correct for a `message` signed with `public_key` 98 | 99 | :param message: message to check 100 | :type message: bytes 101 | 102 | :param signature: signature to check 103 | :type signature: bytes 104 | 105 | :param public_key: public_key to check 106 | :type public_key: bytes 107 | 108 | :return: True if valid, False otherwise 109 | :rtype: bool 110 | """ 111 | 112 | try: 113 | ed25519_blake2.checkvalid(signature, message, public_key) 114 | except ed25519_blake2.SignatureMismatch: 115 | return False 116 | return True 117 | 118 | 119 | def sign_message(message, private_key, public_key=None): 120 | """ 121 | Signs a `message` using `private_key` and `public_key` 122 | 123 | .. warning:: Not safe to use with secret keys or secret data. See module 124 | docstring. This function should be used for testing only. 125 | 126 | :param message: the message to sign 127 | :type message: bytes 128 | 129 | :param private_key: private key used to sign message 130 | :type private_key: bytes 131 | 132 | :param public_key: public key used to sign message 133 | :type public_key: bytes 134 | 135 | :return: the signature of the signed message 136 | :rtype: bytes 137 | """ 138 | 139 | if public_key is None: 140 | public_key = private_to_public_key(private_key) 141 | 142 | return ed25519_blake2.signature_unsafe(message, private_key, public_key) 143 | -------------------------------------------------------------------------------- /src/nano/ed25519_blake2.py: -------------------------------------------------------------------------------- 1 | """ 2 | Modified version of ed22519 that uses pyblake2 hashes instead of sha512 3 | 4 | Original at https://github.com/pyca/ed25519/blob/master/ed25519.py 5 | 6 | ed25519.py - Optimized version of the reference implementation of Ed25519 7 | 8 | Written in 2011? by Daniel J. Bernstein 9 | 2013 by Donald Stufft 10 | 2013 by Alex Gaynor 11 | 2013 by Greg Price 12 | 13 | To the extent possible under law, the author(s) have dedicated all copyright 14 | and related and neighboring rights to this software to the public domain 15 | worldwide. This software is distributed without any warranty. 16 | 17 | You should have received a copy of the CC0 Public Domain Dedication along 18 | with this software. If not, see 19 | . 20 | 21 | NB: This code is not safe for use with secret keys or secret data. 22 | The only safe use of this code is for verifying signatures on public messages. 23 | Functions for computing the public key of a secret key and for signing 24 | a message are included, namely publickey_unsafe and signature_unsafe, 25 | for testing purposes only. 26 | The root of the problem is that Python's long-integer arithmetic is 27 | not designed for use in cryptography. Specifically, it may take more 28 | or less time to execute an operation depending on the values of the 29 | inputs, and its memory access patterns may also depend on the inputs. 30 | This opens it to timing and cache side-channel attacks which can 31 | disclose data to an attacker. We rely on Python's long-integer 32 | arithmetic, so we cannot handle secrets without risking their disclosure. 33 | """ 34 | 35 | from pyblake2 import blake2b 36 | 37 | b = 256 38 | q = 2 ** 255 - 19 39 | l = 2 ** 252 + 27742317777372353535851937790883648493 40 | 41 | 42 | def H(m): 43 | return bytearray(blake2b(m).digest()) 44 | 45 | 46 | def pow2(x, p): 47 | """== pow(x, 2**p, q)""" 48 | while p > 0: 49 | x = x * x % q 50 | p -= 1 51 | return x 52 | 53 | 54 | def inv(z): 55 | """$= z^{-1} \mod q$, for z != 0""" 56 | # Adapted from curve25519_athlon.c in djb's Curve25519. 57 | z2 = z * z % q # 2 58 | z9 = pow2(z2, 2) * z % q # 9 59 | z11 = z9 * z2 % q # 11 60 | z2_5_0 = (z11 * z11) % q * z9 % q # 31 == 2^5 - 2^0 61 | z2_10_0 = pow2(z2_5_0, 5) * z2_5_0 % q # 2^10 - 2^0 62 | z2_20_0 = pow2(z2_10_0, 10) * z2_10_0 % q # ... 63 | z2_40_0 = pow2(z2_20_0, 20) * z2_20_0 % q 64 | z2_50_0 = pow2(z2_40_0, 10) * z2_10_0 % q 65 | z2_100_0 = pow2(z2_50_0, 50) * z2_50_0 % q 66 | z2_200_0 = pow2(z2_100_0, 100) * z2_100_0 % q 67 | z2_250_0 = pow2(z2_200_0, 50) * z2_50_0 % q # 2^250 - 2^0 68 | return pow2(z2_250_0, 5) * z11 % q # 2^255 - 2^5 + 11 = q - 2 69 | 70 | 71 | d = -121665 * inv(121666) % q 72 | I = pow(2, (q - 1) // 4, q) 73 | 74 | 75 | def xrecover(y): 76 | xx = (y * y - 1) * inv(d * y * y + 1) 77 | x = pow(xx, (q + 3) // 8, q) 78 | 79 | if (x * x - xx) % q != 0: 80 | x = (x * I) % q 81 | 82 | if x % 2 != 0: 83 | x = q - x 84 | 85 | return x 86 | 87 | 88 | By = 4 * inv(5) 89 | Bx = xrecover(By) 90 | B = (Bx % q, By % q, 1, (Bx * By) % q) 91 | ident = (0, 1, 1, 0) 92 | 93 | 94 | def edwards_add(P, Q): 95 | # This is formula sequence 'addition-add-2008-hwcd-3' from 96 | # http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html 97 | (x1, y1, z1, t1) = P 98 | (x2, y2, z2, t2) = Q 99 | 100 | a = (y1 - x1) * (y2 - x2) % q 101 | b = (y1 + x1) * (y2 + x2) % q 102 | c = t1 * 2 * d * t2 % q 103 | dd = z1 * 2 * z2 % q 104 | e = b - a 105 | f = dd - c 106 | g = dd + c 107 | h = b + a 108 | x3 = e * f 109 | y3 = g * h 110 | t3 = e * h 111 | z3 = f * g 112 | 113 | return x3 % q, y3 % q, z3 % q, t3 % q 114 | 115 | 116 | def edwards_double(P): 117 | # This is formula sequence 'dbl-2008-hwcd' from 118 | # http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html 119 | (x1, y1, z1, t1) = P 120 | 121 | a = x1 * x1 % q 122 | b = y1 * y1 % q 123 | c = 2 * z1 * z1 % q 124 | # dd = -a 125 | e = ((x1 + y1) * (x1 + y1) - a - b) % q 126 | g = -a + b # dd + b 127 | f = g - c 128 | h = -a - b # dd - b 129 | x3 = e * f 130 | y3 = g * h 131 | t3 = e * h 132 | z3 = f * g 133 | 134 | return x3 % q, y3 % q, z3 % q, t3 % q 135 | 136 | 137 | def scalarmult(P, e): 138 | if e == 0: 139 | return ident 140 | Q = scalarmult(P, e // 2) 141 | Q = edwards_double(Q) 142 | if e & 1: 143 | Q = edwards_add(Q, P) 144 | return Q 145 | 146 | 147 | # Bpow[i] == scalarmult(B, 2**i) 148 | Bpow = [] 149 | 150 | 151 | def make_Bpow(): 152 | P = B 153 | for i in range(253): 154 | Bpow.append(P) 155 | P = edwards_double(P) 156 | 157 | 158 | make_Bpow() 159 | 160 | 161 | def scalarmult_B(e): 162 | """ 163 | Implements scalarmult(B, e) more efficiently. 164 | """ 165 | # scalarmult(B, l) is the identity 166 | e = e % l 167 | P = ident 168 | for i in range(253): 169 | if e & 1: 170 | P = edwards_add(P, Bpow[i]) 171 | e = e // 2 172 | assert e == 0, e 173 | return P 174 | 175 | 176 | def encodeint(y): 177 | bits = [(y >> i) & 1 for i in range(b)] 178 | return bytearray( 179 | sum([bits[i * 8 + j] << j for j in range(8)]) for i in range(b // 8) 180 | ) 181 | 182 | 183 | def encodepoint(P): 184 | (x, y, z, t) = P 185 | zi = inv(z) 186 | x = (x * zi) % q 187 | y = (y * zi) % q 188 | bits = [(y >> i) & 1 for i in range(b - 1)] + [x & 1] 189 | return bytearray( 190 | sum([bits[i * 8 + j] << j for j in range(8)]) for i in range(b // 8) 191 | ) 192 | 193 | 194 | def bit(h, i): 195 | return (h[i // 8] >> (i % 8)) & 1 196 | 197 | 198 | def publickey_unsafe(sk, hash_func=H): 199 | """ 200 | Not safe to use with secret keys or secret data. 201 | See module docstring. This function should be used for testing only. 202 | """ 203 | h = hash_func(sk) 204 | a = 2 ** (b - 2) + sum(2 ** i * bit(h, i) for i in range(3, b - 2)) 205 | A = scalarmult_B(a) 206 | return bytes(encodepoint(A)) 207 | 208 | 209 | def Hint(m, hasher=H): 210 | h = hasher(m) 211 | return sum(2 ** i * bit(h, i) for i in range(2 * b)) 212 | 213 | 214 | def signature_unsafe(m, sk, pk, hash_func=H): 215 | """ 216 | Not safe to use with secret keys or secret data. 217 | See module docstring. This function should be used for testing only. 218 | """ 219 | h = hash_func(sk) 220 | a = 2 ** (b - 2) + sum(2 ** i * bit(h, i) for i in range(3, b - 2)) 221 | r = Hint(bytearray([h[j] for j in range(b // 8, b // 4)]) + m) 222 | R = scalarmult_B(r) 223 | S = (r + Hint(encodepoint(R) + pk + m) * a) % l 224 | return bytes(encodepoint(R) + encodeint(S)) 225 | 226 | 227 | def isoncurve(P): 228 | (x, y, z, t) = P 229 | return ( 230 | z % q != 0 231 | and x * y % q == z * t % q 232 | and (y * y - x * x - z * z - d * t * t) % q == 0 233 | ) 234 | 235 | 236 | def decodeint(s): 237 | return sum(2 ** i * bit(s, i) for i in range(0, b)) 238 | 239 | 240 | def decodepoint(s): 241 | y = sum(2 ** i * bit(s, i) for i in range(0, b - 1)) 242 | x = xrecover(y) 243 | if x & 1 != bit(s, b - 1): 244 | x = q - x 245 | P = (x, y, 1, (x * y) % q) 246 | if not isoncurve(P): 247 | raise ValueError("decoding point that is not on curve") 248 | return P 249 | 250 | 251 | class SignatureMismatch(Exception): 252 | pass 253 | 254 | 255 | def checkvalid(s, m, pk): 256 | """ 257 | Not safe to use when any argument is secret. 258 | See module docstring. This function should be used only for 259 | verifying public signatures of public messages. 260 | """ 261 | if len(s) != b // 4: 262 | raise ValueError("signature length is wrong") 263 | 264 | if len(pk) != b // 8: 265 | raise ValueError("public-key length is wrong") 266 | 267 | s = bytearray(s) 268 | m = bytearray(m) 269 | pk = bytearray(pk) 270 | 271 | R = decodepoint(s[: b // 8]) 272 | A = decodepoint(pk) 273 | S = decodeint(s[b // 8 : b // 4]) 274 | h = Hint(encodepoint(R) + pk + m) 275 | 276 | (x1, y1, z1, t1) = P = scalarmult_B(S) 277 | (x2, y2, z2, t2) = Q = edwards_add(R, scalarmult(A, h)) 278 | 279 | if ( 280 | not isoncurve(P) 281 | or not isoncurve(Q) 282 | or (x1 * z2 - x2 * z1) % q != 0 283 | or (y1 * z2 - y2 * z1) % q != 0 284 | ): 285 | raise SignatureMismatch("signature does not pass verification") 286 | -------------------------------------------------------------------------------- /src/nano/version.py: -------------------------------------------------------------------------------- 1 | __version__ = '2.1.0' 2 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | from collections import OrderedDict 4 | 5 | import pytest 6 | import requests 7 | import requests_mock 8 | 9 | 10 | class MockRPCMatchException(Exception): 11 | """ Exception used to check if a mock response is missing """ 12 | 13 | 14 | def load_mock_rpc_tests(): 15 | jsons_directory = os.path.join( 16 | os.path.dirname(os.path.realpath(__file__)), 'fixtures', 'rpc' 17 | ) 18 | 19 | result = OrderedDict() 20 | for filename in os.listdir(jsons_directory): 21 | if filename.endswith('.json'): 22 | action = filename[: -len('.json')] 23 | try: 24 | tests = json.load(open(os.path.join(jsons_directory, filename))) 25 | except Exception: 26 | print('Failed to load %s test' % filename) 27 | raise 28 | result[action] = tests 29 | return result 30 | 31 | 32 | @pytest.fixture 33 | def mock_rpc_session(): 34 | adapter = requests_mock.Adapter() 35 | session = requests.Session() 36 | session.mount('mock', adapter) 37 | session.adapter = adapter 38 | 39 | responses = {} 40 | 41 | def _text_callback(request, context): 42 | request_json = json.dumps(request.json(), sort_keys=True) 43 | if request_json not in responses: 44 | raise MockRPCMatchException( 45 | 'No mock response found for this request: %s' 46 | % json.dumps(request.json(), sort_keys=True, indent=2) 47 | ) 48 | return responses[request_json] 49 | 50 | for action, tests in load_mock_rpc_tests().items(): 51 | for test in tests: 52 | req_body = json.dumps(test['request'], sort_keys=True) 53 | res_body = json.dumps(test['response'], sort_keys=True) 54 | responses[req_body] = res_body 55 | 56 | adapter.register_uri('POST', 'mock://localhost:7076/', text=_text_callback) 57 | 58 | return session 59 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_balance.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 5 | }, 6 | "expected": { 7 | "balance": 10000, 8 | "pending": 10000 9 | }, 10 | "request": { 11 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 12 | "action": "account_balance" 13 | }, 14 | "response": { 15 | "balance": "10000", 16 | "pending": "10000" 17 | } 18 | }, 19 | { 20 | "args": { 21 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi99999999" 22 | }, 23 | "expected": null, 24 | "request": { 25 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi99999999", 26 | "action": "account_balance" 27 | }, 28 | "response": { 29 | "error": "Bad account number" 30 | } 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_block_count.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" 5 | }, 6 | "expected": 19, 7 | "request": { 8 | "account": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", 9 | "action": "account_block_count" 10 | }, 11 | "response": { 12 | "block_count": "19" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_create.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 7 | "request": { 8 | "action": "account_create", 9 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 10 | }, 11 | "response": { 12 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 13 | } 14 | }, 15 | { 16 | "args": { 17 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 18 | "work": false 19 | }, 20 | "expected": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 21 | "request": { 22 | "action": "account_create", 23 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 24 | "work": "false" 25 | }, 26 | "response": { 27 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 28 | } 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_get.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "key": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039" 5 | }, 6 | "expected": "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", 7 | "request": { 8 | "action": "account_get", 9 | "key": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039" 10 | }, 11 | "response": { 12 | "account": "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_history.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 5 | "count": 1 6 | }, 7 | "expected": [ 8 | { 9 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 10 | "amount": 100000000000000000000000000000000, 11 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 12 | "type": "receive" 13 | } 14 | ], 15 | "request": { 16 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 17 | "action": "account_history", 18 | "count": "1" 19 | }, 20 | "response": { 21 | "history": [ 22 | { 23 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 24 | "amount": "100000000000000000000000000000000", 25 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 26 | "type": "receive" 27 | } 28 | ] 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_info.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" 5 | }, 6 | "expected": { 7 | "balance": 235580100176034320859259343606608761791, 8 | "block_count": 33, 9 | "frontier": "FF84533A571D953A596EA401FD41743AC85D04F406E76FDE4408EAED50B473C5", 10 | "modified_timestamp": 1501793775, 11 | "open_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 12 | "representative_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948" 13 | }, 14 | "request": { 15 | "account": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", 16 | "action": "account_info" 17 | }, 18 | "response": { 19 | "balance": "235580100176034320859259343606608761791", 20 | "block_count": "33", 21 | "frontier": "FF84533A571D953A596EA401FD41743AC85D04F406E76FDE4408EAED50B473C5", 22 | "modified_timestamp": "1501793775", 23 | "open_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 24 | "representative_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948" 25 | } 26 | }, 27 | { 28 | "args": { 29 | "account": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", 30 | "pending": true, 31 | "representative": true, 32 | "weight": true 33 | }, 34 | "expected": { 35 | "balance": 235580100176034320859259343606608761791, 36 | "block_count": 33, 37 | "frontier": "FF84533A571D953A596EA401FD41743AC85D04F406E76FDE4408EAED50B473C5", 38 | "modified_timestamp": 1501793775, 39 | "open_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 40 | "pending": 2309370929000000000000000000000000, 41 | "representative": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", 42 | "representative_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 43 | "weight": 1105577030935649664609129644855132177 44 | }, 45 | "request": { 46 | "account": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", 47 | "action": "account_info", 48 | "pending": "true", 49 | "representative": "true", 50 | "weight": "true" 51 | }, 52 | "response": { 53 | "balance": "235580100176034320859259343606608761791", 54 | "block_count": "33", 55 | "frontier": "FF84533A571D953A596EA401FD41743AC85D04F406E76FDE4408EAED50B473C5", 56 | "modified_timestamp": "1501793775", 57 | "open_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 58 | "pending": "2309370929000000000000000000000000", 59 | "representative": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", 60 | "representative_block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 61 | "weight": "1105577030935649664609129644855132177" 62 | } 63 | } 64 | ] 65 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_key.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx" 5 | }, 6 | "expected": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039", 7 | "request": { 8 | "account": "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", 9 | "action": "account_key" 10 | }, 11 | "response": { 12 | "key": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_list.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": [ 7 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 8 | ], 9 | "request": { 10 | "action": "account_list", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "accounts": [ 15 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 16 | ] 17 | } 18 | } 19 | ] 20 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_move.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "accounts": [ 5 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 6 | ], 7 | "source": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 8 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 9 | }, 10 | "expected": true, 11 | "request": { 12 | "accounts": [ 13 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 14 | ], 15 | "action": "account_move", 16 | "source": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 17 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 18 | }, 19 | "response": { 20 | "moved": "1" 21 | } 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_remove.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_39a73oy5ungrhxy5z5oao1xso4zo7dmgpjd4u74xcrx3r1w6rtazuouw6qfi", 5 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | }, 7 | "expected": true, 8 | "request": { 9 | "account": "xrb_39a73oy5ungrhxy5z5oao1xso4zo7dmgpjd4u74xcrx3r1w6rtazuouw6qfi", 10 | "action": "account_remove", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "removed": "1" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_representative.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_39a73oy5ungrhxy5z5oao1xso4zo7dmgpjd4u74xcrx3r1w6rtazuouw6qfi" 5 | }, 6 | "expected": "xrb_16u1uufyoig8777y6r8iqjtrw8sg8maqrm36zzcm95jmbd9i9aj5i8abr8u5", 7 | "request": { 8 | "account": "xrb_39a73oy5ungrhxy5z5oao1xso4zo7dmgpjd4u74xcrx3r1w6rtazuouw6qfi", 9 | "action": "account_representative" 10 | }, 11 | "response": { 12 | "representative": "xrb_16u1uufyoig8777y6r8iqjtrw8sg8maqrm36zzcm95jmbd9i9aj5i8abr8u5" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_representative_set.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_39a73oy5ungrhxy5z5oao1xso4zo7dmgpjd4u74xcrx3r1w6rtazuouw6qfi", 5 | "representative": "xrb_16u1uufyoig8777y6r8iqjtrw8sg8maqrm36zzcm95jmbd9i9aj5i8abr8u5", 6 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 7 | }, 8 | "expected": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 9 | "request": { 10 | "account": "xrb_39a73oy5ungrhxy5z5oao1xso4zo7dmgpjd4u74xcrx3r1w6rtazuouw6qfi", 11 | "action": "account_representative_set", 12 | "representative": "xrb_16u1uufyoig8777y6r8iqjtrw8sg8maqrm36zzcm95jmbd9i9aj5i8abr8u5", 13 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 14 | }, 15 | "response": { 16 | "block": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 17 | } 18 | }, 19 | { 20 | "args": { 21 | "account": "xrb_39a73oy5ungrhxy5z5oao1xso4zo7dmgpjd4u74xcrx3r1w6rtazuouw6qfi", 22 | "representative": "xrb_16u1uufyoig8777y6r8iqjtrw8sg8maqrm36zzcm95jmbd9i9aj5i8abr8u5", 23 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 24 | "work": "2bf29ef00786a6bc" 25 | }, 26 | "expected": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 27 | "request": { 28 | "account": "xrb_39a73oy5ungrhxy5z5oao1xso4zo7dmgpjd4u74xcrx3r1w6rtazuouw6qfi", 29 | "action": "account_representative_set", 30 | "representative": "xrb_16u1uufyoig8777y6r8iqjtrw8sg8maqrm36zzcm95jmbd9i9aj5i8abr8u5", 31 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 32 | "work": "2bf29ef00786a6bc" 33 | }, 34 | "response": { 35 | "block": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 36 | } 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/account_weight.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 5 | }, 6 | "expected": 10000, 7 | "request": { 8 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 9 | "action": "account_weight" 10 | }, 11 | "response": { 12 | "weight": "10000" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/accounts_balances.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "accounts": [ 5 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 6 | "xrb_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7" 7 | ] 8 | }, 9 | "expected": { 10 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000": { 11 | "balance": 10000, 12 | "pending": 10000 13 | }, 14 | "xrb_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7": { 15 | "balance": 10000000, 16 | "pending": 0 17 | } 18 | }, 19 | "request": { 20 | "accounts": [ 21 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 22 | "xrb_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7" 23 | ], 24 | "action": "accounts_balances" 25 | }, 26 | "response": { 27 | "balances": { 28 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000": { 29 | "balance": "10000", 30 | "pending": "10000" 31 | }, 32 | "xrb_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7": { 33 | "balance": "10000000", 34 | "pending": "0" 35 | } 36 | } 37 | } 38 | } 39 | ] 40 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/accounts_create.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "count": 2, 5 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | }, 7 | "expected": [ 8 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 9 | "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3s00000000" 10 | ], 11 | "request": { 12 | "action": "accounts_create", 13 | "count": "2", 14 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 15 | }, 16 | "response": { 17 | "accounts": [ 18 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 19 | "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3s00000000" 20 | ] 21 | } 22 | }, 23 | { 24 | "args": { 25 | "count": 2, 26 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 27 | "work": false 28 | }, 29 | "expected": [ 30 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 31 | "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3s00000000" 32 | ], 33 | "request": { 34 | "action": "accounts_create", 35 | "count": "2", 36 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 37 | "work": "false" 38 | }, 39 | "response": { 40 | "accounts": [ 41 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 42 | "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3s00000000" 43 | ] 44 | } 45 | } 46 | ] 47 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/accounts_frontiers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "accounts": [ 5 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", 6 | "xrb_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7" 7 | ] 8 | }, 9 | "expected": { 10 | "xrb_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7": "6A32397F4E95AF025DE29D9BF1ACE864D5404362258E06489FABDBA9DCCC046F", 11 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": "791AF413173EEE674A6FCF633B5DFC0F3C33F397F0DA08E987D9E0741D40D81A" 12 | }, 13 | "request": { 14 | "accounts": [ 15 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", 16 | "xrb_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7" 17 | ], 18 | "action": "accounts_frontiers" 19 | }, 20 | "response": { 21 | "frontiers": { 22 | "xrb_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7": "6A32397F4E95AF025DE29D9BF1ACE864D5404362258E06489FABDBA9DCCC046F", 23 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": "791AF413173EEE674A6FCF633B5DFC0F3C33F397F0DA08E987D9E0741D40D81A" 24 | } 25 | } 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/accounts_pending.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "accounts": [] 5 | }, 6 | "expected": {}, 7 | "request": { 8 | "action": "accounts_pending", 9 | "accounts": [] 10 | }, 11 | "response": { 12 | "blocks": "" 13 | } 14 | }, 15 | { 16 | "args": { 17 | "accounts": [ 18 | "xrb_1111111111111111111111111111111111111111111111111117353trpda", 19 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", 20 | "xrb_tsa8mnijtpxm9fkcm736xtoncuohr33t6k35gi95xu6tergt6p69ck76ogmi" 21 | ], 22 | "count": 1 23 | }, 24 | "expected": { 25 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": [ 26 | "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D" 27 | ], 28 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": [ 29 | "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74" 30 | ], 31 | "xrb_tsa8mnijtpxm9fkcm736xtoncuohr33t6k35gi95xu6tergt6p69ck76ogmi": [] 32 | }, 33 | "request": { 34 | "accounts": [ 35 | "xrb_1111111111111111111111111111111111111111111111111117353trpda", 36 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", 37 | "xrb_tsa8mnijtpxm9fkcm736xtoncuohr33t6k35gi95xu6tergt6p69ck76ogmi" 38 | ], 39 | "action": "accounts_pending", 40 | "count": "1" 41 | }, 42 | "response": { 43 | "blocks": { 44 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": [ 45 | "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D" 46 | ], 47 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": [ 48 | "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74" 49 | ], 50 | "xrb_tsa8mnijtpxm9fkcm736xtoncuohr33t6k35gi95xu6tergt6p69ck76ogmi": "" 51 | } 52 | } 53 | }, 54 | { 55 | "args": { 56 | "accounts": [ 57 | "xrb_1111111111111111111111111111111111111111111111111117353trpda", 58 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" 59 | ], 60 | "count": 1, 61 | "threshold": 1000000000000000000000000 62 | }, 63 | "expected": { 64 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": { 65 | "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D": 6000000000000000000000000000000 66 | }, 67 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { 68 | "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74": 106370018000000000000000000000000 69 | } 70 | }, 71 | "request": { 72 | "accounts": [ 73 | "xrb_1111111111111111111111111111111111111111111111111117353trpda", 74 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" 75 | ], 76 | "action": "accounts_pending", 77 | "count": "1", 78 | "threshold": "1000000000000000000000000" 79 | }, 80 | "response": { 81 | "blocks": { 82 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": { 83 | "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D": "6000000000000000000000000000000" 84 | }, 85 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { 86 | "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74": "106370018000000000000000000000000" 87 | } 88 | } 89 | } 90 | }, 91 | { 92 | "args": { 93 | "accounts": [ 94 | "xrb_1111111111111111111111111111111111111111111111111117353trpda", 95 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" 96 | ], 97 | "count": 1, 98 | "source": true 99 | }, 100 | "expected": { 101 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": { 102 | "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D": { 103 | "amount": 6000000000000000000000000000000, 104 | "source": "xrb_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr" 105 | } 106 | }, 107 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { 108 | "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74": { 109 | "amount": 106370018000000000000000000000000, 110 | "source": "xrb_13ezf4od79h1tgj9aiu4djzcmmguendtjfuhwfukhuucboua8cpoihmh8byo" 111 | } 112 | } 113 | }, 114 | "request": { 115 | "accounts": [ 116 | "xrb_1111111111111111111111111111111111111111111111111117353trpda", 117 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3" 118 | ], 119 | "action": "accounts_pending", 120 | "count": "1", 121 | "source": "true" 122 | }, 123 | "response": { 124 | "blocks": { 125 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": { 126 | "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D": { 127 | "amount": "6000000000000000000000000000000", 128 | "source": "xrb_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr" 129 | } 130 | }, 131 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { 132 | "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74": { 133 | "amount": "106370018000000000000000000000000", 134 | "source": "xrb_13ezf4od79h1tgj9aiu4djzcmmguendtjfuhwfukhuucboua8cpoihmh8byo" 135 | } 136 | } 137 | } 138 | } 139 | } 140 | ] 141 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/available_supply.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": 10000, 4 | "request": { 5 | "action": "available_supply" 6 | }, 7 | "response": { 8 | "available": "10000" 9 | } 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/block.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": { 7 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 8 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 9 | "signature": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 10 | "source": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 11 | "type": "open", 12 | "work": "0000000000000000" 13 | }, 14 | "request": { 15 | "action": "block", 16 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 17 | }, 18 | "response": { 19 | "contents": "{\n\"account\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\",\n\"work\": \"0000000000000000\",\n\"source\": \"FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4\",\n\"representative\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\",\n\"signature\": \"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n\"type\": \"open\"\n}" 20 | } 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/block_account.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 7 | "request": { 8 | "action": "block_account", 9 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 10 | }, 11 | "response": { 12 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/block_count.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": { 4 | "count": 1000, 5 | "unchecked": 10 6 | }, 7 | "request": { 8 | "action": "block_count" 9 | }, 10 | "response": { 11 | "count": "1000", 12 | "unchecked": "10" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/block_count_type.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": { 4 | "change": 50, 5 | "open": 100, 6 | "receive": 900, 7 | "send": 1000 8 | }, 9 | "request": { 10 | "action": "block_count_type" 11 | }, 12 | "response": { 13 | "change": "50", 14 | "open": "100", 15 | "receive": "900", 16 | "send": "1000" 17 | } 18 | } 19 | ] 20 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/block_create.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_3kdbxitaj7f6mrir6miiwtw4muhcc58e6tn5st6rfaxsdnb7gr4roudwn951", 5 | "key": "0000000000000000000000000000000000000000000000000000000000000001", 6 | "representative": "xrb_1hza3f7wiiqa7ig3jczyxj5yo86yegcmqk3criaz838j91sxcckpfhbhhra1", 7 | "source": "19D3D919475DEED4696B5D13018151D1AF88B2BD3BCFF048B45031C1F36D1858", 8 | "type": "open" 9 | }, 10 | "expected": { 11 | "block": { 12 | "account": "xrb_3kdbxitaj7f6mrir6miiwtw4muhcc58e6tn5st6rfaxsdnb7gr4roudwn951", 13 | "representative": "xrb_1hza3f7wiiqa7ig3jczyxj5yo86yegcmqk3criaz838j91sxcckpfhbhhra1", 14 | "signature": "5974324F8CC42DA56F62FC212A17886BDCB18DE363D04DA84EEDC99CB4A33919D14A2CF9DE9D534FAA6D0B91D01F0622205D898293525E692586C84F2DCF9208", 15 | "source": "19D3D919475DEED4696B5D13018151D1AF88B2BD3BCFF048B45031C1F36D1858", 16 | "type": "open", 17 | "work": "4ec76c9bda2325ed" 18 | }, 19 | "hash": "F47B23107E5F34B2CE06F562B5C435DF72A533251CB414C51B2B62A8F63A00E4" 20 | }, 21 | "request": { 22 | "account": "xrb_3kdbxitaj7f6mrir6miiwtw4muhcc58e6tn5st6rfaxsdnb7gr4roudwn951", 23 | "action": "block_create", 24 | "key": "0000000000000000000000000000000000000000000000000000000000000001", 25 | "representative": "xrb_1hza3f7wiiqa7ig3jczyxj5yo86yegcmqk3criaz838j91sxcckpfhbhhra1", 26 | "source": "19D3D919475DEED4696B5D13018151D1AF88B2BD3BCFF048B45031C1F36D1858", 27 | "type": "open" 28 | }, 29 | "response": { 30 | "block": "{\n \"type\": \"open\",\n \"source\": \"19D3D919475DEED4696B5D13018151D1AF88B2BD3BCFF048B45031C1F36D1858\",\n \"representative\": \"xrb_1hza3f7wiiqa7ig3jczyxj5yo86yegcmqk3criaz838j91sxcckpfhbhhra1\",\n \"account\": \"xrb_3kdbxitaj7f6mrir6miiwtw4muhcc58e6tn5st6rfaxsdnb7gr4roudwn951\",\n \"work\": \"4ec76c9bda2325ed\",\n \"signature\": \"5974324F8CC42DA56F62FC212A17886BDCB18DE363D04DA84EEDC99CB4A33919D14A2CF9DE9D534FAA6D0B91D01F0622205D898293525E692586C84F2DCF9208\"\n}\n", 31 | "hash": "F47B23107E5F34B2CE06F562B5C435DF72A533251CB414C51B2B62A8F63A00E4" 32 | } 33 | }, 34 | { 35 | "args": { 36 | "account": "xrb_3kdbxitaj7f6mrir6miiwtw4muhcc58e6tn5st6rfaxsdnb7gr4roudwn951", 37 | "previous": "F47B23107E5F34B2CE06F562B5C435DF72A533251CB414C51B2B62A8F63A00E4", 38 | "source": "19D3D919475DEED4696B5D13018151D1AF88B2BD3BCFF048B45031C1F36D1858", 39 | "type": "receive", 40 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 41 | }, 42 | "expected": { 43 | "block": { 44 | "previous": "F47B23107E5F34B2CE06F562B5C435DF72A533251CB414C51B2B62A8F63A00E4", 45 | "signature": "A13FD22527771667D5DFF33D69787D734836A3561D8A490C1F4917A05D77EA09860461D5FBFC99246A4EAB5627F119AD477598E22EE021C4711FACF4F3C80D0E", 46 | "source": "19D3D919475DEED4696B5D13018151D1AF88B2BD3BCFF048B45031C1F36D1858", 47 | "type": "receive", 48 | "work": "6acb5dd43a38d76a" 49 | }, 50 | "hash": "314BA8D9057678C1F53371C2DB3026C1FAC01EC8E7802FD9A2E8130FC523429E" 51 | }, 52 | "request": { 53 | "account": "xrb_3kdbxitaj7f6mrir6miiwtw4muhcc58e6tn5st6rfaxsdnb7gr4roudwn951", 54 | "action": "block_create", 55 | "previous": "F47B23107E5F34B2CE06F562B5C435DF72A533251CB414C51B2B62A8F63A00E4", 56 | "source": "19D3D919475DEED4696B5D13018151D1AF88B2BD3BCFF048B45031C1F36D1858", 57 | "type": "receive", 58 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 59 | }, 60 | "response": { 61 | "block": "{\n \"type\": \"receive\",\n \"previous\": \"F47B23107E5F34B2CE06F562B5C435DF72A533251CB414C51B2B62A8F63A00E4\",\n \"source\": \"19D3D919475DEED4696B5D13018151D1AF88B2BD3BCFF048B45031C1F36D1858\",\n \"work\": \"6acb5dd43a38d76a\",\n \"signature\": \"A13FD22527771667D5DFF33D69787D734836A3561D8A490C1F4917A05D77EA09860461D5FBFC99246A4EAB5627F119AD477598E22EE021C4711FACF4F3C80D0E\"\n}\n", 62 | "hash": "314BA8D9057678C1F53371C2DB3026C1FAC01EC8E7802FD9A2E8130FC523429E" 63 | } 64 | }, 65 | { 66 | "args": { 67 | "account": "xrb_3kdbxitaj7f6mrir6miiwtw4muhcc58e6tn5st6rfaxsdnb7gr4roudwn951", 68 | "amount": "10000000000000000000000000000000", 69 | "balance": "20000000000000000000000000000000", 70 | "destination": "xrb_18gmu6engqhgtjnppqam181o5nfhj4sdtgyhy36dan3jr9spt84rzwmktafc", 71 | "previous": "314BA8D9057678C1F53371C2DB3026C1FAC01EC8E7802FD9A2E8130FC523429E", 72 | "type": "send", 73 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 74 | "work": "478563b2d9facfd4" 75 | }, 76 | "expected": { 77 | "block": { 78 | "balance": "0000007E37BE2022C0914B2680000000", 79 | "destination": "xrb_18gmu6engqhgtjnppqam181o5nfhj4sdtgyhy36dan3jr9spt84rzwmktafc", 80 | "previous": "314BA8D9057678C1F53371C2DB3026C1FAC01EC8E7802FD9A2E8130FC523429E", 81 | "signature": "F19CA177EFA8692C8CBF7478CE3213F56E4A85DF760DA7A9E69141849831F8FD79BA9ED89CEC807B690FB4AA42D5008F9DBA7115E63C935401F1F0EFA547BC00", 82 | "type": "send", 83 | "work": "478563b2d9facfd4" 84 | }, 85 | "hash": "F958305C0FF0551421D4ABEDCCF302079D020A0A3833E33F185E2B0415D4567A" 86 | }, 87 | "request": { 88 | "account": "xrb_3kdbxitaj7f6mrir6miiwtw4muhcc58e6tn5st6rfaxsdnb7gr4roudwn951", 89 | "action": "block_create", 90 | "amount": "10000000000000000000000000000000", 91 | "balance": "20000000000000000000000000000000", 92 | "destination": "xrb_18gmu6engqhgtjnppqam181o5nfhj4sdtgyhy36dan3jr9spt84rzwmktafc", 93 | "previous": "314BA8D9057678C1F53371C2DB3026C1FAC01EC8E7802FD9A2E8130FC523429E", 94 | "type": "send", 95 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 96 | "work": "478563b2d9facfd4" 97 | }, 98 | "response": { 99 | "block": "{\n \"type\": \"send\",\n \"previous\": \"314BA8D9057678C1F53371C2DB3026C1FAC01EC8E7802FD9A2E8130FC523429E\",\n \"destination\": \"xrb_18gmu6engqhgtjnppqam181o5nfhj4sdtgyhy36dan3jr9spt84rzwmktafc\",\n \"balance\": \"0000007E37BE2022C0914B2680000000\",\n \"work\": \"478563b2d9facfd4\",\n \"signature\": \"F19CA177EFA8692C8CBF7478CE3213F56E4A85DF760DA7A9E69141849831F8FD79BA9ED89CEC807B690FB4AA42D5008F9DBA7115E63C935401F1F0EFA547BC00\"\n}\n", 100 | "hash": "F958305C0FF0551421D4ABEDCCF302079D020A0A3833E33F185E2B0415D4567A" 101 | } 102 | }, 103 | { 104 | "args": { 105 | "account": "xrb_3kdbxitaj7f6mrir6miiwtw4muhcc58e6tn5st6rfaxsdnb7gr4roudwn951", 106 | "previous": "F958305C0FF0551421D4ABEDCCF302079D020A0A3833E33F185E2B0415D4567A", 107 | "representative": "xrb_18gmu6engqhgtjnppqam181o5nfhj4sdtgyhy36dan3jr9spt84rzwmktafc", 108 | "type": "change", 109 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 110 | }, 111 | "expected": { 112 | "block": { 113 | "previous": "F958305C0FF0551421D4ABEDCCF302079D020A0A3833E33F185E2B0415D4567A", 114 | "representative": "xrb_18gmu6engqhgtjnppqam181o5nfhj4sdtgyhy36dan3jr9spt84rzwmktafc", 115 | "signature": "98B4D56881D9A88B170A6B2976AE21900C26A27F0E2C338D93FDED56183B73D19AA5BEB48E43FCBB8FF8293FDD368CEF50600FECEFD490A0855ED702ED209E04", 116 | "type": "change", 117 | "work": "55e5b7a83edc3f4f" 118 | }, 119 | "hash": "654FA425CEBFC9E7726089E4EDE7A105462D93DBC915FFB70B50909920A7D286" 120 | }, 121 | "request": { 122 | "account": "xrb_3kdbxitaj7f6mrir6miiwtw4muhcc58e6tn5st6rfaxsdnb7gr4roudwn951", 123 | "action": "block_create", 124 | "previous": "F958305C0FF0551421D4ABEDCCF302079D020A0A3833E33F185E2B0415D4567A", 125 | "representative": "xrb_18gmu6engqhgtjnppqam181o5nfhj4sdtgyhy36dan3jr9spt84rzwmktafc", 126 | "type": "change", 127 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 128 | }, 129 | "response": { 130 | "block": "{\n \"type\": \"change\",\n \"previous\": \"F958305C0FF0551421D4ABEDCCF302079D020A0A3833E33F185E2B0415D4567A\",\n \"representative\": \"xrb_18gmu6engqhgtjnppqam181o5nfhj4sdtgyhy36dan3jr9spt84rzwmktafc\",\n \"work\": \"55e5b7a83edc3f4f\",\n \"signature\": \"98B4D56881D9A88B170A6B2976AE21900C26A27F0E2C338D93FDED56183B73D19AA5BEB48E43FCBB8FF8293FDD368CEF50600FECEFD490A0855ED702ED209E04\"\n}\n", 131 | "hash": "654FA425CEBFC9E7726089E4EDE7A105462D93DBC915FFB70B50909920A7D286" 132 | } 133 | } 134 | ] 135 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/blocks.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "hashes": [ 5 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | ] 7 | }, 8 | "expected": { 9 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": { 10 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 11 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 12 | "signature": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 13 | "source": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 14 | "type": "open", 15 | "work": "0000000000000000" 16 | } 17 | }, 18 | "request": { 19 | "action": "blocks", 20 | "hashes": [ 21 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 22 | ] 23 | }, 24 | "response": { 25 | "blocks": { 26 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": "{\n \"account\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"work\": \"0000000000000000\", \n \"source\": \"FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4\", \n \"representative\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"signature\": \"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \n \"type\": \"open\"\n}" 27 | } 28 | } 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/blocks_info.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "hashes": [ 5 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | ] 7 | }, 8 | "expected": { 9 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": { 10 | "amount": 1000000000000000000000000000000, 11 | "block_account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 12 | "contents": { 13 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 14 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 15 | "signature": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 16 | "source": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 17 | "type": "open", 18 | "work": "0000000000000000" 19 | } 20 | } 21 | }, 22 | "request": { 23 | "action": "blocks_info", 24 | "hashes": [ 25 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 26 | ] 27 | }, 28 | "response": { 29 | "blocks": { 30 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": { 31 | "amount": "1000000000000000000000000000000", 32 | "block_account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 33 | "contents": "{\n \"account\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"work\": \"0000000000000000\", \n \"source\": \"FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4\", \n \"representative\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"signature\": \"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \n \"type\": \"open\"\n}" 34 | } 35 | } 36 | } 37 | }, 38 | { 39 | "args": { 40 | "hashes": [ 41 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 42 | ], 43 | "pending": true, 44 | "source": true 45 | }, 46 | "expected": { 47 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": { 48 | "amount": 1000000000000000000000000000000, 49 | "block_account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 50 | "contents": { 51 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 52 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 53 | "signature": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 54 | "source": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 55 | "type": "open", 56 | "work": "0000000000000000" 57 | }, 58 | "pending": 0, 59 | "source_account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 60 | } 61 | }, 62 | "request": { 63 | "action": "blocks_info", 64 | "hashes": [ 65 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 66 | ], 67 | "pending": "true", 68 | "source": "true" 69 | }, 70 | "response": { 71 | "blocks": { 72 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": { 73 | "amount": "1000000000000000000000000000000", 74 | "block_account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 75 | "contents": "{\n \"account\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"work\": \"0000000000000000\", \n \"source\": \"FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4\", \n \"representative\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"signature\": \"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \n \"type\": \"open\"\n}", 76 | "pending": "0", 77 | "source_account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 78 | } 79 | } 80 | } 81 | } 82 | ] 83 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/bootstrap.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "address": "::ffff:138.201.94.249", 5 | "port": "7075" 6 | }, 7 | "expected": true, 8 | "request": { 9 | "action": "bootstrap", 10 | "address": "::ffff:138.201.94.249", 11 | "port": "7075" 12 | }, 13 | "response": { 14 | "success": "" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/bootstrap_any.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": true, 4 | "request": { 5 | "action": "bootstrap_any" 6 | }, 7 | "response": { 8 | "success": "" 9 | } 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/chain.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "block": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 5 | "count": 1 6 | }, 7 | "expected": [ 8 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 9 | ], 10 | "request": { 11 | "action": "chain", 12 | "block": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 13 | "count": "1" 14 | }, 15 | "response": { 16 | "blocks": [ 17 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 18 | ] 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/delegators.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_1111111111111111111111111111111111111111111111111117353trpda" 5 | }, 6 | "expected": { 7 | "xrb_13bqhi1cdqq8yb9szneoc38qk899d58i5rcrgdk5mkdm86hekpoez3zxw5sd": 500000000000000000000000000000000000, 8 | "xrb_17k6ug685154an8gri9whhe5kb5z1mf5w6y39gokc1657sh95fegm8ht1zpn": 961647970820730000000000000000000000 9 | }, 10 | "request": { 11 | "account": "xrb_1111111111111111111111111111111111111111111111111117353trpda", 12 | "action": "delegators" 13 | }, 14 | "response": { 15 | "delegators": { 16 | "xrb_13bqhi1cdqq8yb9szneoc38qk899d58i5rcrgdk5mkdm86hekpoez3zxw5sd": "500000000000000000000000000000000000", 17 | "xrb_17k6ug685154an8gri9whhe5kb5z1mf5w6y39gokc1657sh95fegm8ht1zpn": "961647970820730000000000000000000000" 18 | } 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/delegators_count.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_1111111111111111111111111111111111111111111111111117353trpda" 5 | }, 6 | "expected": 2, 7 | "request": { 8 | "account": "xrb_1111111111111111111111111111111111111111111111111117353trpda", 9 | "action": "delegators_count" 10 | }, 11 | "response": { 12 | "count": "2" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/deterministic_key.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "index": 0, 5 | "seed": "0000000000000000000000000000000000000000000000000000000000000000" 6 | }, 7 | "expected": { 8 | "account": "xrb_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7", 9 | "private": "9F0E444C69F77A49BD0BE89DB92C38FE713E0963165CCA12FAF5712D7657120F", 10 | "public": "C008B814A7D269A1FA3C6528B19201A24D797912DB9996FF02A1FF356E45552B" 11 | }, 12 | "request": { 13 | "action": "deterministic_key", 14 | "index": "0", 15 | "seed": "0000000000000000000000000000000000000000000000000000000000000000" 16 | }, 17 | "response": { 18 | "account": "xrb_3i1aq1cchnmbn9x5rsbap8b15akfh7wj7pwskuzi7ahz8oq6cobd99d4r3b7", 19 | "private": "9F0E444C69F77A49BD0BE89DB92C38FE713E0963165CCA12FAF5712D7657120F", 20 | "public": "C008B814A7D269A1FA3C6528B19201A24D797912DB9996FF02A1FF356E45552B" 21 | } 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/frontier_count.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": 1000, 4 | "request": { 5 | "action": "frontier_count" 6 | }, 7 | "response": { 8 | "count": "1000" 9 | } 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/frontiers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_1111111111111111111111111111111111111111111111111111hifc8npp", 5 | "count": 1 6 | }, 7 | "expected": { 8 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 9 | }, 10 | "request": { 11 | "account": "xrb_1111111111111111111111111111111111111111111111111111hifc8npp", 12 | "action": "frontiers", 13 | "count": "1" 14 | }, 15 | "response": { 16 | "frontiers": { 17 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 18 | } 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/history.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "count": 1, 5 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | }, 7 | "expected": [ 8 | { 9 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 10 | "amount": 100000000000000000000000000000000, 11 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 12 | "type": "receive" 13 | } 14 | ], 15 | "request": { 16 | "action": "history", 17 | "count": "1", 18 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 19 | }, 20 | "response": { 21 | "history": [ 22 | { 23 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 24 | "amount": "100000000000000000000000000000000", 25 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 26 | "type": "receive" 27 | } 28 | ] 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/keepalive.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "address": "::ffff:192.168.1.1", 5 | "port": "1024" 6 | }, 7 | "expected": true, 8 | "request": { 9 | "action": "keepalive", 10 | "address": "::ffff:192.168.1.1", 11 | "port": "1024" 12 | }, 13 | "response": {} 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/key_create.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": { 4 | "account": "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", 5 | "private": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", 6 | "public": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039" 7 | }, 8 | "request": { 9 | "action": "key_create" 10 | }, 11 | "response": { 12 | "account": "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", 13 | "private": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", 14 | "public": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/key_expand.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "key": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3" 5 | }, 6 | "expected": { 7 | "account": "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", 8 | "private": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", 9 | "public": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039" 10 | }, 11 | "request": { 12 | "action": "key_expand", 13 | "key": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3" 14 | }, 15 | "response": { 16 | "account": "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx", 17 | "private": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3", 18 | "public": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039" 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/krai_from_raw.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "amount": 1000000000000000000000000000 5 | }, 6 | "expected": 1, 7 | "request": { 8 | "action": "krai_from_raw", 9 | "amount": "1000000000000000000000000000" 10 | }, 11 | "response": { 12 | "amount": "1" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/krai_to_raw.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "amount": 1 5 | }, 6 | "expected": 1000000000000000000000000000, 7 | "request": { 8 | "action": "krai_to_raw", 9 | "amount": "1" 10 | }, 11 | "response": { 12 | "amount": "1000000000000000000000000000" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/ledger.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_1111111111111111111111111111111111111111111111111111hifc8npp", 5 | "count": 1 6 | }, 7 | "expected": { 8 | "xrb_11119gbh8hb4hj1duf7fdtfyf5s75okzxdgupgpgm1bj78ex3kgy7frt3s9n": { 9 | "balance": 0, 10 | "block_count": 2, 11 | "frontier": "E71AF3E9DD86BBD8B4620EFA63E065B34D358CFC091ACB4E103B965F95783321", 12 | "modified_timestamp": 1511476234, 13 | "open_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", 14 | "representative_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F" 15 | } 16 | }, 17 | "request": { 18 | "account": "xrb_1111111111111111111111111111111111111111111111111111hifc8npp", 19 | "action": "ledger", 20 | "count": "1" 21 | }, 22 | "response": { 23 | "accounts": { 24 | "xrb_11119gbh8hb4hj1duf7fdtfyf5s75okzxdgupgpgm1bj78ex3kgy7frt3s9n": { 25 | "balance": "0", 26 | "block_count": "2", 27 | "frontier": "E71AF3E9DD86BBD8B4620EFA63E065B34D358CFC091ACB4E103B965F95783321", 28 | "modified_timestamp": "1511476234", 29 | "open_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", 30 | "representative_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F" 31 | } 32 | } 33 | } 34 | }, 35 | { 36 | "args": { 37 | "account": "xrb_1111111111111111111111111111111111111111111111111111hifc8npp", 38 | "count": 1, 39 | "pending": true, 40 | "representative": true, 41 | "sorting": true, 42 | "weight": true 43 | }, 44 | "expected": { 45 | "xrb_11119gbh8hb4hj1duf7fdtfyf5s75okzxdgupgpgm1bj78ex3kgy7frt3s9n": { 46 | "balance": 0, 47 | "block_count": 2, 48 | "frontier": "E71AF3E9DD86BBD8B4620EFA63E065B34D358CFC091ACB4E103B965F95783321", 49 | "modified_timestamp": 1511476234, 50 | "open_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", 51 | "pending": 0, 52 | "representative": "xrb_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs", 53 | "representative_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", 54 | "weight": 0 55 | } 56 | }, 57 | "request": { 58 | "account": "xrb_1111111111111111111111111111111111111111111111111111hifc8npp", 59 | "action": "ledger", 60 | "count": "1", 61 | "pending": "true", 62 | "representative": "true", 63 | "sorting": "true", 64 | "weight": "true" 65 | }, 66 | "response": { 67 | "accounts": { 68 | "xrb_11119gbh8hb4hj1duf7fdtfyf5s75okzxdgupgpgm1bj78ex3kgy7frt3s9n": { 69 | "balance": "0", 70 | "block_count": "2", 71 | "frontier": "E71AF3E9DD86BBD8B4620EFA63E065B34D358CFC091ACB4E103B965F95783321", 72 | "modified_timestamp": "1511476234", 73 | "open_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", 74 | "pending": "0", 75 | "representative": "xrb_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs", 76 | "representative_block": "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F", 77 | "weight": "0" 78 | } 79 | } 80 | } 81 | } 82 | ] 83 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/mrai_from_raw.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "amount": 1000000000000000000000000000000 5 | }, 6 | "expected": 1, 7 | "request": { 8 | "action": "mrai_from_raw", 9 | "amount": "1000000000000000000000000000000" 10 | }, 11 | "response": { 12 | "amount": "1" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/mrai_to_raw.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "amount": 1 5 | }, 6 | "expected": 1000000000000000000000000000000, 7 | "request": { 8 | "action": "mrai_to_raw", 9 | "amount": "1" 10 | }, 11 | "response": { 12 | "amount": "1000000000000000000000000000000" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/password_change.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "password": "test", 5 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | }, 7 | "expected": true, 8 | "request": { 9 | "action": "password_change", 10 | "password": "test", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "changed": "1" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/password_enter.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "password": "test", 5 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | }, 7 | "expected": true, 8 | "request": { 9 | "action": "password_enter", 10 | "password": "test", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "valid": "1" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/password_valid.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": true, 7 | "request": { 8 | "action": "password_valid", 9 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 10 | }, 11 | "response": { 12 | "valid": "1" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/payment_begin.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 7 | "request": { 8 | "action": "payment_begin", 9 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 10 | }, 11 | "response": { 12 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/payment_end.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 5 | "wallet": "FFFD1BAEC8EC20814BBB9059B393051AAA8380F9B5A2E6B2489A277D81789EEE" 6 | }, 7 | "expected": true, 8 | "request": { 9 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 10 | "action": "payment_end", 11 | "wallet": "FFFD1BAEC8EC20814BBB9059B393051AAA8380F9B5A2E6B2489A277D81789EEE" 12 | }, 13 | "response": {} 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/payment_init.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": true, 7 | "request": { 8 | "action": "payment_init", 9 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 10 | }, 11 | "response": { 12 | "status": "Ready" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/payment_wait.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 5 | "amount": 1, 6 | "timeout": 1000 7 | }, 8 | "expected": true, 9 | "request": { 10 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 11 | "action": "payment_wait", 12 | "amount": "1", 13 | "timeout": "1000" 14 | }, 15 | "response": { 16 | "status": "success" 17 | } 18 | } 19 | ] 20 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/peers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": { 4 | "[::ffff:172.17.0.1]:32841": 3 5 | }, 6 | "request": { 7 | "action": "peers" 8 | }, 9 | "response": { 10 | "peers": { 11 | "[::ffff:172.17.0.1]:32841": "3" 12 | } 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/pending.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_1111111111111111111111111111111111111111111111111117353trpda" 5 | }, 6 | "expected": [ 7 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 8 | ], 9 | "request": { 10 | "account": "xrb_1111111111111111111111111111111111111111111111111117353trpda", 11 | "action": "pending" 12 | }, 13 | "response": { 14 | "blocks": [ 15 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 16 | ] 17 | } 18 | }, 19 | { 20 | "args": { 21 | "account": "xrb_1111111111111111111111111111111111111111111111111117353trpda", 22 | "count": 1, 23 | "threshold": 1000000000000000000000000 24 | }, 25 | "expected": { 26 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": 6000000000000000000000000000000 27 | }, 28 | "request": { 29 | "account": "xrb_1111111111111111111111111111111111111111111111111117353trpda", 30 | "action": "pending", 31 | "count": "1", 32 | "threshold": "1000000000000000000000000" 33 | }, 34 | "response": { 35 | "blocks": { 36 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": "6000000000000000000000000000000" 37 | } 38 | } 39 | }, 40 | { 41 | "args": { 42 | "account": "xrb_1111111111111111111111111111111111111111111111111117353trpda", 43 | "count": 1, 44 | "source": true 45 | }, 46 | "expected": { 47 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": { 48 | "amount": 6000000000000000000000000000000, 49 | "source": "xrb_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr" 50 | } 51 | }, 52 | "request": { 53 | "account": "xrb_1111111111111111111111111111111111111111111111111117353trpda", 54 | "action": "pending", 55 | "count": "1", 56 | "source": "true" 57 | }, 58 | "response": { 59 | "blocks": { 60 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": { 61 | "amount": "6000000000000000000000000000000", 62 | "source": "xrb_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr" 63 | } 64 | } 65 | } 66 | } 67 | ] 68 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/pending_exists.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": true, 7 | "request": { 8 | "action": "pending_exists", 9 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 10 | }, 11 | "response": { 12 | "exists": "1" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/process.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "block": { 5 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 6 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 7 | "signature": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 8 | "source": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 9 | "type": "open", 10 | "work": "0000000000000000" 11 | } 12 | }, 13 | "expected": "42A723D2B60462BF7C9A003FE9A70057D3A6355CA5F1D0A57581000000000000", 14 | "request": { 15 | "action": "process", 16 | "block": "{\"account\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \"representative\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \"signature\": \"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \"source\": \"FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4\", \"type\": \"open\", \"work\": \"0000000000000000\"}" 17 | }, 18 | "response": { 19 | "hash": "42A723D2B60462BF7C9A003FE9A70057D3A6355CA5F1D0A57581000000000000" 20 | } 21 | }, 22 | { 23 | "args": { 24 | "block": "{\"account\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \"work\": \"0000000000000000\", \"source\": \"FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4\", \"representative\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \"signature\": \"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \"type\": \"open\"}" 25 | }, 26 | "expected": "42A723D2B60462BF7C9A003FE9A70057D3A6355CA5F1D0A57581000000000000", 27 | "request": { 28 | "action": "process", 29 | "block": "{\"account\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \"work\": \"0000000000000000\", \"source\": \"FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4\", \"representative\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \"signature\": \"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \"type\": \"open\"}" 30 | }, 31 | "response": { 32 | "hash": "42A723D2B60462BF7C9A003FE9A70057D3A6355CA5F1D0A57581000000000000" 33 | } 34 | } 35 | ] 36 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/rai_from_raw.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "amount": 1000000000000000000000000 5 | }, 6 | "expected": 1, 7 | "request": { 8 | "action": "rai_from_raw", 9 | "amount": "1000000000000000000000000" 10 | }, 11 | "response": { 12 | "amount": "1" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/rai_to_raw.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "amount": 1 5 | }, 6 | "expected": 1000000000000000000000000, 7 | "request": { 8 | "action": "rai_to_raw", 9 | "amount": "1" 10 | }, 11 | "response": { 12 | "amount": "1000000000000000000000000" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/receive.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 5 | "block": "53EAA25CE28FA0E6D55EA9704B32604A736966255948594D55CBB05267CECD48", 6 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 7 | }, 8 | "expected": "EE5286AB32F580AB65FD84A69E107C69FBEB571DEC4D99297E19E3FA5529547B", 9 | "request": { 10 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 11 | "action": "receive", 12 | "block": "53EAA25CE28FA0E6D55EA9704B32604A736966255948594D55CBB05267CECD48", 13 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 14 | }, 15 | "response": { 16 | "block": "EE5286AB32F580AB65FD84A69E107C69FBEB571DEC4D99297E19E3FA5529547B" 17 | } 18 | }, 19 | { 20 | "args": { 21 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 22 | "block": "53EAA25CE28FA0E6D55EA9704B32604A736966255948594D55CBB05267CECD48", 23 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 24 | "work": "2bf29ef00786a6bc" 25 | }, 26 | "expected": "EE5286AB32F580AB65FD84A69E107C69FBEB571DEC4D99297E19E3FA5529547B", 27 | "request": { 28 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 29 | "action": "receive", 30 | "block": "53EAA25CE28FA0E6D55EA9704B32604A736966255948594D55CBB05267CECD48", 31 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 32 | "work": "2bf29ef00786a6bc" 33 | }, 34 | "response": { 35 | "block": "EE5286AB32F580AB65FD84A69E107C69FBEB571DEC4D99297E19E3FA5529547B" 36 | } 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/receive_minimum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": 1000000000000000000000000, 4 | "request": { 5 | "action": "receive_minimum" 6 | }, 7 | "response": { 8 | "amount": "1000000000000000000000000" 9 | } 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/receive_minimum_set.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "amount": 1000000000000000000000000000000 5 | }, 6 | "expected": true, 7 | "request": { 8 | "action": "receive_minimum_set", 9 | "amount": "1000000000000000000000000000000" 10 | }, 11 | "response": { 12 | "success": "" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/representatives.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": { 4 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": 3822372327060170000000000000000000000, 5 | "xrb_1111111111111111111111111111111111111111111111111awsq94gtecn": 30999999999999999999999999000000, 6 | "xrb_114nk4rwjctu6n6tr6g6ps61g1w3hdpjxfas4xj1tq6i8jyomc5d858xr1xi": 0 7 | }, 8 | "request": { 9 | "action": "representatives" 10 | }, 11 | "response": { 12 | "representatives": { 13 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": "3822372327060170000000000000000000000", 14 | "xrb_1111111111111111111111111111111111111111111111111awsq94gtecn": "30999999999999999999999999000000", 15 | "xrb_114nk4rwjctu6n6tr6g6ps61g1w3hdpjxfas4xj1tq6i8jyomc5d858xr1xi": "0" 16 | } 17 | } 18 | }, 19 | { 20 | "args": { 21 | "count": 1, 22 | "sorting": true 23 | }, 24 | "expected": { 25 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": 3822372327060170000000000000000000000, 26 | "xrb_1111111111111111111111111111111111111111111111111awsq94gtecn": 30999999999999999999999999000000, 27 | "xrb_114nk4rwjctu6n6tr6g6ps61g1w3hdpjxfas4xj1tq6i8jyomc5d858xr1xi": 0 28 | }, 29 | "request": { 30 | "action": "representatives", 31 | "count": "1", 32 | "sorting": "true" 33 | }, 34 | "response": { 35 | "representatives": { 36 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": "3822372327060170000000000000000000000", 37 | "xrb_1111111111111111111111111111111111111111111111111awsq94gtecn": "30999999999999999999999999000000", 38 | "xrb_114nk4rwjctu6n6tr6g6ps61g1w3hdpjxfas4xj1tq6i8jyomc5d858xr1xi": "0" 39 | } 40 | } 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/republish.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "hash": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948" 5 | }, 6 | "expected": [ 7 | "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 8 | "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293" 9 | ], 10 | "request": { 11 | "action": "republish", 12 | "hash": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948" 13 | }, 14 | "response": { 15 | "blocks": [ 16 | "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 17 | "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293" 18 | ] 19 | } 20 | }, 21 | { 22 | "args": { 23 | "count": 1, 24 | "hash": "90D0C16AC92DD35814E84BFBCC739A039615D0A42A76EF44ADAEF1D99E9F8A35", 25 | "sources": 2 26 | }, 27 | "expected": [ 28 | "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 29 | "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293", 30 | "90D0C16AC92DD35814E84BFBCC739A039615D0A42A76EF44ADAEF1D99E9F8A35" 31 | ], 32 | "request": { 33 | "action": "republish", 34 | "count": "1", 35 | "hash": "90D0C16AC92DD35814E84BFBCC739A039615D0A42A76EF44ADAEF1D99E9F8A35", 36 | "sources": "2" 37 | }, 38 | "response": { 39 | "blocks": [ 40 | "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 41 | "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293", 42 | "90D0C16AC92DD35814E84BFBCC739A039615D0A42A76EF44ADAEF1D99E9F8A35" 43 | ] 44 | } 45 | }, 46 | { 47 | "args": { 48 | "count": 1, 49 | "destinations": 2, 50 | "hash": "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293" 51 | }, 52 | "expected": [ 53 | "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293", 54 | "90D0C16AC92DD35814E84BFBCC739A039615D0A42A76EF44ADAEF1D99E9F8A35", 55 | "18563C814A54535B7C12BF76A0E23291BA3769536634AB90AD0305776A533E8E" 56 | ], 57 | "request": { 58 | "action": "republish", 59 | "count": "1", 60 | "destinations": "2", 61 | "hash": "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293" 62 | }, 63 | "response": { 64 | "blocks": [ 65 | "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293", 66 | "90D0C16AC92DD35814E84BFBCC739A039615D0A42A76EF44ADAEF1D99E9F8A35", 67 | "18563C814A54535B7C12BF76A0E23291BA3769536634AB90AD0305776A533E8E" 68 | ] 69 | } 70 | } 71 | ] 72 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/search_pending.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": true, 7 | "request": { 8 | "action": "search_pending", 9 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 10 | }, 11 | "response": { 12 | "started": "1" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/search_pending_all.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": true, 4 | "request": { 5 | "action": "search_pending_all" 6 | }, 7 | "response": { 8 | "success": "" 9 | } 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/send.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "amount": 1000000, 5 | "destination": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 6 | "source": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 7 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 8 | }, 9 | "expected": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 10 | "request": { 11 | "action": "send", 12 | "amount": "1000000", 13 | "destination": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 14 | "source": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 15 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 16 | }, 17 | "response": { 18 | "block": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 19 | } 20 | }, 21 | { 22 | "args": { 23 | "amount": 1000000, 24 | "destination": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 25 | "source": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 26 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 27 | "work": "2bf29ef00786a6bc" 28 | }, 29 | "expected": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 30 | "request": { 31 | "action": "send", 32 | "amount": "1000000", 33 | "destination": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 34 | "source": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 35 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 36 | "work": "2bf29ef00786a6bc" 37 | }, 38 | "response": { 39 | "block": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 40 | } 41 | }, 42 | { 43 | "args": { 44 | "amount": 1000000, 45 | "destination": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 46 | "source": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 47 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 48 | "id": "tx-13258" 49 | }, 50 | "expected": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 51 | "request": { 52 | "action": "send", 53 | "amount": "1000000", 54 | "destination": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 55 | "source": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 56 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 57 | "id": "tx-13258" 58 | }, 59 | "response": { 60 | "block": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 61 | } 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/stop.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": true, 4 | "request": { 5 | "action": "stop" 6 | }, 7 | "response": { 8 | "success": "" 9 | } 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/successors.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 5 | "count": "1" 6 | }, 7 | "expected": [ 8 | "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293" 9 | ], 10 | "request": { 11 | "action": "successors", 12 | "block": "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 13 | "count": "1" 14 | }, 15 | "response": { 16 | "blocks": [ 17 | "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293" 18 | ] 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/unchecked.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "count": 1 5 | }, 6 | "expected": { 7 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": { 8 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 9 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 10 | "signature": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 11 | "source": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 12 | "type": "open", 13 | "work": "0000000000000000" 14 | } 15 | }, 16 | "request": { 17 | "action": "unchecked", 18 | "count": "1" 19 | }, 20 | "response": { 21 | "blocks": { 22 | "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F": "{\n \"account\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"work\": \"0000000000000000\", \n \"source\": \"FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4\", \n \"representative\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"signature\": \"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \n \"type\": \"open\"\n}" 23 | } 24 | } 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/unchecked_clear.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": true, 4 | "request": { 5 | "action": "unchecked_clear" 6 | }, 7 | "response": { 8 | "success": "" 9 | } 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/unchecked_get.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": { 7 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 8 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 9 | "signature": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 10 | "source": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 11 | "type": "open", 12 | "work": "0000000000000000" 13 | }, 14 | "request": { 15 | "action": "unchecked_get", 16 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 17 | }, 18 | "response": { 19 | "contents": "{\n \"account\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"work\": \"0000000000000000\", \n \"source\": \"FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4\", \n \"representative\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"signature\": \"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \n \"type\": \"open\"\n}" 20 | } 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/unchecked_keys.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "count": 1, 5 | "key": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4" 6 | }, 7 | "expected": [ 8 | { 9 | "contents": { 10 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 11 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 12 | "signature": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 13 | "source": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 14 | "type": "open", 15 | "work": "0000000000000000" 16 | }, 17 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 18 | "key": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4" 19 | } 20 | ], 21 | "request": { 22 | "action": "unchecked_keys", 23 | "count": "1", 24 | "key": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4" 25 | }, 26 | "response": { 27 | "unchecked": [ 28 | { 29 | "contents": "{\n \"account\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"work\": \"0000000000000000\", \n \"source\": \"FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4\", \n \"representative\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"signature\": \"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \n \"type\": \"open\"\n}", 30 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 31 | "key": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4" 32 | } 33 | ] 34 | } 35 | }, 36 | { 37 | "args": { 38 | "key": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4" 39 | }, 40 | "expected": [ 41 | { 42 | "contents": { 43 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 44 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 45 | "signature": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 46 | "source": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4", 47 | "type": "open", 48 | "work": "0000000000000000" 49 | }, 50 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 51 | "key": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4" 52 | } 53 | ], 54 | "request": { 55 | "action": "unchecked_keys", 56 | "key": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4" 57 | }, 58 | "response": { 59 | "unchecked": [ 60 | { 61 | "contents": "{\n \"account\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"work\": \"0000000000000000\", \n \"source\": \"FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4\", \n \"representative\": \"xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000\", \n \"signature\": \"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \n \"type\": \"open\"\n}", 62 | "hash": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 63 | "key": "FA5B51D063BADDF345EFD7EF0D3C5FB115C85B1EF4CDE89D8B7DF3EAF60A04A4" 64 | } 65 | ] 66 | } 67 | } 68 | ] 69 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/validate_account_number.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 5 | }, 6 | "expected": true, 7 | "request": { 8 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 9 | "action": "validate_account_number" 10 | }, 11 | "response": { 12 | "valid": "1" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/version.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": { 4 | "node_vendor": "RaiBlocks 9.0", 5 | "rpc_version": 1, 6 | "store_version": 10 7 | }, 8 | "request": { 9 | "action": "version" 10 | }, 11 | "response": { 12 | "node_vendor": "RaiBlocks 9.0", 13 | "rpc_version": "1", 14 | "store_version": "10" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_add.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "key": "34F0A37AAD20F4A260F0A5B3CB3D7FB50673212263E58A380BC10474BB039CE4", 5 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | }, 7 | "expected": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 8 | "request": { 9 | "action": "wallet_add", 10 | "key": "34F0A37AAD20F4A260F0A5B3CB3D7FB50673212263E58A380BC10474BB039CE4", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 15 | } 16 | }, 17 | { 18 | "args": { 19 | "key": "34F0A37AAD20F4A260F0A5B3CB3D7FB50673212263E58A380BC10474BB039CE4", 20 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 21 | "work": false 22 | }, 23 | "expected": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 24 | "request": { 25 | "action": "wallet_add", 26 | "key": "34F0A37AAD20F4A260F0A5B3CB3D7FB50673212263E58A380BC10474BB039CE4", 27 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 28 | "work": "false" 29 | }, 30 | "response": { 31 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 32 | } 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_balance_total.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": { 7 | "balance": 10000, 8 | "pending": 10000 9 | }, 10 | "request": { 11 | "action": "wallet_balance_total", 12 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 13 | }, 14 | "response": { 15 | "balance": "10000", 16 | "pending": "10000" 17 | } 18 | } 19 | ] 20 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_balances.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": { 7 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000": { 8 | "balance": 10000, 9 | "pending": 10000 10 | } 11 | }, 12 | "request": { 13 | "action": "wallet_balances", 14 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 15 | }, 16 | "response": { 17 | "balances": { 18 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000": { 19 | "balance": "10000", 20 | "pending": "10000" 21 | } 22 | } 23 | } 24 | } 25 | ] 26 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_change_seed.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "seed": "74F2B37AAD20F4A260F0A5B3CB3D7FB51673212263E58A380BC10474BB039CEE", 5 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | }, 7 | "expected": true, 8 | "request": { 9 | "action": "wallet_change_seed", 10 | "seed": "74F2B37AAD20F4A260F0A5B3CB3D7FB51673212263E58A380BC10474BB039CEE", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "success": "" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_contains.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 5 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | }, 7 | "expected": true, 8 | "request": { 9 | "account": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 10 | "action": "wallet_contains", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "exists": "1" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_create.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 4 | "request": { 5 | "action": "wallet_create" 6 | }, 7 | "response": { 8 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 9 | } 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_destroy.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": true, 7 | "request": { 8 | "action": "wallet_destroy", 9 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 10 | }, 11 | "response": {} 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_export.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": { 7 | "0000000000000000000000000000000000000000000000000000000000000000": "0000000000000000000000000000000000000000000000000000000000000001" 8 | }, 9 | "request": { 10 | "action": "wallet_export", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "json": "{\"0000000000000000000000000000000000000000000000000000000000000000\": \"0000000000000000000000000000000000000000000000000000000000000001\"}" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_frontiers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": { 7 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 8 | }, 9 | "request": { 10 | "action": "wallet_frontiers", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "frontiers": { 15 | "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 16 | } 17 | } 18 | } 19 | ] 20 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_key_valid.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": true, 7 | "request": { 8 | "action": "wallet_key_valid", 9 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 10 | }, 11 | "response": { 12 | "valid": "1" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_lock.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": true, 7 | "request": { 8 | "action": "wallet_lock", 9 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 10 | }, 11 | "response": { 12 | "locked": "1" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_locked.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": false, 7 | "request": { 8 | "action": "wallet_locked", 9 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 10 | }, 11 | "response": { 12 | "locked": "0" 13 | } 14 | }, 15 | { 16 | "args": { 17 | "wallet": "111D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 18 | }, 19 | "expected": true, 20 | "request": { 21 | "action": "wallet_locked", 22 | "wallet": "111D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 23 | }, 24 | "response": { 25 | "locked": "1" 26 | } 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_pending.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "51BAC8380F9B5A2E6B2489A277D81789F3F000D1BAEC8EC208142C99059B3930" 5 | }, 6 | "expected": {}, 7 | "request": { 8 | "action": "wallet_pending", 9 | "wallet": "51BAC8380F9B5A2E6B2489A277D81789F3F000D1BAEC8EC208142C99059B3930" 10 | }, 11 | "response": { 12 | "blocks": "" 13 | } 14 | }, 15 | { 16 | "args": { 17 | "count": "1", 18 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 19 | }, 20 | "expected": { 21 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": [ 22 | "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D" 23 | ], 24 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": [ 25 | "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74" 26 | ], 27 | "xrb_tsa8mnijtpxm9fkcm736xtoncuohr33t6k35gi95xu6tergt6p69ck76ogmi": [] 28 | }, 29 | "request": { 30 | "action": "wallet_pending", 31 | "count": "1", 32 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 33 | }, 34 | "response": { 35 | "blocks": { 36 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": [ 37 | "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D" 38 | ], 39 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": [ 40 | "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74" 41 | ], 42 | "xrb_tsa8mnijtpxm9fkcm736xtoncuohr33t6k35gi95xu6tergt6p69ck76ogmi": "" 43 | } 44 | } 45 | }, 46 | { 47 | "args": { 48 | "count": 1, 49 | "threshold": 1000000000000000000000000, 50 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 51 | }, 52 | "expected": { 53 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": { 54 | "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D": 6000000000000000000000000000000 55 | }, 56 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { 57 | "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74": 106370018000000000000000000000000 58 | } 59 | }, 60 | "request": { 61 | "action": "wallet_pending", 62 | "count": "1", 63 | "threshold": "1000000000000000000000000", 64 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 65 | }, 66 | "response": { 67 | "blocks": { 68 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": { 69 | "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D": "6000000000000000000000000000000" 70 | }, 71 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { 72 | "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74": "106370018000000000000000000000000" 73 | } 74 | } 75 | } 76 | }, 77 | { 78 | "args": { 79 | "count": 1, 80 | "source": true, 81 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 82 | }, 83 | "expected": { 84 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": { 85 | "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D": { 86 | "amount": 6000000000000000000000000000000, 87 | "source": "xrb_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr" 88 | } 89 | }, 90 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { 91 | "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74": { 92 | "amount": 106370018000000000000000000000000, 93 | "source": "xrb_13ezf4od79h1tgj9aiu4djzcmmguendtjfuhwfukhuucboua8cpoihmh8byo" 94 | } 95 | } 96 | }, 97 | "request": { 98 | "action": "wallet_pending", 99 | "count": "1", 100 | "source": "true", 101 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 102 | }, 103 | "response": { 104 | "blocks": { 105 | "xrb_1111111111111111111111111111111111111111111111111117353trpda": { 106 | "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D": { 107 | "amount": "6000000000000000000000000000000", 108 | "source": "xrb_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr" 109 | } 110 | }, 111 | "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3": { 112 | "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74": { 113 | "amount": "106370018000000000000000000000000", 114 | "source": "xrb_13ezf4od79h1tgj9aiu4djzcmmguendtjfuhwfukhuucboua8cpoihmh8byo" 115 | } 116 | } 117 | } 118 | } 119 | } 120 | ] 121 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_representative.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 7 | "request": { 8 | "action": "wallet_representative", 9 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 10 | }, 11 | "response": { 12 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_representative_set.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 5 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | }, 7 | "expected": true, 8 | "request": { 9 | "action": "wallet_representative_set", 10 | "representative": "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "set": "1" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_republish.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "count": 2, 5 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | }, 7 | "expected": [ 8 | "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 9 | "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293", 10 | "90D0C16AC92DD35814E84BFBCC739A039615D0A42A76EF44ADAEF1D99E9F8A35" 11 | ], 12 | "request": { 13 | "action": "wallet_republish", 14 | "count": "2", 15 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 16 | }, 17 | "response": { 18 | "blocks": [ 19 | "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948", 20 | "A170D51B94E00371ACE76E35AC81DC9405D5D04D4CEBC399AEACE07AE05DD293", 21 | "90D0C16AC92DD35814E84BFBCC739A039615D0A42A76EF44ADAEF1D99E9F8A35" 22 | ] 23 | } 24 | } 25 | ] 26 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_unlock.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "password": "test", 5 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | }, 7 | "expected": true, 8 | "request": { 9 | "action": "wallet_unlock", 10 | "password": "test", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "valid": "1" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/wallet_work_get.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 5 | }, 6 | "expected": { 7 | "xrb_1111111111111111111111111111111111111111111111111111hifc8npp": "432e5cf728c90f4f" 8 | }, 9 | "request": { 10 | "action": "wallet_work_get", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "works": { 15 | "xrb_1111111111111111111111111111111111111111111111111111hifc8npp": "432e5cf728c90f4f" 16 | } 17 | } 18 | } 19 | ] 20 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/work_cancel.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "hash": "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2" 5 | }, 6 | "expected": true, 7 | "request": { 8 | "action": "work_cancel", 9 | "hash": "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2" 10 | }, 11 | "response": {} 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/work_generate.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "hash": "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2" 5 | }, 6 | "expected": "2bf29ef00786a6bc", 7 | "request": { 8 | "action": "work_generate", 9 | "hash": "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2" 10 | }, 11 | "response": { 12 | "work": "2bf29ef00786a6bc" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/work_get.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_1111111111111111111111111111111111111111111111111111hifc8npp", 5 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 6 | }, 7 | "expected": "432e5cf728c90f4f", 8 | "request": { 9 | "account": "xrb_1111111111111111111111111111111111111111111111111111hifc8npp", 10 | "action": "work_get", 11 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F" 12 | }, 13 | "response": { 14 | "work": "432e5cf728c90f4f" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/work_peer_add.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "address": "::ffff:172.17.0.1", 5 | "port": 7076 6 | }, 7 | "expected": true, 8 | "request": { 9 | "action": "work_peer_add", 10 | "address": "::ffff:172.17.0.1", 11 | "port": "7076" 12 | }, 13 | "response": { 14 | "success": "" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/work_peers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": [ 4 | "::ffff:172.17.0.1:7076" 5 | ], 6 | "request": { 7 | "action": "work_peers" 8 | }, 9 | "response": { 10 | "work_peers": [ 11 | "::ffff:172.17.0.1:7076" 12 | ] 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/work_peers_clear.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "expected": true, 4 | "request": { 5 | "action": "work_peers_clear" 6 | }, 7 | "response": { 8 | "success": "" 9 | } 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/work_set.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "account": "xrb_1111111111111111111111111111111111111111111111111111hifc8npp", 5 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 6 | "work": "0000000000000000" 7 | }, 8 | "expected": true, 9 | "request": { 10 | "account": "xrb_1111111111111111111111111111111111111111111111111111hifc8npp", 11 | "action": "work_set", 12 | "wallet": "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F", 13 | "work": "0000000000000000" 14 | }, 15 | "response": { 16 | "success": "" 17 | } 18 | } 19 | ] 20 | -------------------------------------------------------------------------------- /tests/fixtures/rpc/work_validate.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "args": { 4 | "hash": "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2", 5 | "work": "2bf29ef00786a6bc" 6 | }, 7 | "expected": true, 8 | "request": { 9 | "action": "work_validate", 10 | "hash": "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2", 11 | "work": "2bf29ef00786a6bc" 12 | }, 13 | "response": { 14 | "valid": "1" 15 | } 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/test_accounts.py: -------------------------------------------------------------------------------- 1 | from binascii import hexlify, unhexlify 2 | 3 | import pytest 4 | 5 | from nano.accounts import ( 6 | public_key_to_xrb_address, 7 | xrb_address_to_public_key, 8 | generate_account, 9 | address_checksum, # we can't remove this 10 | ) 11 | from nano.crypto import private_to_public_key 12 | 13 | ACCOUNT_TESTS = [ 14 | { 15 | 'address': ( 16 | 'xrb_3n4fgjgiisyoc1zjen5o1jq3554u' '3t8htjsr6k5yibza3p9yp3kfpgeycnxj' 17 | ), 18 | 'public_hex': ( 19 | 'D04D745D0867D5503F165075046E118C' '5B0E8CFD47382487E827E80D8FEB064D' 20 | ), 21 | }, 22 | { 23 | 'address': ( 24 | 'xrb_34147sxe87n51z174urzg8cbboda' 'hrf7gzuyqbshtkw3ueqgme883mecq9wn' 25 | ), 26 | 'public_hex': ( 27 | '88022E7AC3168307C0516F1F719494D5' '687E1A577F7EBA72FD4B81DB2EE9B0C6' 28 | ), 29 | }, 30 | ] 31 | 32 | 33 | @pytest.mark.parametrize('data', ACCOUNT_TESTS) 34 | def test_xrb_address_to_public_key(data): 35 | public_key = xrb_address_to_public_key(data['address']) 36 | assert public_key == unhexlify(data['public_hex']) 37 | 38 | 39 | @pytest.mark.parametrize( 40 | 'address,error_msg', 41 | [ 42 | ('xrb_34147sxe87n51z174urzg8cbbodahrf7gzuyqbshtkw3ueqgme883mecq9wn', ''), 43 | ( 44 | 'xrb_34147sxe87n51z174urzg8cbbodahrf7gzuyqbshtkw3ueqgme883mecq9w3', 45 | 'invalid checksum', 46 | ), 47 | ( 48 | 'xrp_34147sxe87n51z174urzg8cbbodahrf7gzuyqbshtkw3ueqgme883mecq9w3', 49 | 'does not start with xrb_', 50 | ), 51 | ( 52 | 'xrb_34147sxe87n51z174urzg8cbbodahrf7gzuyqbshtkw3ueqgme883mecq9wn3', 53 | 'must be 64 chars', 54 | ), 55 | ( 56 | 'xrb_34147sxe87n51z174urzg8cbbodahrf7gzuyqbshtkw3ueqgme883mecq9w', 57 | 'must be 64 chars', 58 | ), 59 | ], 60 | ) 61 | def test_invalid_xrb_addresses(address, error_msg): 62 | if not error_msg: # test the valid case is working 63 | assert xrb_address_to_public_key(address) == ( 64 | unhexlify( 65 | '88022E7AC3168307C0516F1F719494D5' '687E1A577F7EBA72FD4B81DB2EE9B0C6' 66 | ) 67 | ) 68 | return 69 | 70 | with pytest.raises(ValueError) as e_info: 71 | xrb_address_to_public_key(address) 72 | 73 | assert e_info.match(error_msg) 74 | 75 | 76 | @pytest.mark.parametrize('data', ACCOUNT_TESTS) 77 | def test_public_key_to_xrb_address(data): 78 | address = public_key_to_xrb_address(unhexlify(data['public_hex'])) 79 | assert address == data['address'] 80 | 81 | 82 | @pytest.mark.parametrize( 83 | 'public_key,error_msg', 84 | [ 85 | (b'00000000000000000000000000000000', ''), 86 | (b'000000000000000000000000000000000', 'must be 32 chars'), 87 | (b'0000000000000000000000000000000', 'must be 32 chars'), 88 | ], 89 | ) 90 | def test_invalid_private_keys(public_key, error_msg): 91 | if not error_msg: # test the valid case is working 92 | assert public_key_to_xrb_address(public_key) == ( 93 | 'xrb_1e3i81r51e3i81r51e3i81r51e3i' '81r51e3i81r51e3i81r51e3imxssakuq' 94 | ) 95 | return 96 | 97 | with pytest.raises(ValueError) as e_info: 98 | public_key_to_xrb_address(public_key) 99 | 100 | assert e_info.match(error_msg) 101 | 102 | 103 | def test_generate_account_from_seed(): 104 | account = generate_account(seed=unhexlify(64 * '0')) 105 | 106 | public_key = unhexlify( 107 | 'c008b814a7d269a1fa3c6528b19201a2' '4d797912db9996ff02a1ff356e45552b' 108 | ) 109 | private_key = unhexlify( 110 | '9f0e444c69f77a49bd0be89db92c38fe7' '13e0963165cca12faf5712d7657120f' 111 | ) 112 | 113 | assert account == { 114 | 'address': ( 115 | u'xrb_3i1aq1cchnmbn9x5rsbap8b15akf' 'h7wj7pwskuzi7ahz8oq6cobd99d4r3b7' 116 | ), 117 | 'public_key_bytes': public_key, 118 | 'public_key_hex': hexlify(public_key), 119 | 'private_key_bytes': private_key, 120 | 'private_key_hex': hexlify(private_key), 121 | } 122 | 123 | 124 | def test_generate_account_random(): 125 | seen = set() 126 | for i in range(5): 127 | account = generate_account() 128 | assert account['address'] not in seen 129 | seen.add(account['address']) 130 | 131 | assert ( 132 | private_to_public_key(account['private_key_bytes']) 133 | == account['public_key_bytes'] 134 | ) 135 | assert ( 136 | public_key_to_xrb_address(account['public_key_bytes']) == account['address'] 137 | ) 138 | -------------------------------------------------------------------------------- /tests/test_conversion.py: -------------------------------------------------------------------------------- 1 | from decimal import Decimal 2 | 3 | import pytest 4 | 5 | from nano.conversion import convert 6 | 7 | 8 | @pytest.mark.parametrize( 9 | 'value,from_unit,expected,to_unit', 10 | [ 11 | (Decimal('1'), 'XRB', Decimal('1'), 'NANO'), 12 | (Decimal('1'), 'XRB', Decimal('0.001'), 'Gxrb'), 13 | (Decimal('1'), 'NANO', Decimal('1'), 'Mxrb'), 14 | (Decimal('1'), 'XRB', Decimal('1000'), 'kxrb'), 15 | (Decimal('1'), 'XRB', Decimal('1000000'), 'xrb'), 16 | (Decimal('1'), 'XRB', Decimal('1000000000'), 'mxrb'), 17 | (Decimal('1'), 'XRB', Decimal('1000000000000'), 'urai'), 18 | ( 19 | Decimal('340282366920938463463374607431768211455'), 20 | 'raw', 21 | Decimal('340282366.9209384634633746074'), 22 | 'XRB', 23 | ), 24 | ( # is 25 | 340282366920938463463374607431768211455, 26 | 'raw', 27 | Decimal('340282366.9209384634633746074'), 28 | 'XRB', 29 | ), 30 | (Decimal('-1'), 'XRB', Decimal('-1'), 'Mrai'), 31 | (Decimal('-1'), 'NANO', Decimal('-1000000'), 'xrb'), 32 | (Decimal('3.142'), 'XRB', Decimal('3142000'), 'xrb'), 33 | (Decimal('-3.142'), 'XRB', Decimal('-3142000'), 'xrb'), 34 | (Decimal('-3142000'), 'raw', Decimal('-3142000'), 'raw'), 35 | ], 36 | ) 37 | def test_convert(value, from_unit, expected, to_unit): 38 | result = convert(value, from_unit, to_unit) 39 | assert result == expected 40 | 41 | 42 | @pytest.mark.parametrize( 43 | 'value,from_unit,to_unit', 44 | [ 45 | (1, 'badunit', 'XRB'), 46 | (1, 'XRB', 'badunit'), 47 | ('string', 'XRB', 'XRB'), 48 | (1.4, 'XRB', 'XRB'), 49 | ], 50 | ) 51 | def test_invalid_convert(value, from_unit, to_unit): 52 | with pytest.raises(ValueError): 53 | convert(value, from_unit=from_unit, to_unit=to_unit) 54 | -------------------------------------------------------------------------------- /tests/test_crypto.py: -------------------------------------------------------------------------------- 1 | from binascii import unhexlify 2 | 3 | import pytest 4 | 5 | from nano.crypto import ( 6 | b32xrb_encode, 7 | b32xrb_decode, 8 | address_checksum, 9 | private_to_public_key, 10 | keypair_from_seed, 11 | verify_signature, 12 | sign_message, 13 | ) 14 | 15 | SIGNING_TESTS = [ 16 | { 17 | 'private_key': unhexlify( 18 | 'A1A7DF26F28DBCC9AB2FF66431473C5F' 'C7F6DD48CAC1485CD45F3F9D82616802' 19 | ), 20 | 'public_key': unhexlify( 21 | '8A3E229B28FFC19DE27C2FD9AFBB6BA' '8723E7E267B87AA690854AB01543E9D20' 22 | ), 23 | 'message': unhexlify( 24 | '5904FC0108F37D30AD57AF9A56F54354' '2476425E473F3C0AFC8D44348BDA48C0' 25 | ), 26 | 'signature': unhexlify( 27 | '025CA216857868E2094C246104ADBDC8' 28 | '2BC8ACE2C658AB4A68601BA0636187A7' 29 | '474AFBB94FDDD05868BA78D7A1C02D3E' 30 | '56860BE529539EEBCE810C9D1603540F' 31 | ), 32 | } 33 | ] 34 | 35 | B32XRB_TESTS = [ 36 | (b'', b''), 37 | (b'hello', b'f3kpru5h'), 38 | (b'okay', b'fxop4ya='), 39 | (b'deadbeef', b'ejkp4s54eokpe==='), 40 | ] 41 | 42 | 43 | @pytest.mark.parametrize('decoded,encoded', B32XRB_TESTS) 44 | def test_b32xrb_encode(decoded, encoded): 45 | result = b32xrb_encode(decoded) 46 | assert result == encoded 47 | 48 | 49 | @pytest.mark.parametrize('decoded, encoded', B32XRB_TESTS) 50 | def test_b32xrb_decode(decoded, encoded): 51 | result = b32xrb_decode(encoded) 52 | assert result == decoded 53 | 54 | 55 | @pytest.mark.parametrize( 56 | 'private_key,public_key', 57 | [ 58 | ( 59 | unhexlify( 60 | '9f0e444c69f77a49bd0be89db92c38fe' '713e0963165cca12faf5712d7657120f' 61 | ), 62 | unhexlify( 63 | 'c008b814a7d269a1fa3c6528b19201a2' '4d797912db9996ff02a1ff356e45552b' 64 | ), 65 | ) 66 | ], 67 | ) 68 | def test_private_to_public_key(private_key, public_key): 69 | result = private_to_public_key(private_key) 70 | assert result == public_key 71 | 72 | 73 | @pytest.mark.parametrize( 74 | 'value,expected', [(b'', b'.\'\xc5d}'), (b'\x01$', b'\xa3\x88\xe8#\xe6')] 75 | ) 76 | def test_address_checksum(value, expected): 77 | assert address_checksum(value) == expected 78 | 79 | 80 | @pytest.mark.parametrize( 81 | 'args,expected', 82 | [ 83 | ( 84 | (unhexlify(b'0' * 64),), 85 | { 86 | 'private': unhexlify( 87 | '9f0e444c69f77a49bd0be89db92c38fe' 88 | '713e0963165cca12faf5712d7657120f' 89 | ), 90 | 'public': unhexlify( 91 | 'c008b814a7d269a1fa3c6528b19201a24' 92 | 'd797912db9996ff02a1ff356e45552b' 93 | ), 94 | }, 95 | ), 96 | ( 97 | (unhexlify(b'0' * 64), 0), 98 | { 99 | 'private': unhexlify( 100 | '9f0e444c69f77a49bd0be89db92c38fe' 101 | '713e0963165cca12faf5712d7657120f' 102 | ), 103 | 'public': unhexlify( 104 | 'c008b814a7d269a1fa3c6528b19201a24' 105 | 'd797912db9996ff02a1ff356e45552b' 106 | ), 107 | }, 108 | ), 109 | ( 110 | (unhexlify(b'0' * 64), 1), 111 | { 112 | 'private': unhexlify( 113 | 'b73b723bf7bd042b66ad3332718ba98d' 114 | 'e7312f95ed3d05a130c9204552a7afff' 115 | ), 116 | 'public': unhexlify( 117 | 'e30d22b7935bcc25412fc07427391ab4c' 118 | '98a4ad68baa733300d23d82c9d20ad3' 119 | ), 120 | }, 121 | ), 122 | ( 123 | (unhexlify(b'1' * 64),), 124 | { 125 | 'private': unhexlify( 126 | 'DBD5DF42B3D4120A9E8F6D3B2EEDCDC2' 127 | '1AD27CF76E95978564F66F44E0240184' 128 | ), 129 | 'public': unhexlify( 130 | '2791D5A1697D454448F9EEABA2A336E52' 131 | '2D5767E570B326278F5532194F642C8' 132 | ), 133 | }, 134 | ), 135 | ( 136 | (unhexlify(b'1' * 64), 0), 137 | { 138 | 'private': unhexlify( 139 | 'DBD5DF42B3D4120A9E8F6D3B2EEDCDC2' 140 | '1AD27CF76E95978564F66F44E0240184' 141 | ), 142 | 'public': unhexlify( 143 | '2791D5A1697D454448F9EEABA2A336E52' 144 | '2D5767E570B326278F5532194F642C8' 145 | ), 146 | }, 147 | ), 148 | ( 149 | (unhexlify(b'1' * 64), 1), 150 | { 151 | 'private': unhexlify( 152 | '4A6E3512ACBB38A3D6BCF53D5452E11F' 153 | '6B34C30D0405139E3328FD7A63E2D612' 154 | ), 155 | 'public': unhexlify( 156 | 'E04BC3CAEDAA1787E9373A105453160E4' 157 | 'B6BEDFE1782A0DBA0C98A89D435DD27' 158 | ), 159 | }, 160 | ), 161 | ], 162 | ) 163 | def test_keypair_from_seed(args, expected): 164 | result = keypair_from_seed(*args) 165 | assert result == expected 166 | 167 | 168 | @pytest.mark.parametrize('data', SIGNING_TESTS) 169 | def test_verify_signature(data): 170 | public_key = data['public_key'] 171 | message = data['message'] 172 | signature = data['signature'] 173 | 174 | assert verify_signature(message, signature, public_key) == True 175 | assert verify_signature(message + b'1', signature, public_key) == False 176 | 177 | 178 | @pytest.mark.parametrize('data', SIGNING_TESTS) 179 | def test_sign_message(data): 180 | public_key = data['public_key'] 181 | private_key = data['private_key'] 182 | message = data['message'] 183 | expected_signature = data['signature'] 184 | 185 | signature = sign_message(message, private_key) 186 | assert signature == expected_signature 187 | signature = sign_message(message, private_key, public_key) 188 | assert signature == expected_signature 189 | 190 | 191 | @pytest.mark.parametrize( 192 | 'message,signature,public_key,error_msg', 193 | [ 194 | (b'a message', b'badsig', b'0' * 32, 'signature length is wrong'), 195 | (b'a message', b'0' * 64, b'badpubkey', 'public-key length is wrong'), 196 | (b'a message', b'0' * 64, b'0' * 32, 'decoding point that is not on curve'), 197 | ], 198 | ) 199 | def test_verify_signature_invalid(message, signature, public_key, error_msg): 200 | with pytest.raises(ValueError) as e_info: 201 | verify_signature(message, signature, public_key) 202 | 203 | assert e_info.match(error_msg) 204 | -------------------------------------------------------------------------------- /tests/test_mock_rpc.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from conftest import MockRPCMatchException 4 | 5 | 6 | class TestMockRPCSession(object): 7 | def test_existing_request(self, mock_rpc_session): 8 | resp = mock_rpc_session.post( 9 | 'mock://localhost:7076/', json={"action": "version"} 10 | ) 11 | assert resp.json() == { 12 | "rpc_version": "1", 13 | "store_version": "10", 14 | "node_vendor": "RaiBlocks 9.0", 15 | } 16 | 17 | def test_missing_request(self, mock_rpc_session): 18 | with pytest.raises(MockRPCMatchException): 19 | resp = mock_rpc_session.post( 20 | 'mock://localhost:7076/', json={"action": "DOES NOT EXIST"} 21 | ) 22 | -------------------------------------------------------------------------------- /tests/test_rpc.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | import pytest 4 | 5 | from conftest import MockRPCMatchException, load_mock_rpc_tests 6 | from nano.rpc import RPCClient, RPCException 7 | 8 | mock_rpc_tests = load_mock_rpc_tests() 9 | 10 | 11 | @pytest.fixture 12 | def rpc(mock_rpc_session): 13 | return RPCClient(host='mock://localhost:7076', session=mock_rpc_session) 14 | 15 | 16 | class TestRPCClient(object): 17 | @pytest.mark.parametrize( 18 | 'arguments', 19 | [{}, {'host': 'http://localhost:7076/'}, {'host': 'http://localhost:7076'}], 20 | ) 21 | def test_create(self, arguments): 22 | assert RPCClient(**arguments) 23 | 24 | def test_call_valid_action(self, rpc): 25 | assert rpc.call('version') == { 26 | "rpc_version": "1", 27 | "store_version": "10", 28 | "node_vendor": "RaiBlocks 9.0", 29 | } 30 | 31 | def test_call_invalid_action(self, rpc): 32 | 33 | with pytest.raises(MockRPCMatchException): 34 | assert rpc.call('versions') 35 | 36 | @pytest.mark.parametrize( 37 | 'action,test', 38 | [(action, test) for action, tests in mock_rpc_tests.items() for test in tests], 39 | ) 40 | def test_rpc_methods(self, rpc, action, test): 41 | """ 42 | Tests should be in the format: 43 | 44 | { 45 | "args": {"values": [3, 2]}, 46 | "expected": 5, 47 | "request": { 48 | "add": [3, 2] 49 | }, 50 | "response": "5" 51 | } 52 | 53 | Assuming we want to test a function add(values=[3, 2]) which sends 54 | a request to the backend with {"add": [3, 2]} and gets a response 55 | with string "5" and the function returns int 5 56 | 57 | If the response contains an "error" key, it is assumed the function 58 | must raise an `RPCException` and "expected" is ignored 59 | """ 60 | 61 | try: 62 | method = getattr(rpc, action) 63 | except AttributeError: 64 | raise Exception("`%s` not yet implemented" % action) 65 | 66 | try: 67 | arguments = test.get('args') or {} 68 | expected = test['expected'] 69 | request = test['request'] 70 | response = test['response'] 71 | except KeyError: 72 | raise Exception( 73 | 'invalid test for %s: %s' % (action, json.dumps(test, indent=2)) 74 | ) 75 | 76 | if "error" in response: 77 | with pytest.raises(RPCException): 78 | result = method(**arguments) 79 | return 80 | 81 | result = method(**arguments) 82 | request_made = rpc.session.adapter.last_request.json() 83 | 84 | assert request_made == request 85 | 86 | if result != expected: 87 | print('result:') 88 | print(json.dumps(result, indent=2, sort_keys=True)) 89 | print('expected:') 90 | print(json.dumps(expected, indent=2, sort_keys=True)) 91 | 92 | assert result == expected 93 | 94 | def test_all_rpc_methods_are_tested(self): 95 | for attr in RPCClient.__dict__: 96 | if attr.startswith('_'): 97 | continue 98 | if attr in ('call',): 99 | continue 100 | if attr not in mock_rpc_tests: 101 | raise Exception('`%s` rpc method has no test' % attr) 102 | 103 | def test_unimplemented_test_fails(self, rpc): 104 | with pytest.raises(Exception) as e_info: 105 | self.test_rpc_methods(rpc, 'invalid', {}) 106 | assert e_info.match('not yet implemented') 107 | 108 | def test_invalid_test_fails(self, rpc): 109 | with pytest.raises(Exception) as e_info: 110 | self.test_rpc_methods(rpc, 'version', {}) 111 | assert e_info.match('invalid test') 112 | 113 | def test_bad_test_fails(self, rpc): 114 | with pytest.raises(AssertionError) as e_info: 115 | self.test_rpc_methods( 116 | rpc, 117 | 'version', 118 | {'expected': None, 'request': {'action': 'version'}, 'response': {}}, 119 | ) 120 | -------------------------------------------------------------------------------- /tests/test_version.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from nano.version import __version__ 4 | 5 | 6 | def is_canonical(version): 7 | return ( 8 | re.match( 9 | r'^([1-9]\d*!)?(0|[1-9]\d*)(\.(0|[1-9]\d*))*((a|b|rc)(0|[1-9]\d*))?(\.post(0|[1-9]\d*))?(\.dev(0|[1-9]\d*))?$', 10 | version, 11 | ) 12 | is not None 13 | ) 14 | 15 | 16 | def test_version(): 17 | assert is_canonical(__version__) 18 | --------------------------------------------------------------------------------