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

REM-1298-1299: implement get list of the transactions and fetch particular transaction #18

Merged
merged 26 commits into from
May 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a829309
REM-1298-1299: implement transactions commands
Alladin9393 Apr 11, 2019
cbe2a41
Merge branch 'develop' into feature/REM-1298-get-list-transactions
Alladin9393 Apr 17, 2019
7469a21
REM-1289-1288: add json pretty
Alladin9393 Apr 17, 2019
ac80ab6
Merge branch 'develop' into feature/REM-1298-get-list-transactions
Alladin9393 Apr 17, 2019
25c0036
REM-1298-1299: fix typo
Alladin9393 Apr 17, 2019
d1475c7
fix-conflicts
Alladin9393 Apr 17, 2019
5b13f49
REM-1298-1299: add family name validation
Alladin9393 Apr 18, 2019
b15856e
REM-1298-1299: add marshmallow validation
Alladin9393 Apr 19, 2019
b0a64cb
REM-1298-1299: add tests and refactor code
Alladin9393 Apr 21, 2019
a82a432
Merge branch 'develop' into feature/REM-1298-get-list-transactions
Alladin9393 Apr 22, 2019
3e3a8a3
Comment non-working test
Alladin9393 Apr 22, 2019
7ae209f
Merge branch 'develop' into feature/REM-1298-get-list-transactions
Alladin9393 Apr 25, 2019
d35ff82
fix typo
Alladin9393 Apr 25, 2019
719b06b
Merge branch 'develop' into feature/REM-1298-get-list-transactions
Alladin9393 Apr 25, 2019
1bfed3a
fix typo errors
Alladin9393 Apr 26, 2019
08af4b5
Merge branch 'develop' into feature/REM-1298-get-list-transactions
Alladin9393 Apr 26, 2019
a4f56df
fix typos & documentation
Alladin9393 Apr 26, 2019
c1c34e4
Merge branch 'develop' into feature/REM-1298-get-list-transactions
Alladin9393 May 2, 2019
ecb0f0c
Merge branch 'develop' into feature/REM-1298-get-list-transactions
Alladin9393 May 2, 2019
2009f74
change TransactionIdentifiersListField validation method
Alladin9393 May 2, 2019
a2f5cbd
Merge branch 'develop' into feature/REM-1298-get-list-transactions
Alladin9393 May 2, 2019
cc036e7
Merge branch 'develop' into feature/REM-1298-get-list-transactions
Alladin9393 May 2, 2019
b63462b
fix typo
Alladin9393 May 2, 2019
0f49767
add test with all parameters
Alladin9393 May 3, 2019
33f14b1
Merge branch 'develop' into feature/REM-1298-get-list-transactions
Alladin9393 May 3, 2019
f9030e7
fix typo
Alladin9393 May 3, 2019
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
105 changes: 105 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* [Account](#account)
* [Node](#node)
* [Public key](#public-key)
* [Transaction](#transaction)
* [Development](#development)
* [Requirements](#development-requirements)
* [Docker](#docker)
Expand Down Expand Up @@ -249,6 +250,110 @@ $ remme public-key get-info \
}
```

### Transaction

Get a list of transactions — ``remme transaction get-list``:

| Arguments | Type | Required | Description |
| :---------: | :----: | :-------: | ----------------------------------------------------- |
| ids | String | No | Identifiers to get a list of transactions by. |
| start | String | No | Transaction identifier to get a list transaction starting from.|
| limit | Integer| No | Maximum amount of transactions to return. |
| head | String | No | Block identifier to get a list of transactions from. |
| reverse | Bool | No | Parameter to reverse result. |
| node-url | String | No | Node URL to apply a command to. |
| family-name | String | No | List of transactions by its family name. |

```bash
$ remme transaction get-list \
--ids='568a1094e574747c757c1f5028d9b929105984e509c4f2f3cb76e5f46f03ca4c3681ca0eeca86a4bd4bb5a3eaaa52fd73b08ebc5d5d85fbb1957b064f8b71972,
d9b891d3efdd51cd47156ad2083bf5cabd5b35bb2ebe66813996d1a0f783e58721bbc50917ff284a40696f24058ef1e22e48600abf37d500ace78eadf7f4ecff' \
--start=568a1094e574747c757c1f5028d9b929105984e509c4f2f3cb76e5f46f03ca4c3681ca0eeca86a4bd4bb5a3eaaa52fd73b08ebc5d5d85fbb1957b064f8b71972 \
--limit=2 \
--head=39566f24561727f5ab2d19eb23612f1a38ff5f0cf9491caa0275261706a7cf8b080d38da0a38fa5b1cbef0cced889fdf6da679cc616a9711380f76b33e53efdf \
--reverse \
--family-name=account \
--node-url=node-6-testnet.remme.io
{
"result": {
"data": [
{
"header": {
"batcher_public_key": "03d4613540ce29cd1f5f28ea9169a5cb5853bd53dede635903af9383bc9ffaf079",
"dependencies": [],
"family_name": "account",
"family_version": "0.1",
"inputs": [
"112007db16c75019f59423da4de3cd5c79609989d7dc1697c9975307ea846e1d4af91f",
"1120076ecf036e857f42129b58303bcf1e03723764a1702cbe98529802aad8514ee3cf"
],
"nonce": "99ccdbcfeb008e2c8407870b7033117e316b4b12df4173f3e2ffd510676e524a77ac64a0b65e6c7889a797fbd4e4462830548f455497e2362dde1bbf35d5372f",
"outputs": [
"112007db16c75019f59423da4de3cd5c79609989d7dc1697c9975307ea846e1d4af91f",
"1120076ecf036e857f42129b58303bcf1e03723764a1702cbe98529802aad8514ee3cf"
],
"payload_sha512": "1f0313cb9cd67559c1d33d61104882b3ebca80dfcd091d5ae3b0ee99bd27723af591551dfeea43be05e2b24a2f9a54adc6c357b60fc5c5720b161c5ff9d10ae1",
"signer_public_key": "03738df3f4ac3621ba8e89413d3ff4ad036c3a0a4dbb164b695885aab6aab614ad"
},
"header_signature": "d9b891d3efdd51cd47156ad2083bf5cabd5b35bb2ebe66813996d1a0f783e58721bbc50917ff284a40696f24058ef1e22e48600abf37d500ace78eadf7f4ecff",
"payload": "CAASTQgAEkYxMTIwMDdkYjE2Yzc1MDE5ZjU5NDIzZGE0ZGUzY2Q1Yzc5NjA5OTg5ZDdkYzE2OTdjOTk3NTMwN2VhODQ2ZTFkNGFmOTFmGOgH"
}
],
"head": "39566f24561727f5ab2d19eb23612f1a38ff5f0cf9491caa0275261706a7cf8b080d38da0a38fa5b1cbef0cced889fdf6da679cc616a9711380f76b33e53efdf",
"paging": {
"limit": 2,
"next": "",
"start": "568a1094e574747c757c1f5028d9b929105984e509c4f2f3cb76e5f46f03ca4c3681ca0eeca86a4bd4bb5a3eaaa52fd73b08ebc5d5d85fbb1957b064f8b71972"
}
}
}
```

Get a transaction by identifier — ``remme transaction get``:

| Arguments | Type | Required | Description |
| :---------: | :----: | :-------: | -------------------------------- |
| id | String | Yes | Identifier to get transaction by. |
| node-url | String | No | Node URL to apply a command to. |

```bash
$ remme transaction get \
--id=64d032fbaae9bc59f9e5484ec6f52cbceef567923456039a26a1cfb8bc9ee2431ac2b5de43efce28ef11820a3734dab9fa56db57a1b2fbdc2323036cceeab6ab \
--node-url=node-6-testnet.remme.io
{
"result": {
"data": {
"header": {
"batcher_public_key": "03738df3f4ac3621ba8e89413d3ff4ad036c3a0a4dbb164b695885aab6aab614ad",
"dependencies": [],
"family_name": "consensus_account",
"family_version": "0.1",
"inputs": [
"116829",
"112007",
"0000007ca83d6bbb759da9cde0fb0dec1400c54773f137ea7cfe91e3b0c44298fc1c14",
"0000007ca83d6bbb759da9cde0fb0dec1400c5034223fb6c3e825ee3b0c44298fc1c14",
"0000007ca83d6bbb759da9cde0fb0dec1400c5e64de9aa6a37ac92e3b0c44298fc1c14",
"00b10c0100000000000000000000000000000000000000000000000000000000000000",
"00b10c00",
"fd0e4f0000000000000000000000000000000000000000000000000000000000000000"
],
"nonce": "b8baa6c54ab9463590627c18fb9c10ed",
"outputs": [
"116829",
"112007",
"fd0e4f0000000000000000000000000000000000000000000000000000000000000000"
],
"payload_sha512": "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
"signer_public_key": "03738df3f4ac3621ba8e89413d3ff4ad036c3a0a4dbb164b695885aab6aab614ad"
},
"header_signature": "64d032fbaae9bc59f9e5484ec6f52cbceef567923456039a26a1cfb8bc9ee2431ac2b5de43efce28ef11820a3734dab9fa56db57a1b2fbdc2323036cceeab6ab",
"payload": ""
}
}
}
```

## Development

<h3 id="development-requirements">Requirements</h4>
Expand Down
12 changes: 11 additions & 1 deletion cli/constants.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
"""
Provide constants for command line interface.
"""
from remme.models.utils.family_name import RemmeFamilyName

ADDRESS_REGEXP = r'^[0-9a-f]{70}$'
BATCH_ID_REGEXP = r'^[0-9a-f]{128}$'
PRIVATE_KEY_REGEXP = r'^[a-f0-9]{64}$'
PUBLIC_KEY_REGEXP = r'^[0-9a-f]{66}$'
Alladin9393 marked this conversation as resolved.
Show resolved Hide resolved
PRIVATE_KEY_REGEXP = r'^[a-f0-9]{64}$'
PUBLIC_KEY_ADDRESS_REGEXP = r'^[0-9a-f]{70}$'
HEADER_SIGNATURE_REGEXP = r'^[0-9a-f]{128}$'
TRANSACTION_HEADER_SIGNATURE_REGEXP = r'^[0-9a-f]{128}$'
DOMAIN_NAME_REGEXP = r'(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]'

PASSED_EXIT_FROM_COMMAND_CODE = 0
Expand All @@ -17,6 +20,13 @@

CLI_CONFIG_FILE_NAME = 'remme-core-cli'

FAMILY_NAMES = [
RemmeFamilyName.ACCOUNT.value,
RemmeFamilyName.NODE_ACCOUNT.value,
RemmeFamilyName.PUBLIC_KEY.value,
RemmeFamilyName.SWAP.value,
]
Alladin9393 marked this conversation as resolved.
Show resolved Hide resolved

NODE_IP_ADDRESS_FOR_TESTING = '159.89.104.9'
LATEST_RELEASE_NODE_IP_ADDRESS_FOR_TESTING = '165.22.75.163'
RELEASE_0_9_0_ALPHA_NODE_ADDRESS = '165.227.169.119'
Expand Down
2 changes: 2 additions & 0 deletions cli/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from cli.atomic_swap.cli import atomic_swap_commands
from cli.node.cli import node_commands
from cli.public_key.cli import public_key_commands
from cli.transaction.cli import transaction_command


@click.group()
Expand All @@ -23,3 +24,4 @@ def cli():
cli.add_command(atomic_swap_commands)
cli.add_command(node_commands)
cli.add_command(public_key_commands)
cli.add_command(transaction_command)
63 changes: 63 additions & 0 deletions cli/generic/forms/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
from cli.constants import (
ADDRESS_REGEXP,
DOMAIN_NAME_REGEXP,
FAMILY_NAMES,
PRIVATE_KEY_REGEXP,
PUBLIC_KEY_ADDRESS_REGEXP,
TRANSACTION_HEADER_SIGNATURE_REGEXP,
)


Expand All @@ -36,6 +38,67 @@ def _deserialize(self, value, attr, obj, **kwargs):
return address


class FamilyNameField(fields.Field):
"""
Implements validation of the family name.

References:
- https://marshmallow.readthedocs.io/en/3.0/custom_fields.html
"""

def _deserialize(self, value, attr, obj, **kwargs):
"""
Validate data (family name) that was passed to field.
"""
if value not in FAMILY_NAMES:
raise ValidationError(f'The following family name `{value}` is invalid.')

return value


class TransactionIdentifiersListField(fields.Field):
"""
Implements validation of the list of the identifiers.

References:
- https://marshmallow.readthedocs.io/en/3.0/custom_fields.html
"""

def _deserialize(self, value, attr, obj, **kwargs):
"""
Validate data (list of the identifiers) that was passed to field.
"""
validated_identifiers = []

for identifier in value.split(','):
identifier = identifier.strip()

if re.match(pattern=TRANSACTION_HEADER_SIGNATURE_REGEXP, string=identifier) is None:
raise ValidationError(f'The following identifier `{identifier}` is invalid.')

validated_identifiers.append(identifier)
Alladin9393 marked this conversation as resolved.
Show resolved Hide resolved

return validated_identifiers


class TransactionIdentifierField(fields.Field):
"""
Implements validation of the identifier.

References:
- https://marshmallow.readthedocs.io/en/3.0/custom_fields.html
"""

def _deserialize(self, value, attr, obj, **kwargs):
"""
Validate data (identifier) that was passed to field.
"""
if re.match(pattern=TRANSACTION_HEADER_SIGNATURE_REGEXP, string=value) is None:
raise ValidationError(f'The following identifier `{value}` is invalid.')

return value


class NodeUrlField(fields.Field):
"""
Implements validation of the node URL.
Expand Down
Empty file added cli/transaction/__init__.py
Empty file.
124 changes: 124 additions & 0 deletions cli/transaction/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
"""
Provide implementation of the command line interface's transaction commands.
"""
import sys

import click
from remme import Remme

from cli.constants import (
FAILED_EXIT_FROM_COMMAND_CODE,
NODE_URL_ARGUMENT_HELP_MESSAGE,
)
from cli.transaction.forms import (
GetTransactionForm,
GetTransactionsListForm,
)
from cli.transaction.help import (
TRANSACTION_FAMILY_NAME_ARGUMENT_HELP_MESSAGE,
TRANSACTION_HEAD_ARGUMENT_HELP_MESSAGE,
TRANSACTION_ID_ARGUMENT_HELP_MESSAGE,
TRANSACTION_IDS_ARGUMENT_HELP_MESSAGE,
TRANSACTION_LIMIT_ARGUMENT_HELP_MESSAGE,
TRANSACTION_REVERSE_ARGUMENT_HELP_MESSAGE,
TRANSACTION_START_ARGUMENT_HELP_MESSAGE,
)
from cli.transaction.service import Transaction
from cli.utils import (
default_node_url,
print_errors,
print_result,
)


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


@click.option('--ids', required=False, type=str, help=TRANSACTION_IDS_ARGUMENT_HELP_MESSAGE)
@click.option('--start', required=False, type=str, help=TRANSACTION_START_ARGUMENT_HELP_MESSAGE)
@click.option('--limit', required=False, type=int, help=TRANSACTION_LIMIT_ARGUMENT_HELP_MESSAGE)
@click.option('--head', required=False, type=str, help=TRANSACTION_HEAD_ARGUMENT_HELP_MESSAGE)
@click.option('--reverse', required=False, is_flag=True, help=TRANSACTION_REVERSE_ARGUMENT_HELP_MESSAGE)
@click.option('--family-name', required=False, type=str, help=TRANSACTION_FAMILY_NAME_ARGUMENT_HELP_MESSAGE)
@click.option('--node-url', required=False, type=str, help=NODE_URL_ARGUMENT_HELP_MESSAGE, default=default_node_url())
@transaction_command.command('get-list')
def get_transactions(ids, start, limit, head, reverse, family_name, node_url):
"""
Get a list of transactions.
"""
arguments, errors = GetTransactionsListForm().load({
'ids': ids,
'start': start,
'limit': limit,
'head': head,
'family_name': family_name,
'reverse': reverse,
'node_url': node_url,
})

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

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

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

transactions, errors = Transaction(service=remme).get_list(
transaction_ids=transaction_ids,
start=start,
limit=limit,
head=head,
family_name=family_name,
reverse=reverse,
)

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

print_result(result=transactions)


@click.option('--id', required=True, type=str, help=TRANSACTION_ID_ARGUMENT_HELP_MESSAGE)
@click.option('--node-url', required=False, type=str, help=NODE_URL_ARGUMENT_HELP_MESSAGE, default=default_node_url())
@transaction_command.command('get')
def get_transaction(id, node_url):
"""
Fetch transaction by its identifier.
"""
arguments, errors = GetTransactionForm().load({
'id': id,
'node_url': node_url,
})

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

Alladin9393 marked this conversation as resolved.
Show resolved Hide resolved
transaction_id = arguments.get('id')
node_url = arguments.get('node_url')

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

transaction, errors = Transaction(service=remme).get(transaction_id=transaction_id)

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

print_result(result=transaction)
Loading