Skip to content

Commit

Permalink
REM-1296: Get list of the batches
Browse files Browse the repository at this point in the history
  • Loading branch information
Artem Saprykin committed Apr 24, 2019
1 parent 789714a commit 326892d
Show file tree
Hide file tree
Showing 9 changed files with 598 additions and 1 deletion.
66 changes: 65 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* [Nodes](#nodes)
* [Configuration file](#configuration-file)
* [Service](#service)
* [Account](#account)
* [Batch](#batch)
* [Development](#development)
* [Requirements](#development-requirements)
* [Docker](#docker)
Expand Down Expand Up @@ -116,6 +116,70 @@ $ remme account get-balance \
}
```

### Batch

Get a list of batches — ``remme batch get-list``:

| Arguments | Type | Required | Description |
| :-------: | :----: | :-------: | --------------------------------------------------- |
| ids | String | No | Identifiers to get a list of batches by. |
| start | String | No | Parameter to list batches starting from. |
| limit | Integer| No | Parameter to limit amount of batches. |
| head | String | No | Block identifier to get a list of batches from. |
| reverse | String | No | Parameter to reverse result. |
| node-url | String | No | Node URL to apply the command to. |

```bash
$ remme batch get-list \
--ids=[c2eeb94926d3432e41cb5ceed078f78466389e4fe685ec958021a1368f634c035072e434e5d0ff64820dd01fde6e5afc67eb5a9ae6c48d3983ff43abe98aef6b] \
--node-url=159.89.104.9
{
"result": {
"data": [
{
"header": {
"signer_public_key": "02d1fbda50dbcd0d3c286a6a9fa71aa7ce2d97159b90ddd463e0816422d621e135",
"transaction_ids": [
"0317216042416f38087fed16bd4a0e1ea90ca240d22547495f8eb0d23c9b680e0d763199e7864f2384256d16d5ea56ca31ee8087f6c579434dcd454d97140faa"
]
},
"header_signature": "c2eeb94926d3432e41cb5ceed078f78466389e4fe685ec958021a1368f634c035072e434e5d0ff64820dd01fde6e5afc67eb5a9ae6c48d3983ff43abe98aef6b",
"trace": false,
"transactions": [
{
"header": {
"batcher_public_key": "02d1fbda50dbcd0d3c286a6a9fa71aa7ce2d97159b90ddd463e0816422d621e135",
"dependencies": [],
"family_name": "block_info",
"family_version": "1.0",
"inputs": [
"00b10c0100000000000000000000000000000000000000000000000000000000000000",
"00b10c00"
],
"nonce": "",
"outputs": [
"00b10c0100000000000000000000000000000000000000000000000000000000000000",
"00b10c00"
],
"payload_sha512": "68073292cc2595ed11eac0a9b61c9a54cbee641209ab75ce83f8a4ccb78c64fb77c78d05d54f52624664a4725f5c57cd89f665d22dfcebe9fe11acd28c48884d",
"signer_public_key": "02d1fbda50dbcd0d3c286a6a9fa71aa7ce2d97159b90ddd463e0816422d621e135"
},
"header_signature": "0317216042416f38087fed16bd4a0e1ea90ca240d22547495f8eb0d23c9b680e0d763199e7864f2384256d16d5ea56ca31ee8087f6c579434dcd454d97140faa",
"payload": "CtICCHoSgAFkZGJhZTU2ZDZkYzJiMDE2MjQyODc1NWE1MmJkZDdhYzkzODJjNGRiOTk3MTkzMWEyMTA5MmZhYjA1ZGIwZDJjNWYzMzE2M2NlODZhZTRlNzY0MGEyYmY0ZWNhNWJiMzdlZTM2NzU1N2M2YTc4ZDMwOGQ0ZGYyMWQxY2Y3Y2EyORpCMDJkMWZiZGE1MGRiY2QwZDNjMjg2YTZhOWZhNzFhYTdjZTJkOTcxNTliOTBkZGQ0NjNlMDgxNjQyMmQ2MjFlMTM1IoABMGU4ODRkYjdiYjRkN2ZkYTdhODc2YWQ4NzVmNTA0NWFjNmY1MDUwZDZlOGVkYzk2NjRhZjg0NWI2YTM0Mzk4ODc4YmQ2MDA2ODgyY2JjMTMzNTMzYzQ1OWRhZDE3ZDExODMwNGViZjNjOGFmMmE2ZGZhNWViNWIzMjc4MTViY2QoyPb85QU="
}
]
}
],
"head": "b6ac30a480b237c8796fa4903354af835c85d78e781644265bc7a202b61d750c465790865b28ce69473d02b4e056d823194fd29e3f986800f0e7316865bffd7b",
"paging": {
"limit": null,
"next": "",
"start": null
}
}
}
```

## Development

<h3 id="development-requirements">Requirements</h4>
Expand Down
Empty file added cli/batch/__init__.py
Empty file.
105 changes: 105 additions & 0 deletions cli/batch/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"""
Provide implementation of the command line interface's batch commands.
"""
import asyncio
import sys

import click
from remme import Remme

from cli.batch.forms import ListBatchesForm
from cli.batch.help import (
BATCH_HEAD_ARGUMENT_HELP_MESSAGE,
BATCH_IDS_ARGUMENT_HELP_MESSAGE,
BATCH_LIMIT_ARGUMENT_HELP_MESSAGE,
BATCH_REVERSE_ARGUMENT_HELP_MESSAGE,
BATCH_START_ARGUMENT_HELP_MESSAGE,
)
from cli.batch.service import Batch
from cli.constants import (
FAILED_EXIT_FROM_COMMAND_CODE,
NODE_URL_ARGUMENT_HELP_MESSAGE,
)
from cli.utils import (
default_node_url,
dict_to_pretty_json,
print_errors,
print_result,
)

loop = asyncio.get_event_loop()


@click.group('batch', chain=True)
def batch_commands():
"""
Provide commands for working with batches.
"""
pass


def _split_ids(ctx, param, value):
"""
Convert string to list. Remove '[', ']' and split by ','.
"""
if value is None:
return

if value[0] != '[' or value[-1] != ']':
click.echo(dict_to_pretty_json({
'ids': ['Not a valid list.'],
}))
sys.exit(FAILED_EXIT_FROM_COMMAND_CODE)
value = value[1:-1]
values = [c.strip() for c in value.split(',')]

return values


@click.option('--ids', type=str, required=False, help=BATCH_IDS_ARGUMENT_HELP_MESSAGE, callback=_split_ids)
@click.option('--start', type=str, required=False, help=BATCH_START_ARGUMENT_HELP_MESSAGE)
@click.option('--limit', type=int, required=False, help=BATCH_LIMIT_ARGUMENT_HELP_MESSAGE)
@click.option('--head', type=str, required=False, help=BATCH_HEAD_ARGUMENT_HELP_MESSAGE)
@click.option('--reverse', type=str, required=False, help=BATCH_REVERSE_ARGUMENT_HELP_MESSAGE)
@click.option('--node-url', type=str, required=False, help=NODE_URL_ARGUMENT_HELP_MESSAGE, default=default_node_url())
@batch_commands.command('get-list')
def get_batches(ids, start, limit, head, reverse, node_url):
"""
Get a list of batches.
"""
arguments, errors = ListBatchesForm().load({
'ids': ids,
'start': start,
'limit': limit,
'head': head,
'reverse': reverse,
'node_url': node_url,
})

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

ids = arguments.get('ids')
start = arguments.get('start')
limit = arguments.get('limit')
head = arguments.get('head')
reverse = arguments.get('reverse')
node_url = arguments.get('node_url')

remme = Remme(network_config={
'node_address': str(node_url) + ':8080',
})

query = {
'ids': ids,
'start': start,
'limit': limit,
'head': head,
'reverse': reverse,
}

batch_service = Batch(service=remme)
batches = loop.run_until_complete(batch_service.get_list(query))

print_result(batches)
87 changes: 87 additions & 0 deletions cli/batch/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""
Provide forms for command line interface's batch commands.
"""
import re

from marshmallow import (
Schema,
ValidationError,
fields,
validates,
)

from cli.constants import (
DOMAIN_NAME_REGEXP,
HEADER_SIGNATURE_REGEXP,
)


class ListBatchesForm(Schema):
"""
List batches validation form.
"""

ids = fields.List(fields.String(), allow_none=True, required=False)
start = fields.String(allow_none=True, required=False)
limit = fields.Integer(allow_none=True, required=False)
head = fields.String(allow_none=True, required=False)
reverse = fields.String(allow_none=True, required=False)
node_url = fields.String(allow_none=True, required=False)

@validates('ids')
def validate_ids(self, ids):
"""
Validate batch identifiers.
"""
if ids is not None:
for batch_id in ids:
if re.match(pattern=HEADER_SIGNATURE_REGEXP, string=batch_id) is None:
raise ValidationError(f'The following batch id `{batch_id}` is invalid.')

@validates('start')
def validate_start(self, start):
"""
Validate start.
"""
if start is not None and re.match(pattern=HEADER_SIGNATURE_REGEXP, string=start) is None:
raise ValidationError(f'The following batch id `{start}` is invalid.')

@validates('limit')
def validate_limit(self, limit):
"""
Validate limit.
"""
if limit is not None and limit < 0:
raise ValidationError("Limit can't be negative.")

@validates('head')
def validate_head(self, head):
"""
Validate head.
"""
if head is not None and re.match(pattern=HEADER_SIGNATURE_REGEXP, string=head) is None:
raise ValidationError(f'The following block id `{head}` is invalid.')

@validates('reverse')
def validate_reverse(self, reverse):
"""
Validate reverse.
"""
if reverse is not None and reverse not in ('true', 'false'):
raise ValidationError("Invalid reverse field. Should be either 'true' or 'false'.")

@validates('node_url')
def validate_node_url(self, node_url):
"""
Validate node URL.
If node URL is localhost, it means client didn't passed any URL, so nothing to validate.
"""
if node_url == 'localhost':
return

if 'http' in node_url or 'https' in node_url:
raise ValidationError(f'Pass the following node URL `{node_url}` without protocol (http, https, etc.).')

if re.match(pattern=DOMAIN_NAME_REGEXP, string=node_url) is None:
raise ValidationError(f'The following node URL `{node_url}` is invalid.')
8 changes: 8 additions & 0 deletions cli/batch/help.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""
Provide help messages for command line interface's batch commands.
"""
BATCH_IDS_ARGUMENT_HELP_MESSAGE = 'Identifiers to get a list of batches by.'
BATCH_START_ARGUMENT_HELP_MESSAGE = 'Parameter to list batches starting from.'
BATCH_LIMIT_ARGUMENT_HELP_MESSAGE = 'Parameter to limit amount of batches.'
BATCH_HEAD_ARGUMENT_HELP_MESSAGE = 'Block identifier to get a list of batches from.'
BATCH_REVERSE_ARGUMENT_HELP_MESSAGE = 'Parameter to reverse result.'
21 changes: 21 additions & 0 deletions cli/batch/interfaces.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""
Provide implementation of the batch interfaces.
"""


class BatchInterface:
"""
Implements batch interface.
"""

async def get_list(self, query=None):
"""
Get a list of batches from REMChain.
Arguments:
query (dict, optional): dictionary with specific parameters
Returns:
List of batches.
"""
pass
34 changes: 34 additions & 0 deletions cli/batch/service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""
Provide implementation of the batch service.
"""
from accessify import implements

from cli.batch.interfaces import BatchInterface


@implements(BatchInterface)
class Batch:
"""
Implements batch interface.
"""

def __init__(self, service):
"""
Constructor.
Arguments:
service: object to interact with Remme core API.
"""
self.service = service

async def get_list(self, query=None):
"""
Get all batches from REMChain.
Arguments:
query (dict, optional): dictionary with specific parameters
Returns:
List of batches.
"""
return await self.service.blockchain_info.get_batches(query=query)
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.batch.cli import batch_commands


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


cli.add_command(account_commands)
cli.add_command(batch_commands)
Loading

0 comments on commit 326892d

Please sign in to comment.