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

Add balance changes parser #383

Merged
merged 35 commits into from
Jun 2, 2022
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2376d5d
Add better support for txn flags
LimpidCrypto Mar 15, 2022
973dfbf
support Transaction.has_flag()
LimpidCrypto Mar 15, 2022
8533884
support Transaction.has_flag()
LimpidCrypto Mar 15, 2022
0bfb37d
Add better support for txn flags.
LimpidCrypto Mar 17, 2022
3c1c1a2
bump version; fix import TypedDict
LimpidCrypto Mar 18, 2022
4dc7ed5
Update CHANGELOG.md
LimpidCrypto Mar 18, 2022
b148cf8
All flags to upper case; Update Changelog; Update pyproject
LimpidCrypto Mar 21, 2022
aa9bfa1
All flags to upper case; Update Changelog; Update pyproject
LimpidCrypto Mar 21, 2022
a958b0b
Merge branch 'master' into master
LimpidCrypto Mar 21, 2022
6053562
Merge branch 'XRPLF:master' into master
LimpidCrypto Mar 29, 2022
abc18d8
Merge branch 'XRPLF:master' into master
LimpidCrypto Apr 5, 2022
3e015fe
Merge branch 'XRPLF:master' into master
LimpidCrypto Apr 7, 2022
6a22b04
Merge branch 'XRPLF:master' into master
LimpidCrypto Apr 22, 2022
5439fe7
Merge branch 'XRPLF:master' into master
LimpidCrypto May 3, 2022
5142a3e
Initial commit
LimpidCrypto May 3, 2022
71e3d37
fix lint
LimpidCrypto May 3, 2022
2c1cfa7
export XRPLTxnFieldsException; add TestInvalidTxn; fix nits
LimpidCrypto May 7, 2022
759976d
Update parser
LimpidCrypto May 11, 2022
6106bd1
fix linter
LimpidCrypto May 11, 2022
e93275d
implement suggestions
LimpidCrypto May 11, 2022
285f4e6
fix linter
LimpidCrypto May 11, 2022
53981cc
better handling optional values
LimpidCrypto May 11, 2022
81293fc
implement suggestions
LimpidCrypto May 13, 2022
86beb77
Merge branch 'master' into parse_balance_changes
LimpidCrypto May 15, 2022
e048c89
fix indentation of example txns
LimpidCrypto May 16, 2022
4737f99
fix nits, remove pydash, better typing
LimpidCrypto May 16, 2022
e878849
more readable _flip_trustline_perspective; pass value instead of valu…
LimpidCrypto May 16, 2022
376fcae
Merge branch 'parse_balance_changes' of https://github.com/LimpidCryp…
LimpidCrypto May 16, 2022
5221766
fix type: ignore
LimpidCrypto May 18, 2022
d79a1d4
implement suggestions; remove last type: ignore
LimpidCrypto May 19, 2022
db936ac
Merge branch 'master' into parse_balance_changes
LimpidCrypto May 24, 2022
58c2e24
Merge branch 'master' into parse_balance_changes
LimpidCrypto May 25, 2022
08cf5a2
better typing
LimpidCrypto May 25, 2022
77ac487
Merge branch 'parse_balance_changes' of https://github.com/LimpidCryp…
LimpidCrypto May 25, 2022
600df5d
Merge branch 'master' into parse_balance_changes
LimpidCrypto Jun 1, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [[Unreleased]]
### Added:
- Support for dynamic fee calculation
- Add function to parse account balances from a transaction's metadata

### Fixed
- Resolve `txnNotFound` error with `send_reliable_submission` when waiting for a submitted malformed transaction
Expand Down
1 change: 1 addition & 0 deletions docs/source/xrpl.utils.txn_parser.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:orphan:
1 change: 1 addition & 0 deletions docs/source/xrpl.utils.txn_parser.utils.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:orphan:
58 changes: 57 additions & 1 deletion poetry.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ websockets = [
{version = ">=9.0.1 <11.0", python = ">= 3.7, < 3.10"},
{version = "^10.0", python = "^3.10"}
]
pydash = "^5.1.0"

[tool.poetry.dev-dependencies]
flake8 = "^3.8.4"
Expand Down
Empty file.
22 changes: 22 additions & 0 deletions tests/unit/utils/txn_parser/test_invalid_txn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from __future__ import annotations

from copy import deepcopy
from unittest import TestCase

import xrpl.utils
from tests.unit.utils.txn_parser.transaction import TXN

meta_not_included_txn = deepcopy(TXN)
meta_not_included_txn.pop("meta")
no_nodes_txn = deepcopy(TXN)
no_nodes_txn["meta"].clear()


class TestInvalidTxn(TestCase):
LimpidCrypto marked this conversation as resolved.
Show resolved Hide resolved
def test_meta_not_included(self: TestInvalidTxn):
with self.assertRaises(xrpl.utils.XRPLTxnFieldsException):
xrpl.utils.parse_balance_changes(transaction=meta_not_included_txn)

def test_no_nodes(self: TestInvalidTxn):
with self.assertRaises(xrpl.utils.XRPLTxnFieldsException):
xrpl.utils.parse_balance_changes(transaction=no_nodes_txn)
41 changes: 41 additions & 0 deletions tests/unit/utils/txn_parser/test_parse_balance_changes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from __future__ import annotations

from unittest import TestCase

from tests.unit.utils.txn_parser.transaction import TXN
LimpidCrypto marked this conversation as resolved.
Show resolved Hide resolved
from xrpl.utils import parse_balance_changes


class TestParseBalanceChanges(TestCase):
LimpidCrypto marked this conversation as resolved.
Show resolved Hide resolved
def test(self: TestParseBalanceChanges):
actual = parse_balance_changes(transaction=TXN)
excpected = {
"rwwyrB83G6hS8vp4oLMqwRiMNLWToVCX6L": [
{
"issuer": "rLBnhMjV6ifEHYeV4gaS6jPKerZhQddFxW",
"currency": "5452535259000000000000000000000000000000",
"value": "10",
}
],
"rLBnhMjV6ifEHYeV4gaS6jPKerZhQddFxW": [
{
"issuer": "rwwyrB83G6hS8vp4oLMqwRiMNLWToVCX6L",
"currency": "5452535259000000000000000000000000000000",
"value": "-10",
},
{
"issuer": "rME2LXH8Che2BZRbu5LCRKWju9U3ARaEPd",
"currency": "5452535259000000000000000000000000000000",
"value": "10",
},
],
"rME2LXH8Che2BZRbu5LCRKWju9U3ARaEPd": [
{
"issuer": "rLBnhMjV6ifEHYeV4gaS6jPKerZhQddFxW",
"currency": "5452535259000000000000000000000000000000",
"value": "-10",
},
{"issuer": "", "currency": "XRP", "value": "-0.000012"},
LimpidCrypto marked this conversation as resolved.
Show resolved Hide resolved
],
}
self.assertEqual(first=actual, second=excpected)
LimpidCrypto marked this conversation as resolved.
Show resolved Hide resolved
170 changes: 170 additions & 0 deletions tests/unit/utils/txn_parser/transaction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
TXN = {
LimpidCrypto marked this conversation as resolved.
Show resolved Hide resolved
"Account": "rME2LXH8Che2BZRbu5LCRKWju9U3ARaEPd",
"Amount": {
"currency": "5452535259000000000000000000000000000000",
"issuer": "rLBnhMjV6ifEHYeV4gaS6jPKerZhQddFxW",
"value": "10",
},
"Destination": "rwwyrB83G6hS8vp4oLMqwRiMNLWToVCX6L",
"Fee": "12",
"LastLedgerSequence": 71409597,
"Memos": [
{
"Memo": {
"MemoData": "5472616E73616374696F6E537562547970653A204C6561726E696E67"
}
},
{
"Memo": {
"MemoData": "436F6E67726174756C6174696F6E2066726F6D20746865205"
"4726561737572792041636164656D7920F09F8E89F09F8E93"
}
},
{
"Memo": {
"MemoData": "436F757273653A2050726F7465637420596F757273656C66"
"202623383231313B2054686520696D706F7274616E6365206F662044594F52"
}
},
{
"Memo": {
"MemoData": "4C6573736F6E3A204C6573736F6E20383A20426C61636"
"B686F6C696E67202D204C696D6974696E6720496E666C6174696F6E"
}
},
{
"Memo": {
"MemoData": "596F75722047726164653A2031303025",
}
},
],
"Sequence": 71306845,
"SigningPubKey": "EDD07E10AB5C915FAA3487CAA2CD9A2EE38F5DE869A18FADFC5E154BD4C"
"D349579",
"TransactionType": "Payment",
"TxnSignature": "6BB0F2FBB205571E53C6D05C1E92E5E5A9229BFA81189A32A91BA107E018"
"0D63977871B98DD908DAC0C043B7710050F54AEB3D28920E25D051A51BC27AAA9706",
"date": 704922692,
"hash": "F96C046288B5F0FE743C02C796FF457E4E64726DD935673D9D06ADF628151CEC",
"inLedger": 71409589,
"ledger_index": 71409589,
"meta": {
"AffectedNodes": [
{
"ModifiedNode": {
"FinalFields": {
"Balance": {
"currency": "5452535259000000000000000000000000000000",
"issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji",
"value": "165",
},
"Flags": 1114112,
"HighLimit": {
"currency": "5452535259000000000000000000000000000000",
"issuer": "rLBnhMjV6ifEHYeV4gaS6jPKerZhQddFxW",
"value": "0",
},
"HighNode": "11fd",
"LowLimit": {
"currency": "5452535259000000000000000000000000000000",
"issuer": "rwwyrB83G6hS8vp4oLMqwRiMNLWToVCX6L",
"value": "100000000",
},
"LowNode": "0",
},
"LedgerEntryType": "RippleState",
"LedgerIndex": "1C25C21543238F1CC7776AC096DBF2575B561C39FD40B2"
"D2E270BF81C900D852",
"PreviousFields": {
"Balance": {
"currency": "5452535259000000000000000000000000000000",
"issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji",
"value": "155",
}
},
"PreviousTxnID": "A4C406A1A81D741C79E148E65B94B7613D0BF80EA74"
"7E224EC016AE833A7F91A",
"PreviousTxnLgrSeq": 71404087,
}
},
{
"ModifiedNode": {
"FinalFields": {
"Balance": {
"currency": "5452535259000000000000000000000000000000",
"issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji",
"value": "-60193",
},
"Flags": 2228224,
"HighLimit": {
"currency": "5452535259000000000000000000000000000000",
"issuer": "rME2LXH8Che2BZRbu5LCRKWju9U3ARaEPd",
"value": "99119930.7682357",
},
"HighNode": "0",
"LowLimit": {
"currency": "5452535259000000000000000000000000000000",
"issuer": "rLBnhMjV6ifEHYeV4gaS6jPKerZhQddFxW",
"value": "0",
},
"LowNode": "11ca",
},
"LedgerEntryType": "RippleState",
"LedgerIndex": "7EC1111F3BDB7E27B681A2769F851DB5BC1C7A"
"362624FD9949CB8D9C35CC64F6",
"PreviousFields": {
"Balance": {
"currency": "5452535259000000000000000000000000000000",
"issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji",
"value": "-60203",
}
},
"PreviousTxnID": "5F530DFF08505CB4CAA588799D1305FFC21"
"19889673FBD99290BC66A7087A294",
"PreviousTxnLgrSeq": 71409584,
}
},
{
"ModifiedNode": {
"FinalFields": {
"Account": "rME2LXH8Che2BZRbu5LCRKWju9U3ARaEPd",
"Balance": "14794674",
"Flags": 65536,
"OwnerCount": 1,
"RegularKey": "rLJUjR5L7mtoRc9st3WBotX1yit14C48RL",
"Sequence": 71306846,
},
"LedgerEntryType": "AccountRoot",
"LedgerIndex": "EFA7C1ACD9049645911E6EE1CFC5311054EDBB4"
"FC313603709BE364974227506",
"PreviousFields": {
"Balance": "14794686",
"Sequence": 71306845,
},
"PreviousTxnID": "5F530DFF08505CB4CAA588799D1305FFC2119"
"889673FBD99290BC66A7087A294",
"PreviousTxnLgrSeq": 71409584,
}
},
],
"TransactionIndex": 47,
"TransactionResult": "tesSUCCESS",
"delivered_amount": {
"currency": "5452535259000000000000000000000000000000",
"issuer": "rLBnhMjV6ifEHYeV4gaS6jPKerZhQddFxW",
"value": "10",
},
},
"validated": True,
"warnings": [
{
"id": 1004,
"message": "This is a reporting server. The default behavior of a "
"reporting server is to only return validated data. If you are looking for"
' not yet validated data, include "ledger_index : current" in your'
" request, which will cause this server to forward the request to a p2p"
" node. If the forward is successful the response will include"
' "forwarded" : "true"',
}
],
}
3 changes: 3 additions & 0 deletions xrpl/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
ripple_time_to_datetime,
ripple_time_to_posix,
)
from xrpl.utils.txn_parser import XRPLTxnFieldsException, parse_balance_changes
from xrpl.utils.xrp_conversions import XRPRangeException, drops_to_xrp, xrp_to_drops

__all__ = [
Expand All @@ -23,4 +24,6 @@
"XRPRangeException",
"XRPLTimeRangeException",
"create_cross_chain_payment",
"XRPLTxnFieldsException",
"parse_balance_changes",
]
6 changes: 6 additions & 0 deletions xrpl/utils/txn_parser/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Transaction parser."""

from xrpl.utils.txn_parser.balance_parser import parse_balance_changes
from xrpl.utils.txn_parser.utils import XRPLTxnFieldsException

__all__ = ["parse_balance_changes", "XRPLTxnFieldsException"]
51 changes: 51 additions & 0 deletions xrpl/utils/txn_parser/balance_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Parse balance changes of every account involved in the given transaction."""

from typing import Any, Dict, List, Union, cast

from xrpl.utils.txn_parser.utils import (
RawTxnType,
SubscriptionRawTxnType,
compute_balance_changes,
normalize_nodes,
normalize_transaction,
parse_quantities,
validate_transaction_fields,
)


def parse_balance_changes(
transaction: Union[RawTxnType, SubscriptionRawTxnType],
) -> Dict[str, Any]:
"""
Parse the balance changes of all accounts affected
by the transaction after it occurred.

Args:
transaction: Raw transaction data including the account that
sent the transaction and the metadata.

Returns:
All balance changes.
"""
validate_transaction_fields(transaction_data=transaction)
if "transaction" in transaction:
transaction = cast(SubscriptionRawTxnType, transaction)
transaction = normalize_transaction(transaction_data=transaction)
nodes = normalize_nodes(transaction_data=transaction)
parsedQuantities = parse_quantities(
nodes=nodes, value_parser=compute_balance_changes
)
result: Dict[str, List[Dict[str, str]]] = {}
for address, change in parsedQuantities.items():
result[address] = []
for obj in change:
if isinstance(obj.issuer, tuple):
obj.issuer = obj.issuer[0]
result[address].append(
{
"issuer": obj.issuer,
"currency": obj.currency,
"value": obj.value,
}
)
return result
28 changes: 28 additions & 0 deletions xrpl/utils/txn_parser/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Utils for the transaction parser."""


from xrpl.utils.txn_parser.utils.balance_parser import (
compute_balance_changes,
parse_quantities,
)
from xrpl.utils.txn_parser.utils.transaction import (
normalize_nodes,
normalize_transaction,
validate_transaction_fields,
)
from xrpl.utils.txn_parser.utils.types import (
RawTxnType,
SubscriptionRawTxnType,
XRPLTxnFieldsException,
)

__all__ = [
"parse_quantities",
"compute_balance_changes",
"RawTxnType",
"SubscriptionRawTxnType",
"XRPLTxnFieldsException",
"normalize_nodes",
"normalize_transaction",
"validate_transaction_fields",
]