Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get list of the public keys by account address on which these keys depend #16

Merged
merged 11 commits into from
Apr 24, 2019
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* [Configuration file](#configuration-file)
* [Service](#service)
* [Account](#account)
* [Public key](#public-key)
* [Development](#development)
* [Requirements](#development-requirements)
* [Docker](#docker)
Expand Down Expand Up @@ -139,6 +140,26 @@ $ remme account transfer-tokens \
}
```

### Public key

Get list of the public keys by account address — ``remme public-key get-list``:
Copy link
Contributor

@dmytrostriletskyi dmytrostriletskyi Apr 24, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get list of the public keys ... > Get a list of the addresses of the public keys....

Apply the same to the code and tests documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


| Arguments | Type | Required | Description |
| :-------: | :----: | :------: | ------------------------------------------ |
| address | String | Yes | Address to get list of the public keys by. |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apply the comment above to the argument description.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

| node-url | String | No | Node URL to apply a command to. |

```bash
$ remme public-key get-list \
--address=1120076ecf036e857f42129b58303bcf1e03723764a1702cbe98529802aad8514ee3cf \
--node-url=node-genesis-testnet.remme.io
[
"a23be14785e7b073b50e24f72e086675289795b969a895a7f02202404086946e8ddc5b",
"a23be17265e8393dd9ae7a46f1be662f86130c434fd54576a7d92b678e5c30de4f677f",
...
]
```

## Development

<h3 id="development-requirements">Requirements</h4>
Expand Down Expand Up @@ -174,7 +195,7 @@ $ docker exec -it remme-core-cli bash

And now being in the container, you can develop the project. For instance, run tests and linters:

```bash
```bashpytest -vv tests/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert this change, please.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$ pytest -vv tests/
$ flake8 cli && flake8 tests/
```
Expand Down
2 changes: 2 additions & 0 deletions cli/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import click

from cli.account.cli import account_commands
from cli.public_key.cli import public_key_commands


@click.group()
Expand All @@ -17,3 +18,4 @@ def cli():


cli.add_command(account_commands)
cli.add_command(public_key_commands)
Empty file added cli/public_key/__init__.py
Empty file.
61 changes: 61 additions & 0 deletions cli/public_key/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
Provide implementation of the command line interface's public key commands.
"""
import asyncio
import sys

import click
from remme import Remme

from cli.constants import (
FAILED_EXIT_FROM_COMMAND_CODE,
NODE_URL_ARGUMENT_HELP_MESSAGE,
)
from cli.public_key.forms import GetPublicKeysForm
from cli.public_key.help import ADDRESS_ARGUMENT_HELP_MESSAGE
from cli.public_key.service import PublicKey
from cli.utils import (
default_node_url,
print_errors,
print_result,
)

loop = asyncio.get_event_loop()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You do not need it anymore here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.



@click.group('public-key', chain=True)
def public_key_commands():
"""
Provide commands for working with public key.
"""
pass


@click.option('--address', type=str, required=True, help=ADDRESS_ARGUMENT_HELP_MESSAGE)
@click.option('--node-url', type=str, required=False, help=NODE_URL_ARGUMENT_HELP_MESSAGE, default=default_node_url())
@public_key_commands.command('get-list')
def get_public_keys(address, node_url):
"""
Get list of the public keys by account address.
"""
arguments, errors = GetPublicKeysForm().load({
'address': address,
'node_url': node_url,
})

if errors:
print_errors(errors)
sys.exit(FAILED_EXIT_FROM_COMMAND_CODE)

address = arguments.get('address')
node_url = arguments.get('node_url')

remme = Remme(network_config={'node_address': str(node_url) + ':8080'})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow this style, please.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


result, errors = PublicKey(service=remme).get_list(address=address)

if errors is not None:
print_errors(errors=errors)
sys.exit(FAILED_EXIT_FROM_COMMAND_CODE)

print_result(result=result)
18 changes: 18 additions & 0 deletions cli/public_key/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""
Provide forms for command line interface's account commands.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

account > public key.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"""
from marshmallow import Schema

from cli.generic.forms.fields import (
AccountAddressField,
NodeURLField,
)


class GetPublicKeysForm(Schema):
"""
Get list of the public keys of the public key form.
"""

address = AccountAddressField(required=True)
node_url = NodeURLField(allow_none=True, required=False)
4 changes: 4 additions & 0 deletions cli/public_key/help.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"""
Provide help messages for command line interface's public key commands.
"""
ADDRESS_ARGUMENT_HELP_MESSAGE = 'Account address to get list of the public keys by.'
15 changes: 15 additions & 0 deletions cli/public_key/interfaces.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""
Provide implementation of the public key interfaces.
"""


class PublicKeyInterface:
"""
Implements public key interface.
"""

def get_list(self, address):
"""
Get list of the public keys by account address.
"""
pass
36 changes: 36 additions & 0 deletions cli/public_key/service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""
Provide implementation of the public key.
"""
import asyncio

from accessify import implements

from cli.public_key.interfaces import PublicKeyInterface

loop = asyncio.get_event_loop()


@implements(PublicKeyInterface)
class PublicKey:
"""
Implements public key.
"""

def __init__(self, service):
"""
Constructor.

Arguments:
service: object to interact with Remme core API.
"""
self.service = service

def get_list(self, address):
"""
Get list of the public keys by account address.
"""
public_keys = loop.run_until_complete(self.service.public_key_storage.get_account_public_keys(address=address))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember to handle Exception and write tests for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


return {
'public_keys': public_keys,
}, None
Empty file added tests/public_key/__init__.py
Empty file.
178 changes: 178 additions & 0 deletions tests/public_key/test_get_public_keys.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
"""
Provide tests for command line interface's public key get public keys commands.
"""
import json
import re

from click.testing import CliRunner

from cli.constants import (
ADDRESS_REGEXP,
FAILED_EXIT_FROM_COMMAND_CODE,
NODE_IP_ADDRESS_FOR_TESTING,
PASSED_EXIT_FROM_COMMAND_CODE,
)
from cli.entrypoint import cli
from cli.utils import dict_to_pretty_json

ADDRESS_PRESENTED_ON_THE_TEST_NODE = '1120076ecf036e857f42129b58303bcf1e03723764a1702cbe98529802aad8514ee3cf'


def test_get_public_keys():
"""
Case: get a list of the public keys by account address.
Expect: list of public keys, each public key matched regexp checking.
"""
runner = CliRunner()
result = runner.invoke(cli, [
'public-key',
'get-list',
'--address',
ADDRESS_PRESENTED_ON_THE_TEST_NODE,
'--node-url',
NODE_IP_ADDRESS_FOR_TESTING,
])

public_keys = json.loads(result.output).get('result').get('public_keys')

assert PASSED_EXIT_FROM_COMMAND_CODE == result.exit_code

for public_key in public_keys:
assert re.match(pattern=ADDRESS_REGEXP, string=public_key) is not None


def test_get_public_keys_invalid_address():
"""
Case: get a list of the public keys by invalid address.
Expect: the following address is not valid error message.
"""
invalid_address = '1120076ecf036e857f42129b58303bcf1e03723764a1702cbe98529802aad8514ee3zz'

runner = CliRunner()
result = runner.invoke(cli, [
'public-key', 'get-list', '--address', invalid_address, '--node-url', NODE_IP_ADDRESS_FOR_TESTING,
])

expected_error = {
'errors': {
'address': [
f'The following address `{invalid_address}` is invalid.',
],
},
}

assert FAILED_EXIT_FROM_COMMAND_CODE == result.exit_code
assert dict_to_pretty_json(expected_error) in result.output


def test_get_public_keys_without_node_url(mocker):
"""
Case: get a list of the public keys by address without passing node URL.
Expect: list of public keys is returned from node on localhost.
"""
list_of_public_keys = [
'a23be14785e7b073b50e24f72e086675289795b969a895a7f02202404086946e8ddc5b',
'a23be17265e8393dd9ae7a46f1be662f86130c434fd54576a7d92b678e5c30de4f677f',
]

mock_public_key_get_public_keys = mocker.patch('cli.public_key.service.loop.run_until_complete')
mock_public_key_get_public_keys.return_value = list_of_public_keys

runner = CliRunner()
result = runner.invoke(cli, ['public-key', 'get-list', '--address', ADDRESS_PRESENTED_ON_THE_TEST_NODE])

expected_result = {
'result': {
'public_keys': list_of_public_keys,
},
}

assert PASSED_EXIT_FROM_COMMAND_CODE == result.exit_code
assert expected_result == json.loads(result.output)


def test_get_public_keys_invalid_node_url():
"""
Case: get a list of the public keys by passing invalid node URL.
Expect: the following node URL is invalid error message.
"""
invalid_node_url = 'domainwithoutextention'

runner = CliRunner()
result = runner.invoke(cli, [
'public-key',
'get-list',
'--address',
ADDRESS_PRESENTED_ON_THE_TEST_NODE,
'--node-url',
invalid_node_url,
])

expected_error = {
'errors': {
'node_url': [
f'The following node URL `{invalid_node_url}` is invalid.',
],
},
}

assert FAILED_EXIT_FROM_COMMAND_CODE == result.exit_code
assert dict_to_pretty_json(expected_error) in result.output


def test_get_public_keys_node_url_with_http():
"""
Case: get a list of the public keys by passing node URL with explicit HTTP protocol.
Expect: the following node URL contains protocol error message.
"""
node_url_with_http_protocol = 'http://masternode.com'

runner = CliRunner()
result = runner.invoke(cli, [
'public-key',
'get-list',
'--address',
ADDRESS_PRESENTED_ON_THE_TEST_NODE,
'--node-url',
node_url_with_http_protocol,
])

expected_error = {
'errors': {
'node_url': [
f'Pass the following node URL `{node_url_with_http_protocol}` without protocol (http, https, etc.).',
],
},
}

assert FAILED_EXIT_FROM_COMMAND_CODE == result.exit_code
assert dict_to_pretty_json(expected_error) in result.output


def test_get_public_keys_node_url_with_https():
"""
Case: get a list of the public keys by passing node URL with explicit HTTPS protocol.
Expect: the following node URL contains protocol error message.
"""
node_url_with_https_protocol = 'https://masternode.com'

runner = CliRunner()
result = runner.invoke(cli, [
'public-key',
'get-list',
'--address',
ADDRESS_PRESENTED_ON_THE_TEST_NODE,
'--node-url',
node_url_with_https_protocol,
])

expected_error = {
'errors': {
'node_url': [
f'Pass the following node URL `{node_url_with_https_protocol}` without protocol (http, https, etc.).',
],
},
}

assert FAILED_EXIT_FROM_COMMAND_CODE == result.exit_code
assert dict_to_pretty_json(expected_error) in result.output