Skip to content
Merged
Show file tree
Hide file tree
Changes from 74 commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
8c1f795
update definitions.json
mvadari Oct 2, 2024
ea28bc4
update scripts after rippled refactor
mvadari Oct 2, 2024
dbedfdc
add LedgerStateFix
mvadari Oct 2, 2024
703f4c8
add basic batch models
mvadari Oct 2, 2024
429d6fc
add autofill
mvadari Oct 3, 2024
2677584
add autofill tests
mvadari Oct 3, 2024
b79c7f7
fix multisign issue, add test
mvadari Oct 3, 2024
2443f4c
rename some tests
mvadari Oct 10, 2024
3fa2294
fix multisign so tests pass
mvadari Oct 10, 2024
5a000f7
improve typing
mvadari Oct 10, 2024
76d3666
improve tests, fix more issues
mvadari Oct 10, 2024
5e7bc74
more cleanup
mvadari Oct 10, 2024
68ba657
more typing improvements
mvadari Oct 10, 2024
7aae9d8
update changelog
mvadari Oct 10, 2024
786e156
add binary codec batch encoding
mvadari Oct 10, 2024
1a8939d
add multi-account batch signing helper function
mvadari Oct 10, 2024
c5ea66c
add batch signer combine function
mvadari Oct 10, 2024
41fbe40
move to transaction
mvadari Oct 10, 2024
eb0d88b
add tests, fix issues
mvadari Oct 10, 2024
ca6caec
fix typing issue
mvadari Oct 10, 2024
d3da22a
fix tests
mvadari Oct 10, 2024
c441795
Update main.py
mvadari Oct 10, 2024
a2dca0e
Merge branch 'main' into batch
mvadari Oct 25, 2024
2378081
Merge branch 'main' into batch
mvadari Nov 4, 2024
27a822f
Merge branch 'main' into batch
mvadari Nov 7, 2024
d2119e1
remove BatchTxn field
mvadari Nov 7, 2024
f9cbea7
fix tests
mvadari Nov 7, 2024
7d842c6
fix unrelated TicketSequence bug
mvadari Nov 7, 2024
2a632cf
improve autofilling
mvadari Nov 7, 2024
6f1cbed
better flag handling
mvadari Nov 7, 2024
8ca1005
update changelog
mvadari Nov 7, 2024
77fc6e1
fix integration tests
mvadari Nov 7, 2024
0792b3e
handle batch in batch
mvadari Nov 7, 2024
a2890a9
get working integration test
mvadari Nov 8, 2024
6ff9c60
Merge branch 'main' into batch
mvadari Dec 11, 2024
f29bc15
Merge branch 'main' into batch
mvadari Dec 13, 2024
be36119
Merge branch 'main' into batch
mvadari Dec 20, 2024
4157762
Merge branch 'main' into batch
mvadari Jan 2, 2025
a637da3
rename field
mvadari Jan 2, 2025
8be504d
more renames
mvadari Jan 2, 2025
eb4124d
Merge
mvadari Feb 7, 2025
74cdbb9
Merge branch 'main' into batch
mvadari Feb 10, 2025
b130d83
remove transaction_ids
mvadari Feb 10, 2025
2b444e2
fix tests
mvadari Feb 10, 2025
25084c0
Merge branch 'main' into batch
mvadari Feb 11, 2025
874d4f5
add multisign test
mvadari Feb 12, 2025
3dd191c
Merge branch 'main' into batch
mvadari Feb 18, 2025
af5eccf
Merge branch 'main' into batch
mvadari Mar 18, 2025
038b5ee
Merge branch 'main' into batch
mvadari Mar 19, 2025
dbdc0c9
remove debug lines
mvadari Apr 1, 2025
81b600e
remove LedgerStateFix
mvadari Apr 1, 2025
e406f5b
respond to comments
mvadari Apr 9, 2025
bff059e
fix linting issue
mvadari Apr 9, 2025
355e806
improve tfInnerBatchTxn stuff
mvadari Apr 10, 2025
d20a616
Merge branch 'main' into batch
mvadari Apr 15, 2025
2d31fd9
fix definitions
mvadari Apr 17, 2025
1cb3025
respond to comments
mvadari Apr 17, 2025
d25b35f
Merge branch 'main' into batch
mvadari May 8, 2025
4d8cdc8
remove debug statement
mvadari May 20, 2025
134f7d4
update definitions
mvadari May 20, 2025
db3bf5f
Merge branch 'main' into batch
mvadari May 20, 2025
10050f0
fix flag handling
mvadari May 20, 2025
d53dc58
fix FlagInterfaces
mvadari May 20, 2025
b296815
Merge branch 'main' into batch
mvadari May 20, 2025
9717619
fix changelog
mvadari May 20, 2025
a833012
add Batch to non-delegable txs, clean up
mvadari May 20, 2025
4c19e62
fix definitions, update amendments in config
mvadari May 27, 2025
e7b2a57
fix test
mvadari May 27, 2025
c322632
Merge branch 'main' into batch
mvadari Jun 4, 2025
8182f48
Merge branch 'main' into batch
mvadari Jun 5, 2025
bac28c0
fix changelog
mvadari Jun 5, 2025
2496176
clean up changelog
mvadari Jun 5, 2025
7e87781
more changelog cleanup
mvadari Jun 5, 2025
cd03c6f
fix typing
mvadari Jun 5, 2025
10a3775
clean up
mvadari Jun 5, 2025
78a8a7e
Merge branch 'main' into batch
mvadari Jun 5, 2025
01ab82f
fix tests
mvadari Jun 5, 2025
876b91a
respond to comments
mvadari Jun 5, 2025
fa78532
Merge branch 'main' into batch
mvadari Jun 5, 2025
4389b5c
fix issues
mvadari Jun 5, 2025
b6644cf
remove bad test, improve fee calculation
mvadari Jun 5, 2025
e1dc2b0
remove unneeded code
mvadari Jun 5, 2025
1eb5234
respond to comments
mvadari Jun 6, 2025
341d91a
fix tests
mvadari Jun 6, 2025
a144e60
fix multisig fee calculations
mvadari Jun 6, 2025
ccb0446
Merge branch 'main' into batch
mvadari Jun 6, 2025
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
10 changes: 7 additions & 3 deletions .ci-config/rippled.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -183,20 +183,24 @@ fixEmptyDID
fixXChainRewardRounding
fixPreviousTxnID
# 2.3.0 Amendments
fixAMMv1_1
fixAMMv1_2
AMMClawback
InvariantsV1_1
Credentials
NFTokenMintOffer
MPTokensV1
fixAMMv1_2
fixNFTokenPageLinks
fixInnerObjTemplate2
fixEnforceNFTokenTrustline
fixReducedOffersV2
# 2.4.0 Amendments
DeepFreeze
DynamicNFT
PermissionedDomains
fixFrozenLPTokenTransfer
fixInvalidTxFlags
# 2.5.0 Amendments
PermissionDelegation
Batch

# This section can be used to simulate various FeeSettings scenarios for rippled node in standalone mode
[voting]
Expand Down
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
"aiounittest",
"altnet",
"asyncio",
"autofilling",
"autofills",
"binarycodec",
"Clawback",
"isnumeric",
"keypair",
"keypairs",
"multiaccount",
"multisign",
"multisigned",
"multisigning",
"nftoken",
"PATHSET",
"rippletest",
Expand Down
16 changes: 10 additions & 6 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]]

### Fixed
- add `MPTCurrency` support in `Issue` (rippled internal type)
- Fixed the implementation error in get_latest_open_ledger_sequence method. The change uses the "current" ledger for extracting sequence number.
- Increase default maximum payload size for websocket client
- Fixed the default behavior of flags field when preparing transactions. By default, flags are not part of the transaction if not explicitly provided.

### Added
- Improved validation for models to also check param types
- Support for `Account Permission` and `Account Permission Delegation` (XLS-74d, XLS-75d)
- Support for the `Batch` amendment (XLS-56d)

### Fixed
- Add `MPTCurrency` support in `Issue` (rippled internal type)
- Fixed the implementation error in get_latest_open_ledger_sequence method. The change uses the "current" ledger for extracting sequence number
- Increase default maximum payload size for websocket client
- Fixed the default behavior of flags field when preparing transactions. By default, flags are not part of the transaction if not explicitly provided
- Handle autofilling better when multisigning transactions
- Improve typing for transaction-related helper functions
- Improve handling of `TicketSequence`

## [4.1.0] - 2025-2-13

Expand Down
4 changes: 2 additions & 2 deletions tests/integration/it_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def fund_wallet(wallet: Wallet) -> None:
destination=wallet.address,
amount=FUNDING_AMOUNT,
)
sign_and_submit(payment, client, MASTER_WALLET, check_fee=True)
sign_and_submit(payment, client, MASTER_WALLET)
client.request(LEDGER_ACCEPT_REQUEST)


Expand All @@ -122,7 +122,7 @@ async def fund_wallet_async(
destination=wallet.address,
amount=FUNDING_AMOUNT,
)
await sign_and_submit_async(payment, client, MASTER_WALLET, check_fee=True)
await sign_and_submit_async(payment, client, MASTER_WALLET)
await client.request(LEDGER_ACCEPT_REQUEST)


Expand Down
42 changes: 41 additions & 1 deletion tests/integration/sugar/test_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
)
from tests.integration.reusable_values import DESTINATION as DESTINATION_WALLET
from tests.integration.reusable_values import WALLET
from xrpl.asyncio.account import get_next_valid_seq_number
from xrpl.asyncio.ledger import get_fee, get_latest_validated_ledger_sequence
from xrpl.asyncio.transaction import (
XRPLReliableSubmissionException,
Expand All @@ -24,7 +25,15 @@
from xrpl.models.amounts.issued_currency_amount import IssuedCurrencyAmount
from xrpl.models.exceptions import XRPLException
from xrpl.models.requests import ServerState, Tx
from xrpl.models.transactions import AccountDelete, AccountSet, EscrowFinish, Payment
from xrpl.models.transactions import (
AccountDelete,
AccountSet,
Batch,
DepositPreauth,
EscrowFinish,
Payment,
TransactionFlag,
)
from xrpl.utils import xrp_to_drops

ACCOUNT = WALLET.address
Expand Down Expand Up @@ -326,6 +335,37 @@ async def test_simulate(self, client):
self.assertEqual(response.result["engine_result_code"], 0)
self.assertFalse(response.result["applied"])

@test_async_and_sync(
globals(),
["xrpl.transaction.autofill", "xrpl.account.get_next_valid_seq_number"],
)
async def test_batch_autofill(self, client):
tx = Batch(
account="rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
raw_transactions=[
DepositPreauth(
account=WALLET.address,
authorize="rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
),
DepositPreauth(
account=WALLET.address,
authorize="rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
),
],
)
transaction = await autofill(tx, client)

sequence = await get_next_valid_seq_number(WALLET.address, client)
for i in range(len(transaction.raw_transactions)):
raw_tx = transaction.raw_transactions[i]
self.assertTrue(raw_tx.has_flag(TransactionFlag.TF_INNER_BATCH_TXN))
self.assertEqual(raw_tx.sequence, sequence + i)
self.assertEqual(raw_tx.network_id, 63456)
self.assertIsNone(raw_tx.last_ledger_sequence)
self.assertEqual(raw_tx.fee, "0")
self.assertEqual(raw_tx.signing_pub_key, "")
self.assertEqual(raw_tx.txn_signature, None)


class TestSubmitAndWait(IntegrationTestCase):
@test_async_and_sync(
Expand Down
51 changes: 51 additions & 0 deletions tests/integration/transactions/test_batch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from tests.integration.integration_test_case import IntegrationTestCase
from tests.integration.it_utils import (
sign_and_reliable_submission_async,
test_async_and_sync,
)
from tests.integration.reusable_values import DESTINATION, WALLET
from xrpl.asyncio.transaction import autofill
from xrpl.models import Batch, BatchFlag, Payment
from xrpl.models.response import ResponseStatus
from xrpl.transaction.batch_signers import sign_multiaccount_batch


class TestBatch(IntegrationTestCase):
@test_async_and_sync(globals())
async def test_basic_functionality(self, client):
payment = Payment(
account=WALLET.address,
amount="1",
destination=DESTINATION.address,
)
batch = Batch(
account=WALLET.address,
flags=BatchFlag.TF_ALL_OR_NOTHING,
raw_transactions=[payment, payment],
)
response = await sign_and_reliable_submission_async(batch, WALLET, client)
self.assertEqual(response.status, ResponseStatus.SUCCESS)
self.assertEqual(response.result["engine_result"], "tesSUCCESS")

@test_async_and_sync(globals(), ["xrpl.transaction.autofill"])
async def test_multisign(self, client):
payment = Payment(
account=WALLET.address,
amount="1",
destination=DESTINATION.address,
)
payment2 = Payment(
account=DESTINATION.address,
amount="1",
destination=WALLET.address,
)
batch = Batch(
account=WALLET.address,
flags=BatchFlag.TF_ALL_OR_NOTHING,
raw_transactions=[payment, payment2],
)
autofilled = await autofill(batch, client, 2)
signed = sign_multiaccount_batch(DESTINATION, autofilled)
response = await sign_and_reliable_submission_async(signed, WALLET, client)
self.assertEqual(response.status, ResponseStatus.SUCCESS)
self.assertEqual(response.result["engine_result"], "tesSUCCESS")
27 changes: 27 additions & 0 deletions tests/unit/core/binarycodec/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
encode,
encode_for_multisigning,
encode_for_signing,
encode_for_signing_batch,
encode_for_signing_claim,
)

Expand Down Expand Up @@ -401,6 +402,32 @@ def test_claim(self):
)
self.assertEqual(encode_for_signing_claim(json), expected)

def test_batch(self):
flags = 1
transaction_ids = [
"ABE4871E9083DF66727045D49DEEDD3A6F166EB7F8D1E92FE868F02E76B2C5CA",
"795AAC88B59E95C3497609749127E69F12958BC016C600C770AEEB1474C840B4",
]

json = {"flags": flags, "transaction_ids": transaction_ids}
actual = encode_for_signing_batch(json)
self.assertEqual(
actual,
"".join(
[
# hash prefix
"42434800",
# flags
"00000001",
# transaction_ids length
"00000002",
# transaction_ids
"ABE4871E9083DF66727045D49DEEDD3A6F166EB7F8D1E92FE868F02E76B2C5CA",
"795AAC88B59E95C3497609749127E69F12958BC016C600C770AEEB1474C840B4",
]
),
)

def test_multisig(self):
signing_account = "rJZdUusLDtY9NEsGea7ijqhVrXv98rYBYN"
multisig_json = {**signing_json, "SigningPubKey": ""}
Expand Down
27 changes: 27 additions & 0 deletions tests/unit/models/transactions/test_batch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from unittest import TestCase

from xrpl.models import Batch, BatchFlag, Payment, TransactionFlag

_ACCOUNT = "r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ"
_DESTINATION = "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg"


class TestBatch(TestCase):
def test_basic(self):
payment = Payment(
account=_ACCOUNT,
amount="1",
destination=_DESTINATION,
)
batch = Batch(
account=_ACCOUNT,
flags=BatchFlag.TF_ALL_OR_NOTHING,
raw_transactions=[payment, payment],
)
self.assertTrue(batch.is_valid())
self.assertTrue(
batch.raw_transactions[0].has_flag(TransactionFlag.TF_INNER_BATCH_TXN)
)
self.assertTrue(
batch.raw_transactions[1].has_flag(TransactionFlag.TF_INNER_BATCH_TXN)
)
4 changes: 2 additions & 2 deletions tests/unit/models/transactions/test_delegate_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def test_account_and_delegate_are_the_same(self):
+ "'}",
)

def test_non_delegatable_transactions(self):
def test_non_delegable_transactions(self):
with self.assertRaises(XRPLModelException) as error:
DelegateSet(
account=_ACCOUNT,
Expand All @@ -109,6 +109,6 @@ def test_non_delegatable_transactions(self):
)
self.assertEqual(
error.exception.args[0],
"{'permissions': \"Non-delegatable transactions found in `permissions` "
"{'permissions': \"Non-delegable transactions found in `permissions` "
"list: {<TransactionType.ACCOUNT_DELETE: 'AccountDelete'>}.\"}",
)
43 changes: 30 additions & 13 deletions tests/unit/models/transactions/test_transaction.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from unittest import TestCase

from xrpl.asyncio.transaction.main import sign
from xrpl.core.addresscodec.main import classic_address_to_xaddress
from xrpl.models.exceptions import XRPLModelException
from xrpl.models.transactions import AccountSet, OfferCreate, Payment
from xrpl.models.transactions import AccountSet, DepositPreauth, OfferCreate, Payment
from xrpl.models.transactions.transaction import Transaction
from xrpl.models.transactions.types.transaction_type import TransactionType
from xrpl.transaction.multisign import multisign
Expand Down Expand Up @@ -158,12 +159,28 @@ def test_is_signed_for_multisigned_transaction(self):
multisigned_tx = multisign(tx, [tx_1, tx_2])
self.assertTrue(multisigned_tx.is_signed())

def test_multisigned_transaction_xaddress(self):
tx = DepositPreauth(
account=classic_address_to_xaddress(_WALLET.address, 1, False),
authorize=classic_address_to_xaddress(_ACCOUNT, 1, False),
)
tx_1 = sign(tx, _FIRST_SIGNER, multisign=True)
tx_2 = sign(tx, _SECOND_SIGNER, multisign=True)

for tx_signed in (tx_1, tx_2):
self.assertEqual(tx_signed.account, _WALLET.address)
self.assertEqual(tx_signed.source_tag, 1)
self.assertEqual(tx_signed.authorize, _ACCOUNT)

multisigned_tx = multisign(tx, [tx_1, tx_2])
self.assertTrue(multisigned_tx.is_signed())

# test the usage of DeliverMax field in Payment transactions
def test_payment_txn_API_no_deliver_max(self):
def test_payment_txn_api_no_deliver_max(self):
delivered_amount = "200000"
payment_tx_json = {
"Account": "rGWTUVmm1fB5QUjMYn8KfnyrFNgDiD9H9e",
"Destination": "rw71Qs1UYQrSQ9hSgRohqNNQcyjCCfffkQ",
"Account": _WALLET.address,
"Destination": _ACCOUNT,
"TransactionType": "Payment",
"Amount": delivered_amount,
"Fee": "15",
Expand All @@ -175,11 +192,11 @@ def test_payment_txn_API_no_deliver_max(self):
payment_txn = Payment.from_xrpl(payment_tx_json)
self.assertEqual(delivered_amount, payment_txn.to_dict()["amount"])

def test_payment_txn_API_no_amount(self):
def test_payment_txn_api_no_amount(self):
delivered_amount = "200000"
payment_tx_json = {
"Account": "rGWTUVmm1fB5QUjMYn8KfnyrFNgDiD9H9e",
"Destination": "rw71Qs1UYQrSQ9hSgRohqNNQcyjCCfffkQ",
"Account": _WALLET.address,
"Destination": _ACCOUNT,
"TransactionType": "Payment",
"DeliverMax": delivered_amount,
"Fee": "15",
Expand All @@ -191,10 +208,10 @@ def test_payment_txn_API_no_amount(self):
payment_txn = Payment.from_xrpl(payment_tx_json)
self.assertEqual(delivered_amount, payment_txn.to_dict()["amount"])

def test_payment_txn_API_different_amount_and_deliver_max(self):
def test_payment_txn_api_different_amount_and_deliver_max(self):
payment_tx_json = {
"Account": "rGWTUVmm1fB5QUjMYn8KfnyrFNgDiD9H9e",
"Destination": "rw71Qs1UYQrSQ9hSgRohqNNQcyjCCfffkQ",
"Account": _WALLET.address,
"Destination": _ACCOUNT,
"TransactionType": "Payment",
"DeliverMax": "200000",
"Amount": "200010",
Expand All @@ -207,11 +224,11 @@ def test_payment_txn_API_different_amount_and_deliver_max(self):
with self.assertRaises(XRPLModelException):
Payment.from_xrpl(payment_tx_json)

def test_payment_txn_API_identical_amount_and_deliver_max(self):
def test_payment_txn_api_identical_amount_and_deliver_max(self):
delivered_amount = "200000"
payment_tx_json = {
"Account": "rGWTUVmm1fB5QUjMYn8KfnyrFNgDiD9H9e",
"Destination": "rw71Qs1UYQrSQ9hSgRohqNNQcyjCCfffkQ",
"Account": _WALLET.address,
"Destination": _ACCOUNT,
"TransactionType": "Payment",
"DeliverMax": delivered_amount,
"Amount": delivered_amount,
Expand Down
Empty file.
Loading