Skip to content

Commit

Permalink
Merge branch 'amm' into amm-beta
Browse files Browse the repository at this point in the history
  • Loading branch information
khancode committed Sep 15, 2022
2 parents f5b1544 + e9307f5 commit ee005fc
Show file tree
Hide file tree
Showing 12 changed files with 464 additions and 668 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [[Unreleased]]
### Added:
- Support for ExpandedSignerList amendment that expands the maximum signer list to 32 entries
- Function to parse the final account balances from a transaction's metadata
- Function to parse order book changes from a transaction's metadata
- Support for Ed25519 seeds that don't use the `sEd` prefix
- Support for cross-chain bridge proposal
- Support for Automated Market Maker (AMM) transactions and requests as defined in XLS-30.
- Add docs to`get_account_transactions` explaining how to allow pagination through all transaction history [#462]
- Common field `ticket_sequence` to Transaction class

### Fixed:
- Typing for factory classmethods on models
- Use properly encoded transactions in `Sign`, `SignFor`, and `SignAndSubmit`
- Fix Sphinx build errors due to incompatible version bumps

## [1.6.0] - 2022-06-02
### Added:
Expand Down
601 changes: 105 additions & 496 deletions poetry.lock

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ websockets = [
{version = ">=9.0.1 <11.0", python = ">= 3.7, < 3.10"},
{version = "^10.0", python = "^3.10"}
]
Deprecated = "^1.2.13"
types-Deprecated = "^1.2.9"

[tool.poetry.dev-dependencies]
flake8 = "^3.8.4"
Expand All @@ -51,10 +53,12 @@ flake8-isort = "^4.0.0"
flake8-annotations = "2.7.0"
flake8-absolute-import = "^1.0"
darglint = "^1.5.8"
Sphinx = "^3.5.1"
sphinx-rtd-theme = "^0.5.1"
aiounittest = "^1.4.0"
coverage = "^6.4.1"
Jinja2 = "^2.11.3"
MarkupSafe = "2.0.1"
Sphinx = "^5.1.1"

[tool.isort]
# Make sure that isort's settings line up with black
Expand Down
22 changes: 0 additions & 22 deletions tests/unit/core/binarycodec/fixtures/data/codec-fixtures.json
Original file line number Diff line number Diff line change
Expand Up @@ -4694,28 +4694,6 @@
]
}
}
},
{
"binary": "120027220000000024000000185E90C09DE74DB53F9737385AC45039CC1873501CA5333CB4518648524C7B14F15368400000000000000A6D40000000000000056E400000000000000A7321036FB8123857AA5E0CB94CBEDF5E10AAC3AB86B02F988D12B13E4BE4CDF54898D874473045022100F4CD0BC16ADFE1BD1C6C44E720C9F65D028D016677416C049E4F78CC3E8B90AD02204F42BC47CA9166928C2C46F94AC8F446BA21B628BAAAC6D763B116791220D4B181140B9DD29BC414ECC0EB0CBAB7969D360FCD0B0194F015E01C81149A91957F8F16BC57F3F200CD8C98375BF1791586E1F1",
"json": {
"AMMID": "90C09DE74DB53F9737385AC45039CC1873501CA5333CB4518648524C7B14F153",
"Account": "rphRVF5zFGwgMUMzPX1jdnEwfdnCYUoARC",
"AuthAccounts": [
{ "AuthAccount":
{
"Account": "rEaHTti4HZsMBpxTAF4ncWxkcdqDh1h6P7"
}
}
],
"Fee": "10",
"Flags": 0,
"MaxSlotPrice": "10",
"MinSlotPrice": "5",
"Sequence": 24,
"SigningPubKey": "036FB8123857AA5E0CB94CBEDF5E10AAC3AB86B02F988D12B13E4BE4CDF54898D8",
"TransactionType": "AMMBid",
"TxnSignature": "3045022100F4CD0BC16ADFE1BD1C6C44E720C9F65D028D016677416C049E4F78CC3E8B90AD02204F42BC47CA9166928C2C46F94AC8F446BA21B628BAAAC6D763B116791220D4B1"
}
}
],
"ledgerData": [{
Expand Down
133 changes: 133 additions & 0 deletions tests/unit/models/transactions/test_signer_list_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,136 @@ def test_signer_entries_signer_quorum_valid(self):
signer_entries=_SIGNER_ENTRIES_VALID,
)
self.assertTrue(tx.is_valid())

def test_max_signer_entries_above_8_below_32(self):
signers = [
"rBFBipte4nAQCTsRxd2czwvSurhCpAf4X6",
"r3ijUH32iiy9tYNj3rD7hKWYjy1BFUxngm",
"rpwq8vi4Mn3L5kDJmb8Mg59CanPFPzMCnj",
"rB72Gzqfejai46nkA4HaKYBHwAnn2yUoT4",
"rGqsJSAW71pCfUwDD5m52bLw69RzFg6kMW",
"rs8smPRA31Ym4mGxb1wzgwxtU5eVK82Gyk",
"rLrugpGxzezUQLDh7Jv1tZpouuV4MQLbU9",
"rUQ6zLXQdh1jJLGwMXp9P8rgi42kwuafzs",
"rMjY8sPdfxsyRrnVKQcutxr4mTHNXy9dEF",
]
signer_entries = []
for acc in signers:
signer_entries.append(
SignerEntry(
account=acc,
signer_weight=1,
)
)

tx = SignerListSet(
account=_ACCOUNT,
fee=_FEE,
sequence=_SEQUENCE,
signer_quorum=9,
signer_entries=signer_entries,
)
self.assertTrue(tx.is_valid())

def test_max_signer_entries_exceeded(self):
signers = [
"rBFBipte4nAQCTsRxd2czwvSurhCpAf4X6",
"r3ijUH32iiy9tYNj3rD7hKWYjy1BFUxngm",
"rpwq8vi4Mn3L5kDJmb8Mg59CanPFPzMCnj",
"rB72Gzqfejai46nkA4HaKYBHwAnn2yUoT4",
"rGqsJSAW71pCfUwDD5m52bLw69RzFg6kMW",
"rs8smPRA31Ym4mGxb1wzgwxtU5eVK82Gyk",
"rLrugpGxzezUQLDh7Jv1tZpouuV4MQLbU9",
"rUQ6zLXQdh1jJLGwMXp9P8rgi42kwuafzs",
"rMjY8sPdfxsyRrnVKQcutxr4mTHNXy9dEF",
"rUaxYLeFGm6SmMoa2WCqLKSyHwJyvaQmeG",
"r9wUfeVtqMfqrcDTfCpNYbNZvs5q9M9Rpo",
"rQncVNak5kvJGPUFa6fuKH7t8Usjs7Np1c",
"rnwbSSnPbVbUzuBa4etkeYrfy5v7SyhtPu",
"rDXh5D3t48MdBJyXByXq47k5P8Kuf1758B",
"rh1D4jd2mAiqUPHfAZ2cY9Nbfa3kAkaQXP",
"r9T129tXgtnyfGoLeS35c2HctaZAZSQoCH",
"rUd2uKsyCWfJP7Ve36mKoJbNCA7RYThnYk",
"r326x8PaAFtnaH7uoxaKrcDWuwpeHn4wDa",
"rpN3mkXkYhfNadcXPrY4LniM1KpM3egyQM",
"rsPKbR155hz1zrA4pSJp5Y2fxasZAatcHb",
"rsyWFLaEKTpaoSJusjpcDvGexuHCwMnqss",
"rUbc5RXfyF81oLDMgd3d7jpY9YMNMZG4XN",
"rGpYHM88BZe1iVKFHm5xiWYYxR74oxJEXf",
"rPsetWAtR1KxDtxzgHjRMD7Rc87rvXk5nD",
"rwSeNhL6Hi34igr12mCr61jY42psfTkWTq",
"r46Mygy98qjkDhVB6qs4sBnqaf7FPiA2vU",
"r4s8GmeYN4CiwVate1nMUvwMQbundqf5cW",
"rKAr4dQWDYG8cG2hSwJUVp4ry4WNaWiNgp",
"rPWXRLp1vqeUHEH3WiSKuyo9GM9XhaENQU",
"rPgmdBdRKGmndxNEYxUrrsYCZaS6go9RvW",
"rPDJZ9irzgwKRKScfEmuJMvUgrqZAJNCbL",
"rDuU2uSXMfEaoxN1qW8sj7aUNFLGEn3Hr2",
"rsbjSjA4TCB9gtm7x7SrWbZHB6g4tt9CGU",
]
signer_entries = []
for acc in signers:
signer_entries.append(
SignerEntry(
account=acc,
signer_weight=1,
)
)

with self.assertRaises(XRPLModelException):
SignerListSet(
account=_ACCOUNT,
fee=_FEE,
sequence=_SEQUENCE,
signer_quorum=33,
signer_entries=signer_entries,
)

def test_signer_entries_with_wallet_locator(self):
signer_entries = [
SignerEntry(
account="rBFBipte4nAQCTsRxd2czwvSurhCpAf4X6",
signer_weight=1,
wallet_locator="CAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAF"
"ECAFECAFE",
),
SignerEntry(
account="r3ijUH32iiy9tYNj3rD7hKWYjy1BFUxngm",
signer_weight=1,
),
SignerEntry(
account="rpwq8vi4Mn3L5kDJmb8Mg59CanPFPzMCnj",
signer_weight=1,
wallet_locator="0000000000000000000000000000000000000000000000000000000"
"0DEADBEEF",
),
]
tx = SignerListSet(
account=_ACCOUNT,
fee=_FEE,
sequence=_SEQUENCE,
signer_quorum=3,
signer_entries=signer_entries,
)
self.assertTrue(tx.is_valid())

def test_signer_entries_with_invalid_wallet_locator(self):
signer_entries = [
SignerEntry(
account="rBFBipte4nAQCTsRxd2czwvSurhCpAf4X6",
signer_weight=1,
wallet_locator="not_valid",
),
SignerEntry(
account="r3ijUH32iiy9tYNj3rD7hKWYjy1BFUxngm",
signer_weight=1,
),
]
with self.assertRaises(XRPLModelException):
SignerListSet(
account=_ACCOUNT,
fee=_FEE,
sequence=_SEQUENCE,
signer_quorum=2,
signer_entries=signer_entries,
)
43 changes: 43 additions & 0 deletions tests/unit/models/transactions/test_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
_ACCOUNT = "r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ"
_FEE = "0.00001"
_SEQUENCE = 19048
_TICKET_SEQUENCE = 20510
_ACCOUNT_TXN_ID = "66F3D6158CAB6E53405F8C264DB39F07D8D0454433A63DDFB98218ED1BC99B60"


class TestTransaction(TestCase):
Expand Down Expand Up @@ -79,3 +81,44 @@ def test_to_dict_flag_list(self):
expected_flags = 0b111
value = tx.to_dict()["flags"]
self.assertEqual(value, expected_flags)

def test_to_dict_ticket_sequence(self):
tx = Transaction(
account=_ACCOUNT,
fee=_FEE,
ticket_sequence=_TICKET_SEQUENCE,
transaction_type=TransactionType.ACCOUNT_DELETE,
)
value = tx.to_dict()["ticket_sequence"]
self.assertEqual(value, _TICKET_SEQUENCE)

def test_to_dict_ticket_sequence_with_sequence_zero(self):
tx = Transaction(
account=_ACCOUNT,
fee=_FEE,
sequence=0,
ticket_sequence=_TICKET_SEQUENCE,
transaction_type=TransactionType.ACCOUNT_DELETE,
)
value = tx.to_dict()["ticket_sequence"]
self.assertEqual(value, _TICKET_SEQUENCE)

def test_throws_when_ticket_sequence_and_sequence_both_nonzero(self):
with self.assertRaises(XRPLModelException):
Transaction(
account=_ACCOUNT,
fee=_FEE,
sequence=_SEQUENCE,
ticket_sequence=_TICKET_SEQUENCE,
transaction_type=TransactionType.ACCOUNT_DELETE,
)

def test_throws_when_ticket_sequence_and_account_tx_in_both_included(self):
with self.assertRaises(XRPLModelException):
Transaction(
account=_ACCOUNT,
fee=_FEE,
account_txn_id=_ACCOUNT_TXN_ID,
ticket_sequence=_TICKET_SEQUENCE,
transaction_type=TransactionType.ACCOUNT_DELETE,
)
17 changes: 15 additions & 2 deletions xrpl/account/transaction_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import asyncio
from typing import Any, Dict, List

from deprecated.sphinx import deprecated

from xrpl.asyncio.account import transaction_history
from xrpl.clients.sync_client import SyncClient
from xrpl.models.response import Response
Expand All @@ -24,16 +26,24 @@ def get_latest_transaction(account: str, client: SyncClient) -> Response:
return asyncio.run(transaction_history.get_latest_transaction(account, client))


@deprecated(
reason="Sending an AccountTx request directly allows you to page through all"
"results and is just as easy to use.",
version="1.6.0",
)
def get_account_transactions(address: str, client: SyncClient) -> List[Dict[str, Any]]:
"""
Query the ledger for a list of transactions that involved a given account.
To access more than just the first page of results, use the :class:`AccountTx`
request directly.
Args:
address: the account to query.
client: the network client used to make network calls.
Returns:
The transaction history for the address.
The most recent transaction history for the address. For the full history,
page through the :class:`AccountTx` request directly.
Raises:
XRPLRequestFailureException: if the transaction fails.
Expand All @@ -46,13 +56,16 @@ def get_account_payment_transactions(
) -> List[Dict[str, Any]]:
"""
Query the ledger for a list of payment transactions that involved a given account.
To access more than just the first page of results, use the :class:`AccountTx`
request directly then filter for transactions with a "Payment" TransactionType.
Args:
address: the account to query.
client: the network client used to make network calls.
Returns:
The payment transaction history for the address.
The most recent payment transaction history for the address. For the full
history, page through the :class:`AccountTx` request directly.
"""
return asyncio.run(
transaction_history.get_account_payment_transactions(address, client)
Expand Down
23 changes: 19 additions & 4 deletions xrpl/asyncio/account/transaction_history.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""High-level methods to obtain information about account transaction history."""
from typing import Any, Dict, List, cast

from deprecated.sphinx import deprecated

from xrpl.asyncio.clients import Client, XRPLRequestFailureException
from xrpl.core.addresscodec import is_valid_xaddress, xaddress_to_classic_address
from xrpl.models.requests import AccountTx
Expand Down Expand Up @@ -32,18 +34,27 @@ async def get_latest_transaction(account: str, client: Client) -> Response:
return response


@deprecated(
reason="Sending an AccountTx request directly allows you to page through all"
"results and is just as easy to use.",
version="1.6.0",
)
async def get_account_transactions(
address: str, client: Client
address: str,
client: Client,
) -> List[Dict[str, Any]]:
"""
Query the ledger for a list of transactions that involved a given account.
To access more than just the first page of results, use the :class:`AccountTx`
request directly.
Args:
address: the account to query.
client: the network client used to make network calls.
Returns:
The transaction history for the address.
The most recent transaction history for the address. For the full history,
page through the :class:`AccountTx` request directly.
Raises:
XRPLRequestFailureException: if the transaction fails.
Expand All @@ -58,17 +69,21 @@ async def get_account_transactions(


async def get_account_payment_transactions(
address: str, client: Client
address: str,
client: Client,
) -> List[Dict[str, Any]]:
"""
Query the ledger for a list of payment transactions that involved a given account.
To access more than just the first page of results, use the :class:`AccountTx`
request directly then filter for transactions with a "Payment" TransactionType.
Args:
address: the account to query.
client: the network client used to make network calls.
Returns:
The payment transaction history for the address.
The most page of payment transaction history for the address. For the full
history, page through the :class:`AccountTx` request directly.
"""
all_transactions = await get_account_transactions(address, client)
return [tx for tx in all_transactions if tx["tx"]["TransactionType"] == "Payment"]
Loading

0 comments on commit ee005fc

Please sign in to comment.