From 79b5bc8fd3b060dda1970a97d44c080f5befd26a Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 10 Mar 2025 18:01:33 -0400 Subject: [PATCH 01/32] basics --- xrpl/asyncio/transaction/main.py | 3 +++ xrpl/models/transactions/escrow_create.py | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/xrpl/asyncio/transaction/main.py b/xrpl/asyncio/transaction/main.py index a9f0f6f9c..029be2a15 100644 --- a/xrpl/asyncio/transaction/main.py +++ b/xrpl/asyncio/transaction/main.py @@ -479,6 +479,9 @@ async def _calculate_fee_per_transaction_type( # BaseFee × (33 + (Fulfillment size in bytes / 16)) base_fee = math.ceil(net_fee * (33 + (len(fulfillment_bytes) / 16))) + if transaction.transaction_type == TransactionType.ESCROW_CANCEL: + base_fee += 1000 + # AccountDelete Transaction if transaction.transaction_type in ( TransactionType.ACCOUNT_DELETE, diff --git a/xrpl/models/transactions/escrow_create.py b/xrpl/models/transactions/escrow_create.py index 3d564ed53..59bea4867 100644 --- a/xrpl/models/transactions/escrow_create.py +++ b/xrpl/models/transactions/escrow_create.py @@ -67,6 +67,10 @@ class EscrowCreate(Transaction): fulfilled. """ + finish_function: Optional[str] = None + + data: Optional[str] = None + transaction_type: TransactionType = field( default=TransactionType.ESCROW_CREATE, init=False, @@ -82,5 +86,14 @@ def _get_errors(self: Self) -> Dict[str, str]: errors["EscrowCreate"] = ( "The finish_after time must be before the cancel_after time." ) + if ( + self.cancel_after is None + and self.condition is None + and self.finish_function is None + ): + errors["EscrowCreate"] = ( + "At least one of cancel_after, condition, or finish_function must be " + "set." + ) return errors From db9234b0676db0f80ac3ccb5da9f9e5c1cd32e33 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 11 Mar 2025 14:02:18 -0400 Subject: [PATCH 02/32] add tests, fix issues, refactor escrow tests --- tests/integration/it_utils.py | 43 +----- tests/integration/transactions/test_escrow.py | 135 ++++++++++++++++++ .../transactions/test_escrow_cancel.py | 27 ---- .../transactions/test_escrow_create.py | 38 ----- .../transactions/test_escrow_finish.py | 38 ----- xrpl/asyncio/transaction/main.py | 7 +- .../binarycodec/definitions/definitions.json | 31 ++++ xrpl/models/transactions/escrow_create.py | 4 +- 8 files changed, 178 insertions(+), 145 deletions(-) create mode 100644 tests/integration/transactions/test_escrow.py delete mode 100644 tests/integration/transactions/test_escrow_cancel.py delete mode 100644 tests/integration/transactions/test_escrow_create.py delete mode 100644 tests/integration/transactions/test_escrow_finish.py diff --git a/tests/integration/it_utils.py b/tests/integration/it_utils.py index ebd2e2861..79856ffdc 100644 --- a/tests/integration/it_utils.py +++ b/tests/integration/it_utils.py @@ -3,7 +3,6 @@ import asyncio import importlib import inspect -from threading import Timer as ThreadingTimer from time import sleep from typing import Any, Dict, cast @@ -14,7 +13,7 @@ from xrpl.clients import Client, JsonRpcClient, WebsocketClient from xrpl.clients.sync_client import SyncClient from xrpl.constants import CryptoAlgorithm -from xrpl.models import GenericRequest, Payment, Request, Response, Transaction +from xrpl.models import GenericRequest, Payment, Response, Transaction from xrpl.models.amounts.issued_currency_amount import IssuedCurrencyAmount from xrpl.models.currencies.issued_currency import IssuedCurrency from xrpl.models.currencies.xrp import XRP @@ -69,40 +68,6 @@ LEDGER_ACCEPT_TIME = 0.1 -class AsyncTestTimer: - def __init__( - self, - client: AsyncClient, - delay: float = LEDGER_ACCEPT_TIME, - request: Request = LEDGER_ACCEPT_REQUEST, - ): - self._client = client - self._delay = delay - self._request = request - self._task = asyncio.ensure_future(self._job()) - - async def _job(self): - await asyncio.sleep(self._delay) - await self._client.request(self._request) - - def cancel(self): - self._task.cancel() - - -class SyncTestTimer: - def __init__( - self, - client: SyncClient, - delay: float = LEDGER_ACCEPT_TIME, - request: Request = LEDGER_ACCEPT_REQUEST, - ): - self._timer = ThreadingTimer(delay, client.request, (request,)) - self._timer.start() - - def cancel(self): - self._timer.cancel() - - def fund_wallet(wallet: Wallet) -> None: client = JSON_RPC_CLIENT payment = Payment( @@ -232,7 +197,8 @@ def accept_ledger( delay: float for how many seconds to wait before accepting ledger. """ client = _choose_client(use_json_client) - SyncTestTimer(client, delay) + sleep(delay) + client.request(LEDGER_ACCEPT_REQUEST) async def accept_ledger_async( @@ -247,7 +213,8 @@ async def accept_ledger_async( delay: float for how many seconds to wait before accepting ledger. """ client = _choose_client_async(use_json_client) - AsyncTestTimer(client, delay) + await asyncio.sleep(delay) + await client.request(LEDGER_ACCEPT_REQUEST) def _choose_client(use_json_client: bool) -> SyncClient: diff --git a/tests/integration/transactions/test_escrow.py b/tests/integration/transactions/test_escrow.py new file mode 100644 index 000000000..d99cfe302 --- /dev/null +++ b/tests/integration/transactions/test_escrow.py @@ -0,0 +1,135 @@ +from tests.integration.integration_test_case import IntegrationTestCase +from tests.integration.it_utils import ( + accept_ledger_async, + sign_and_reliable_submission_async, + test_async_and_sync, +) +from tests.integration.reusable_values import DESTINATION, WALLET +from xrpl.models import EscrowCancel, EscrowCreate, EscrowFinish, Ledger +from xrpl.models.response import ResponseStatus + +ACCOUNT = WALLET.address + +AMOUNT = "10000" +CONDITION = ( + "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100" +) +DESTINATION_TAG = 23480 +SOURCE_TAG = 11747 + +FINISH_FUNCTION = ( + "0061736d010000000105016000017f021b0108686f73745f6c69620e6765745f6c" + "65646765725f73716e0000030201000405017001010105030100100619037f0141" + "8080c0000b7f00418080c0000b7f00418080c0000b072d04066d656d6f72790200" + "05726561647900010a5f5f646174615f656e6403010b5f5f686561705f62617365" + "03020a0d010b0010808080800041044a0b006e046e616d65000e0d7761736d5f6c" + "69622e7761736d01430200395f5a4e387761736d5f6c696238686f73745f6c6962" + "31346765745f6c65646765725f73716e3137686663383539386237646539633036" + "64624501057265616479071201000f5f5f737461636b5f706f696e746572005509" + "70726f64756365727302086c616e6775616765010452757374000c70726f636573" + "7365642d62790105727573746325312e38332e302d6e696768746c792028633266" + "37346333663920323032342d30392d30392900490f7461726765745f6665617475" + "726573042b0a6d756c746976616c75652b0f6d757461626c652d676c6f62616c73" + "2b0f7265666572656e63652d74797065732b087369676e2d657874" +) + + +class TestEscrow(IntegrationTestCase): + @test_async_and_sync(globals()) + async def test_all_fields_cancel(self, client): + ledger = await client.request(Ledger(ledger_index="validated")) + close_time = ledger.result["ledger"]["close_time"] + escrow_create = EscrowCreate( + account=ACCOUNT, + amount=AMOUNT, + destination=DESTINATION.classic_address, + destination_tag=DESTINATION_TAG, + cancel_after=close_time + 3, + finish_after=close_time + 2, + source_tag=SOURCE_TAG, + ) + response = await sign_and_reliable_submission_async( + escrow_create, WALLET, client + ) + self.assertEqual(response.status, ResponseStatus.SUCCESS) + self.assertEqual(response.result["engine_result"], "tesSUCCESS") + sequence = response.result["tx_json"]["Sequence"] + # TODO: check account_objects + + for _ in range(4): + await accept_ledger_async() + + escrow_cancel = EscrowCancel( + account=ACCOUNT, + owner=ACCOUNT, + offer_sequence=sequence, + ) + response = await sign_and_reliable_submission_async( + escrow_cancel, WALLET, client + ) + self.assertEqual(response.status, ResponseStatus.SUCCESS) + self.assertEqual(response.result["engine_result"], "tesSUCCESS") + + @test_async_and_sync(globals()) + async def test_all_fields_finish(self, client): + ledger = await client.request(Ledger(ledger_index="validated")) + close_time = ledger.result["ledger"]["close_time"] + escrow_create = EscrowCreate( + account=ACCOUNT, + amount=AMOUNT, + destination=DESTINATION.classic_address, + destination_tag=DESTINATION_TAG, + finish_after=close_time + 2, + source_tag=SOURCE_TAG, + ) + response = await sign_and_reliable_submission_async( + escrow_create, WALLET, client + ) + self.assertEqual(response.status, ResponseStatus.SUCCESS) + self.assertEqual(response.result["engine_result"], "tesSUCCESS") + sequence = response.result["tx_json"]["Sequence"] + # TODO: check account_objects + + for _ in range(4): + await accept_ledger_async() + + escrow_finish = EscrowFinish( + account=ACCOUNT, + owner=ACCOUNT, + offer_sequence=sequence, + ) + response = await sign_and_reliable_submission_async( + escrow_finish, WALLET, client + ) + self.assertEqual(response.status, ResponseStatus.SUCCESS) + self.assertEqual(response.result["engine_result"], "tesSUCCESS") + + @test_async_and_sync(globals()) + async def test_finish_function(self, client): + ledger = await client.request(Ledger(ledger_index="validated")) + close_time = ledger.result["ledger"]["close_time"] + escrow_create = EscrowCreate( + account=ACCOUNT, + amount=AMOUNT, + destination=DESTINATION.classic_address, + finish_function=FINISH_FUNCTION, + cancel_after=close_time + 200, + ) + response = await sign_and_reliable_submission_async( + escrow_create, WALLET, client + ) + self.assertEqual(response.status, ResponseStatus.SUCCESS) + self.assertEqual(response.result["engine_result"], "tesSUCCESS") + sequence = response.result["tx_json"]["Sequence"] + # TODO: check account_objects + + escrow_finish = EscrowFinish( + account=ACCOUNT, + owner=ACCOUNT, + offer_sequence=sequence, + ) + response = await sign_and_reliable_submission_async( + escrow_finish, WALLET, client + ) + self.assertEqual(response.status, ResponseStatus.SUCCESS) + self.assertEqual(response.result["engine_result"], "tesSUCCESS") diff --git a/tests/integration/transactions/test_escrow_cancel.py b/tests/integration/transactions/test_escrow_cancel.py deleted file mode 100644 index 42cae81d6..000000000 --- a/tests/integration/transactions/test_escrow_cancel.py +++ /dev/null @@ -1,27 +0,0 @@ -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 WALLET -from xrpl.models.response import ResponseStatus -from xrpl.models.transactions import EscrowCancel - -ACCOUNT = WALLET.address -OWNER = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn" -OFFER_SEQUENCE = 7 - - -class TestEscrowCancel(IntegrationTestCase): - @test_async_and_sync(globals()) - async def test_all_fields(self, client): - escrow_cancel = EscrowCancel( - account=ACCOUNT, - owner=OWNER, - offer_sequence=OFFER_SEQUENCE, - ) - response = await sign_and_reliable_submission_async( - escrow_cancel, WALLET, client - ) - # Actual engine_result is `tecNO_TARGET since OWNER account doesn't exist - self.assertEqual(response.status, ResponseStatus.SUCCESS) diff --git a/tests/integration/transactions/test_escrow_create.py b/tests/integration/transactions/test_escrow_create.py deleted file mode 100644 index 4e1df99ac..000000000 --- a/tests/integration/transactions/test_escrow_create.py +++ /dev/null @@ -1,38 +0,0 @@ -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.models import EscrowCreate, Ledger -from xrpl.models.response import ResponseStatus - -ACCOUNT = WALLET.address - -AMOUNT = "10000" -CONDITION = ( - "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100" -) -DESTINATION_TAG = 23480 -SOURCE_TAG = 11747 - - -class TestEscrowCreate(IntegrationTestCase): - @test_async_and_sync(globals()) - async def test_all_fields(self, client): - ledger = await client.request(Ledger(ledger_index="validated")) - close_time = ledger.result["ledger"]["close_time"] - escrow_create = EscrowCreate( - account=WALLET.classic_address, - amount=AMOUNT, - destination=DESTINATION.classic_address, - destination_tag=DESTINATION_TAG, - cancel_after=close_time + 3, - finish_after=close_time + 2, - source_tag=SOURCE_TAG, - ) - response = await sign_and_reliable_submission_async( - escrow_create, WALLET, client - ) - self.assertEqual(response.status, ResponseStatus.SUCCESS) - self.assertEqual(response.result["engine_result"], "tesSUCCESS") diff --git a/tests/integration/transactions/test_escrow_finish.py b/tests/integration/transactions/test_escrow_finish.py deleted file mode 100644 index a415cb3fa..000000000 --- a/tests/integration/transactions/test_escrow_finish.py +++ /dev/null @@ -1,38 +0,0 @@ -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 WALLET -from xrpl.models.response import ResponseStatus -from xrpl.models.transactions import EscrowFinish - -# Special fee for EscrowFinish transactions that contain a fulfillment. -# See note here: https://xrpl.org/escrowfinish.html -FEE = "600000000" - -ACCOUNT = WALLET.address -OWNER = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn" -OFFER_SEQUENCE = 7 -CONDITION = ( - "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100" -) -FULFILLMENT = "A0028000" - - -class TestEscrowFinish(IntegrationTestCase): - @test_async_and_sync(globals()) - async def test_all_fields(self, client): - escrow_finish = EscrowFinish( - account=ACCOUNT, - owner=OWNER, - offer_sequence=OFFER_SEQUENCE, - condition=CONDITION, - fulfillment=FULFILLMENT, - ) - response = await sign_and_reliable_submission_async( - escrow_finish, WALLET, client - ) - # Actual engine_result will be 'tecNO_TARGET' since using non-extant - # account for OWNER - self.assertEqual(response.status, ResponseStatus.SUCCESS) diff --git a/xrpl/asyncio/transaction/main.py b/xrpl/asyncio/transaction/main.py index 029be2a15..2ea9e0f3e 100644 --- a/xrpl/asyncio/transaction/main.py +++ b/xrpl/asyncio/transaction/main.py @@ -22,6 +22,7 @@ SubmitOnly, Transaction, ) +from xrpl.models.transactions.escrow_create import EscrowCreate from xrpl.models.transactions.transaction import ( transaction_json_to_binary_codec_form as model_transaction_to_binary_codec, ) @@ -479,8 +480,10 @@ async def _calculate_fee_per_transaction_type( # BaseFee × (33 + (Fulfillment size in bytes / 16)) base_fee = math.ceil(net_fee * (33 + (len(fulfillment_bytes) / 16))) - if transaction.transaction_type == TransactionType.ESCROW_CANCEL: - base_fee += 1000 + if transaction.transaction_type == TransactionType.ESCROW_CREATE: + escrow_create = cast(EscrowCreate, transaction) + if escrow_create.finish_function is not None: + base_fee += 1000 # AccountDelete Transaction if transaction.transaction_type in ( diff --git a/xrpl/core/binarycodec/definitions/definitions.json b/xrpl/core/binarycodec/definitions/definitions.json index 92e90c8e6..f6c4984cd 100644 --- a/xrpl/core/binarycodec/definitions/definitions.json +++ b/xrpl/core/binarycodec/definitions/definitions.json @@ -670,6 +670,26 @@ "type": "UInt32" } ], + [ + "ExtensionComputeLimit", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 52, + "type": "UInt32" + } + ], + [ + "ExtensionSizeLimit", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 53, + "type": "UInt32" + } + ], [ "IndexNext", { @@ -1850,6 +1870,16 @@ "type": "Blob" } ], + [ + "FinishFunction", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 32, + "type": "Blob" + } + ], [ "Account", { @@ -2951,6 +2981,7 @@ "tecUNFUNDED_AMM": 162, "tecUNFUNDED_OFFER": 103, "tecUNFUNDED_PAYMENT": 104, + "tecWASM_REJECTED": 194, "tecXCHAIN_ACCOUNT_CREATE_PAST": 181, "tecXCHAIN_ACCOUNT_CREATE_TOO_MANY": 182, "tecXCHAIN_BAD_CLAIM_ID": 172, diff --git a/xrpl/models/transactions/escrow_create.py b/xrpl/models/transactions/escrow_create.py index 59bea4867..0ed8a85ab 100644 --- a/xrpl/models/transactions/escrow_create.py +++ b/xrpl/models/transactions/escrow_create.py @@ -87,12 +87,12 @@ def _get_errors(self: Self) -> Dict[str, str]: "The finish_after time must be before the cancel_after time." ) if ( - self.cancel_after is None + self.finish_after is None and self.condition is None and self.finish_function is None ): errors["EscrowCreate"] = ( - "At least one of cancel_after, condition, or finish_function must be " + "At least one of finish_after, condition, or finish_function must be " "set." ) From 09f98af7dcdebd9b5fec70bc09d3d5f2bdd3803e Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 11 Mar 2025 14:13:12 -0400 Subject: [PATCH 03/32] add EscrowCancel --- .../models/transactions/test_escrow_create.py | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/tests/unit/models/transactions/test_escrow_create.py b/tests/unit/models/transactions/test_escrow_create.py index d7f301a7a..b94c7878a 100644 --- a/tests/unit/models/transactions/test_escrow_create.py +++ b/tests/unit/models/transactions/test_escrow_create.py @@ -5,6 +5,30 @@ class TestEscrowCreate(TestCase): + def test_all_fields_valid(self): + account = "r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ" + amount = "amount" + cancel_after = 3 + destination = "destination" + destination_tag = 1 + fee = "0.00001" + finish_after = 2 + finish_function = "abcdef" + condition = "abcdef" + + escrow_create = EscrowCreate( + account=account, + amount=amount, + destination=destination, + destination_tag=destination_tag, + fee=fee, + cancel_after=cancel_after, + finish_after=finish_after, + finish_function=finish_function, + condition=condition, + ) + self.assertTrue(escrow_create.is_valid()) + def test_final_after_less_than_cancel_after(self): account = "r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ" amount = "amount" @@ -12,7 +36,6 @@ def test_final_after_less_than_cancel_after(self): finish_after = 2 destination = "destination" fee = "0.00001" - sequence = 19048 with self.assertRaises(XRPLModelException): EscrowCreate( @@ -22,5 +45,24 @@ def test_final_after_less_than_cancel_after(self): destination=destination, fee=fee, finish_after=finish_after, + ) + + def test_no_finish(self): + account = "r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ" + amount = "amount" + cancel_after = 1 + destination = "destination" + destination_tag = 1 + fee = "0.00001" + sequence = 19048 + + with self.assertRaises(XRPLModelException): + EscrowCreate( + account=account, + amount=amount, + destination=destination, + destination_tag=destination_tag, + fee=fee, + cancel_after=cancel_after, sequence=sequence, ) From c7b3b48544563e0b8d552c8802a536ca856a248d Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 11 Mar 2025 14:15:25 -0400 Subject: [PATCH 04/32] cleanup --- tests/unit/models/transactions/test_escrow_create.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/unit/models/transactions/test_escrow_create.py b/tests/unit/models/transactions/test_escrow_create.py index b94c7878a..5dd21eccd 100644 --- a/tests/unit/models/transactions/test_escrow_create.py +++ b/tests/unit/models/transactions/test_escrow_create.py @@ -11,7 +11,6 @@ def test_all_fields_valid(self): cancel_after = 3 destination = "destination" destination_tag = 1 - fee = "0.00001" finish_after = 2 finish_function = "abcdef" condition = "abcdef" @@ -21,7 +20,6 @@ def test_all_fields_valid(self): amount=amount, destination=destination, destination_tag=destination_tag, - fee=fee, cancel_after=cancel_after, finish_after=finish_after, finish_function=finish_function, @@ -35,7 +33,6 @@ def test_final_after_less_than_cancel_after(self): cancel_after = 1 finish_after = 2 destination = "destination" - fee = "0.00001" with self.assertRaises(XRPLModelException): EscrowCreate( @@ -43,7 +40,6 @@ def test_final_after_less_than_cancel_after(self): amount=amount, cancel_after=cancel_after, destination=destination, - fee=fee, finish_after=finish_after, ) @@ -53,8 +49,6 @@ def test_no_finish(self): cancel_after = 1 destination = "destination" destination_tag = 1 - fee = "0.00001" - sequence = 19048 with self.assertRaises(XRPLModelException): EscrowCreate( @@ -62,7 +56,5 @@ def test_no_finish(self): amount=amount, destination=destination, destination_tag=destination_tag, - fee=fee, cancel_after=cancel_after, - sequence=sequence, ) From d6614382f2fa8a91526d0162926cd4fc35436327 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 11 Mar 2025 17:42:16 -0400 Subject: [PATCH 05/32] remove repeat test --- tests/integration/sugar/test_wallet.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/integration/sugar/test_wallet.py b/tests/integration/sugar/test_wallet.py index 997f92072..87f5b1bc4 100644 --- a/tests/integration/sugar/test_wallet.py +++ b/tests/integration/sugar/test_wallet.py @@ -6,11 +6,9 @@ from xrpl.asyncio.clients import AsyncJsonRpcClient, AsyncWebsocketClient from xrpl.asyncio.wallet import generate_faucet_wallet from xrpl.clients import JsonRpcClient, WebsocketClient -from xrpl.core.addresscodec.main import classic_address_to_xaddress from xrpl.models.requests import AccountInfo from xrpl.models.transactions import Payment from xrpl.wallet import generate_faucet_wallet as sync_generate_faucet_wallet -from xrpl.wallet.main import Wallet def sync_generate_faucet_wallet_and_fund_again( @@ -156,8 +154,3 @@ async def _parallel_test_generate_faucet_wallet_devnet_async_websockets(self): "wss://s.devnet.rippletest.net:51233" ) as client: await generate_faucet_wallet_and_fund_again(self, client) - - def test_wallet_get_xaddress(self): - wallet = Wallet.create() - expected = classic_address_to_xaddress(wallet.address, None, False) - self.assertEqual(wallet.get_xaddress(), expected) From 139992960796b79567ae5d7691b256a163e579a1 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 26 Mar 2025 15:22:03 -0400 Subject: [PATCH 06/32] bump version for beta --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5c6e0806e..a99a73f20 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "xrpl-py" -version = "4.1.0" -description = "A complete Python library for interacting with the XRP ledger" +version = "4.2.0b0" +description = "A complete Python library for interacting with the XRP ledger (Smart Escrow beta)" readme = "README.md" repository = "https://github.com/XRPLF/xrpl-py" authors = [ From dc465b47171fd4704496d816da7b03fe2060372c Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 28 Mar 2025 12:53:44 -0400 Subject: [PATCH 07/32] add faucet info --- tests/integration/sugar/test_wallet.py | 6 ++++++ tests/unit/asyn/wallet/test_wallet.py | 10 ++++++---- xrpl/asyncio/wallet/wallet_generation.py | 16 ++++++++++++---- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/tests/integration/sugar/test_wallet.py b/tests/integration/sugar/test_wallet.py index 87f5b1bc4..b0036891d 100644 --- a/tests/integration/sugar/test_wallet.py +++ b/tests/integration/sugar/test_wallet.py @@ -154,3 +154,9 @@ async def _parallel_test_generate_faucet_wallet_devnet_async_websockets(self): "wss://s.devnet.rippletest.net:51233" ) as client: await generate_faucet_wallet_and_fund_again(self, client) + + async def _parallel_test_generate_faucet_wallet_wasm_devnet_async_websockets(self): + async with AsyncWebsocketClient( + "wss://wasm.devnet.rippletest.net:51233" + ) as client: + await generate_faucet_wallet_and_fund_again(self, client) diff --git a/tests/unit/asyn/wallet/test_wallet.py b/tests/unit/asyn/wallet/test_wallet.py index 19114aacd..c2501417e 100644 --- a/tests/unit/asyn/wallet/test_wallet.py +++ b/tests/unit/asyn/wallet/test_wallet.py @@ -1,8 +1,9 @@ from unittest import TestCase from xrpl.asyncio.wallet.wallet_generation import ( - _DEV_FAUCET_URL, - _TEST_FAUCET_URL, + _DEVNET_FAUCET_URL, + _TESTNET_FAUCET_URL, + _WASM_DEVNET_FAUCET_URL, XRPLFaucetException, get_faucet_url, process_faucet_host_url, @@ -18,8 +19,9 @@ def test_wallet_get_xaddress(self): self.assertEqual(wallet.get_xaddress(), expected) def test_get_faucet_wallet_valid(self): - self.assertEqual(get_faucet_url(1), _TEST_FAUCET_URL) - self.assertEqual(get_faucet_url(2), _DEV_FAUCET_URL) + self.assertEqual(get_faucet_url(1), _TESTNET_FAUCET_URL) + self.assertEqual(get_faucet_url(2), _DEVNET_FAUCET_URL) + self.assertEqual(get_faucet_url(2002), _WASM_DEVNET_FAUCET_URL) def test_get_faucet_wallet_invalid(self): with self.assertRaises(XRPLFaucetException): diff --git a/xrpl/asyncio/wallet/wallet_generation.py b/xrpl/asyncio/wallet/wallet_generation.py index c5bf7418c..d71afea12 100644 --- a/xrpl/asyncio/wallet/wallet_generation.py +++ b/xrpl/asyncio/wallet/wallet_generation.py @@ -13,11 +13,19 @@ from xrpl.constants import XRPLException from xrpl.wallet.main import Wallet -_TEST_FAUCET_URL: Final[str] = "https://faucet.altnet.rippletest.net/accounts" -_DEV_FAUCET_URL: Final[str] = "https://faucet.devnet.rippletest.net/accounts" +_TESTNET_FAUCET_URL: Final[str] = "https://faucet.altnet.rippletest.net/accounts" +_DEVNET_FAUCET_URL: Final[str] = "https://faucet.devnet.rippletest.net/accounts" +_WASM_DEVNET_FAUCET_URL: Final[str] = ( + "https://wasmfaucet.devnet.rippletest.net/accounts" +) + _TIMEOUT_SECONDS: Final[int] = 40 -_NETWORK_ID_URL_MAP: Dict[int, str] = {1: _TEST_FAUCET_URL, 2: _DEV_FAUCET_URL} +_NETWORK_ID_URL_MAP: Dict[int, str] = { + 1: _TESTNET_FAUCET_URL, + 2: _DEVNET_FAUCET_URL, + 2002: _WASM_DEVNET_FAUCET_URL, +} class XRPLFaucetException(XRPLException): @@ -35,7 +43,7 @@ async def generate_faucet_wallet( user_agent: Optional[str] = "xrpl-py", ) -> Wallet: """ - Generates a random wallet and funds it using the XRPL Testnet Faucet. + Generates a random wallet and funds it using an XRPL Testnet Faucet. Args: client: the network client used to make network calls. From 3a009c230b248f1db19bfcaecb321523f7b354d2 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 28 Mar 2025 15:38:15 -0400 Subject: [PATCH 08/32] easier running wallet tests --- tests/integration/sugar/test_wallet.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/integration/sugar/test_wallet.py b/tests/integration/sugar/test_wallet.py index b0036891d..6d1297cf2 100644 --- a/tests/integration/sugar/test_wallet.py +++ b/tests/integration/sugar/test_wallet.py @@ -1,7 +1,11 @@ import asyncio from threading import Thread -from tests.integration.integration_test_case import IntegrationTestCase +try: + from unittest import IsolatedAsyncioTestCase +except ImportError: + from aiounittest import AsyncTestCase as IsolatedAsyncioTestCase # type: ignore + from tests.integration.it_utils import submit_transaction_async from xrpl.asyncio.clients import AsyncJsonRpcClient, AsyncWebsocketClient from xrpl.asyncio.wallet import generate_faucet_wallet @@ -63,7 +67,7 @@ async def generate_faucet_wallet_and_fund_again( self.assertTrue(new_balance > balance) -class TestWallet(IntegrationTestCase): +class TestWallet(IsolatedAsyncioTestCase): async def test_run_faucet_tests(self): # run all the tests that start with `_test_` in parallel def run_test(test_name): From 468b29b7485b985c960dc06010d1c7beaa298bbe Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 28 Mar 2025 16:07:01 -0400 Subject: [PATCH 09/32] Update rippled.cfg --- .ci-config/rippled.cfg | 3 --- 1 file changed, 3 deletions(-) diff --git a/.ci-config/rippled.cfg b/.ci-config/rippled.cfg index c266a72fa..1561f9906 100644 --- a/.ci-config/rippled.cfg +++ b/.ci-config/rippled.cfg @@ -72,9 +72,6 @@ pool.ntp.org [ips] r.ripple.com 51235 -[validators_file] -validators.txt - [rpc_startup] { "command": "log_level", "severity": "info" } From cbeee6bffaa9ce13803dde039b0adf3989eb97d8 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 28 Mar 2025 16:13:44 -0400 Subject: [PATCH 10/32] if it ain't broke don't fix it --- tests/integration/it_utils.py | 43 +++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/tests/integration/it_utils.py b/tests/integration/it_utils.py index 79856ffdc..ebd2e2861 100644 --- a/tests/integration/it_utils.py +++ b/tests/integration/it_utils.py @@ -3,6 +3,7 @@ import asyncio import importlib import inspect +from threading import Timer as ThreadingTimer from time import sleep from typing import Any, Dict, cast @@ -13,7 +14,7 @@ from xrpl.clients import Client, JsonRpcClient, WebsocketClient from xrpl.clients.sync_client import SyncClient from xrpl.constants import CryptoAlgorithm -from xrpl.models import GenericRequest, Payment, Response, Transaction +from xrpl.models import GenericRequest, Payment, Request, Response, Transaction from xrpl.models.amounts.issued_currency_amount import IssuedCurrencyAmount from xrpl.models.currencies.issued_currency import IssuedCurrency from xrpl.models.currencies.xrp import XRP @@ -68,6 +69,40 @@ LEDGER_ACCEPT_TIME = 0.1 +class AsyncTestTimer: + def __init__( + self, + client: AsyncClient, + delay: float = LEDGER_ACCEPT_TIME, + request: Request = LEDGER_ACCEPT_REQUEST, + ): + self._client = client + self._delay = delay + self._request = request + self._task = asyncio.ensure_future(self._job()) + + async def _job(self): + await asyncio.sleep(self._delay) + await self._client.request(self._request) + + def cancel(self): + self._task.cancel() + + +class SyncTestTimer: + def __init__( + self, + client: SyncClient, + delay: float = LEDGER_ACCEPT_TIME, + request: Request = LEDGER_ACCEPT_REQUEST, + ): + self._timer = ThreadingTimer(delay, client.request, (request,)) + self._timer.start() + + def cancel(self): + self._timer.cancel() + + def fund_wallet(wallet: Wallet) -> None: client = JSON_RPC_CLIENT payment = Payment( @@ -197,8 +232,7 @@ def accept_ledger( delay: float for how many seconds to wait before accepting ledger. """ client = _choose_client(use_json_client) - sleep(delay) - client.request(LEDGER_ACCEPT_REQUEST) + SyncTestTimer(client, delay) async def accept_ledger_async( @@ -213,8 +247,7 @@ async def accept_ledger_async( delay: float for how many seconds to wait before accepting ledger. """ client = _choose_client_async(use_json_client) - await asyncio.sleep(delay) - await client.request(LEDGER_ACCEPT_REQUEST) + AsyncTestTimer(client, delay) def _choose_client(use_json_client: bool) -> SyncClient: From 445b233ade905ba068993923a1ce88e4b96e2740 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 28 Mar 2025 16:19:30 -0400 Subject: [PATCH 11/32] add more buffer --- tests/integration/transactions/test_escrow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/transactions/test_escrow.py b/tests/integration/transactions/test_escrow.py index d99cfe302..65ff38493 100644 --- a/tests/integration/transactions/test_escrow.py +++ b/tests/integration/transactions/test_escrow.py @@ -90,7 +90,7 @@ async def test_all_fields_finish(self, client): sequence = response.result["tx_json"]["Sequence"] # TODO: check account_objects - for _ in range(4): + for _ in range(6): await accept_ledger_async() escrow_finish = EscrowFinish( From 67a7775eecd1d32a00c554117eecbfb83925321f Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 28 Mar 2025 16:23:03 -0400 Subject: [PATCH 12/32] add 1s wait between snippet runs --- .github/workflows/snippet_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/snippet_test.yml b/.github/workflows/snippet_test.yml index 619c29663..f7720b201 100644 --- a/.github/workflows/snippet_test.yml +++ b/.github/workflows/snippet_test.yml @@ -48,4 +48,4 @@ jobs: run: poetry install - name: Run Snippets - run: (for i in snippets/*.py; do echo "Running $i" && poetry run python $i || exit 1; done) + run: (for i in snippets/*.py; do echo "Running $i" && poetry run python $i && sleep 1 || exit 1; done) From 4443d6956f07297bcb516bb8e5ad799cd3336708 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 28 Mar 2025 16:30:18 -0400 Subject: [PATCH 13/32] more fixes --- tests/integration/transactions/test_escrow.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/transactions/test_escrow.py b/tests/integration/transactions/test_escrow.py index 65ff38493..f8a214fc9 100644 --- a/tests/integration/transactions/test_escrow.py +++ b/tests/integration/transactions/test_escrow.py @@ -57,7 +57,7 @@ async def test_all_fields_cancel(self, client): # TODO: check account_objects for _ in range(4): - await accept_ledger_async() + await accept_ledger_async(delay=0.5) escrow_cancel = EscrowCancel( account=ACCOUNT, @@ -91,7 +91,7 @@ async def test_all_fields_finish(self, client): # TODO: check account_objects for _ in range(6): - await accept_ledger_async() + await accept_ledger_async(delay=0.5) escrow_finish = EscrowFinish( account=ACCOUNT, From 2a68fde5cc20c30e2a9272f8e16d566e9e7c9c46 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 28 Mar 2025 16:40:19 -0400 Subject: [PATCH 14/32] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f5411bbe9..2073496f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "xrpl-py" -version = "4.2.0b0" +version = "4.2.0b1" description = "A complete Python library for interacting with the XRP ledger (Smart Escrow beta)" license = "ISC" readme = "README.md" From 34e6d8009c1e65f6dc37b8acf17790c518e1cc48 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 28 Mar 2025 16:51:21 -0400 Subject: [PATCH 15/32] increase faucet timeout --- xrpl/asyncio/wallet/wallet_generation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xrpl/asyncio/wallet/wallet_generation.py b/xrpl/asyncio/wallet/wallet_generation.py index d71afea12..eb6f10a29 100644 --- a/xrpl/asyncio/wallet/wallet_generation.py +++ b/xrpl/asyncio/wallet/wallet_generation.py @@ -228,7 +228,7 @@ async def _request_funding( json_body = {"destination": address, "userAgent": user_agent} if usage_context is not None: json_body["usageContext"] = usage_context - response = await http_client.post(url=url, json=json_body) + response = await http_client.post(url=url, json=json_body, timeout=10) if not response.status_code == httpx.codes.OK: response.raise_for_status() From cfa95f5db852edf1532367f15d0538701b48b476 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 29 Apr 2025 16:39:15 -0400 Subject: [PATCH 16/32] update to Devnet 2 --- xrpl/asyncio/transaction/main.py | 12 ++++++++++++ xrpl/models/transactions/escrow_finish.py | 2 ++ 2 files changed, 14 insertions(+) diff --git a/xrpl/asyncio/transaction/main.py b/xrpl/asyncio/transaction/main.py index 2ea9e0f3e..79658f9e1 100644 --- a/xrpl/asyncio/transaction/main.py +++ b/xrpl/asyncio/transaction/main.py @@ -38,6 +38,7 @@ # More context: https://github.com/XRPLF/rippled/pull/4370 _RESTRICTED_NETWORKS = 1024 _REQUIRED_NETWORKID_VERSION = "1.11.0" +_MICRO_DROPS_PER_DROP = 1_000_000 async def sign_and_submit( @@ -479,6 +480,11 @@ async def _calculate_fee_per_transaction_type( fulfillment_bytes = escrow_finish.fulfillment.encode("ascii") # BaseFee × (33 + (Fulfillment size in bytes / 16)) base_fee = math.ceil(net_fee * (33 + (len(fulfillment_bytes) / 16))) + if escrow_finish.computation_allowance is not None: + gas_price = await _fetch_gas_price(client) + base_fee += math.ceil( + gas_price * escrow_finish.computation_allowance / _MICRO_DROPS_PER_DROP + ) if transaction.transaction_type == TransactionType.ESCROW_CREATE: escrow_create = cast(EscrowCreate, transaction) @@ -504,3 +510,9 @@ async def _fetch_owner_reserve_fee(client: Client) -> int: server_state = await client._request_impl(ServerState()) fee = server_state.result["state"]["validated_ledger"]["reserve_inc"] return int(fee) + + +async def _fetch_gas_price(client: Client) -> int: + server_state = await client._request_impl(ServerState()) + fee = server_state.result["state"]["validated_ledger"]["gas_price"] + return int(fee) diff --git a/xrpl/models/transactions/escrow_finish.py b/xrpl/models/transactions/escrow_finish.py index 07bb87fa4..93176700f 100644 --- a/xrpl/models/transactions/escrow_finish.py +++ b/xrpl/models/transactions/escrow_finish.py @@ -63,6 +63,8 @@ class EscrowFinish(Transaction): """Credentials associated with sender of this transaction. The credentials included must not be expired.""" + computation_allowance: Optional[int] = None + def _get_errors(self: Self) -> Dict[str, str]: errors = super()._get_errors() if self.condition and not self.fulfillment: From fc3f5f6b012320333ff83708615f175b8cc3b42b Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 2 May 2025 11:42:40 -0400 Subject: [PATCH 17/32] update beta version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2073496f5..787ae4ae1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "xrpl-py" -version = "4.2.0b1" +version = "4.2.0b2" description = "A complete Python library for interacting with the XRP ledger (Smart Escrow beta)" license = "ISC" readme = "README.md" From 1f25b908ecafa8868c309fbf34a4db7c1b8ef2b1 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Sat, 3 May 2025 21:47:02 -0400 Subject: [PATCH 18/32] update definitions --- .../binarycodec/definitions/definitions.json | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/xrpl/core/binarycodec/definitions/definitions.json b/xrpl/core/binarycodec/definitions/definitions.json index f6c4984cd..d0f3376c0 100644 --- a/xrpl/core/binarycodec/definitions/definitions.json +++ b/xrpl/core/binarycodec/definitions/definitions.json @@ -690,6 +690,26 @@ "type": "UInt32" } ], + [ + "GasPrice", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 54, + "type": "UInt32" + } + ], + [ + "ComputationAllowance", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 55, + "type": "UInt32" + } + ], [ "IndexNext", { @@ -1880,6 +1900,16 @@ "type": "Blob" } ], + [ + "FinishFunction", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 32, + "type": "Blob" + } + ], [ "Account", { @@ -2571,7 +2601,8 @@ } ], [ - "AcceptedCredentials", { + "AcceptedCredentials", + { "nth": 28, "isVLEncoded": false, "isSerialized": true, @@ -3018,8 +3049,10 @@ "tefNOT_MULTI_SIGNING": -184, "tefNO_AUTH_REQUIRED": -191, "tefNO_TICKET": -180, + "tefNO_WASM": -177, "tefPAST_SEQ": -190, "tefTOO_BIG": -181, + "tefWASM_FIELD_NOT_INCLUDED": -176, "tefWRONG_PRIOR": -189, "telBAD_DOMAIN": -398, "telBAD_PATH_COUNT": -397, From 7238d6fad4f7a2db0c390e25ba91ac1d3927a2b2 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 29 May 2025 16:04:26 -0400 Subject: [PATCH 19/32] fix integration tests --- tests/integration/it_utils.py | 6 ++-- tests/integration/transactions/test_escrow.py | 32 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/integration/it_utils.py b/tests/integration/it_utils.py index ebd2e2861..26717a3b6 100644 --- a/tests/integration/it_utils.py +++ b/tests/integration/it_utils.py @@ -232,7 +232,8 @@ def accept_ledger( delay: float for how many seconds to wait before accepting ledger. """ client = _choose_client(use_json_client) - SyncTestTimer(client, delay) + timer = SyncTestTimer(client, delay) + timer._timer.join() # Wait for the timer to finish async def accept_ledger_async( @@ -247,7 +248,8 @@ async def accept_ledger_async( delay: float for how many seconds to wait before accepting ledger. """ client = _choose_client_async(use_json_client) - AsyncTestTimer(client, delay) + timer = AsyncTestTimer(client, delay) + await timer._job() def _choose_client(use_json_client: bool) -> SyncClient: diff --git a/tests/integration/transactions/test_escrow.py b/tests/integration/transactions/test_escrow.py index f8a214fc9..e14e8fee7 100644 --- a/tests/integration/transactions/test_escrow.py +++ b/tests/integration/transactions/test_escrow.py @@ -18,19 +18,16 @@ SOURCE_TAG = 11747 FINISH_FUNCTION = ( - "0061736d010000000105016000017f021b0108686f73745f6c69620e6765745f6c" - "65646765725f73716e0000030201000405017001010105030100100619037f0141" - "8080c0000b7f00418080c0000b7f00418080c0000b072d04066d656d6f72790200" - "05726561647900010a5f5f646174615f656e6403010b5f5f686561705f62617365" - "03020a0d010b0010808080800041044a0b006e046e616d65000e0d7761736d5f6c" - "69622e7761736d01430200395f5a4e387761736d5f6c696238686f73745f6c6962" - "31346765745f6c65646765725f73716e3137686663383539386237646539633036" - "64624501057265616479071201000f5f5f737461636b5f706f696e746572005509" - "70726f64756365727302086c616e6775616765010452757374000c70726f636573" - "7365642d62790105727573746325312e38332e302d6e696768746c792028633266" - "37346333663920323032342d30392d30392900490f7461726765745f6665617475" - "726573042b0a6d756c746976616c75652b0f6d757461626c652d676c6f62616c73" - "2b0f7265666572656e63652d74797065732b087369676e2d657874" + "0061736d010000000105016000017f02190108686f73745f6c69620c6765" + "744c656467657253716e00000302010005030100100611027f00418080c0" + "000b7f00418080c0000b072e04066d656d6f727902000666696e69736800" + "010a5f5f646174615f656e6403000b5f5f686561705f6261736503010a09" + "010700100041044a0b004d0970726f64756365727302086c616e67756167" + "65010452757374000c70726f6365737365642d6279010572757374631d31" + "2e38352e31202834656231363132353020323032352d30332d3135290049" + "0f7461726765745f6665617475726573042b0f6d757461626c652d676c6f" + "62616c732b087369676e2d6578742b0f7265666572656e63652d74797065" + "732b0a6d756c746976616c7565" ) @@ -56,8 +53,8 @@ async def test_all_fields_cancel(self, client): sequence = response.result["tx_json"]["Sequence"] # TODO: check account_objects - for _ in range(4): - await accept_ledger_async(delay=0.5) + for _ in range(3): + await accept_ledger_async() escrow_cancel = EscrowCancel( account=ACCOUNT, @@ -90,8 +87,8 @@ async def test_all_fields_finish(self, client): sequence = response.result["tx_json"]["Sequence"] # TODO: check account_objects - for _ in range(6): - await accept_ledger_async(delay=0.5) + for _ in range(2): + await accept_ledger_async() escrow_finish = EscrowFinish( account=ACCOUNT, @@ -127,6 +124,7 @@ async def test_finish_function(self, client): account=ACCOUNT, owner=ACCOUNT, offer_sequence=sequence, + computation_allowance=5, ) response = await sign_and_reliable_submission_async( escrow_finish, WALLET, client From fa6955e62d62be5f94db523cc1f5508c554c40bd Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 29 May 2025 16:18:43 -0400 Subject: [PATCH 20/32] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index eb45b1e09..d5688e70b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "xrpl-py" -version = "4.2.0b2" +version = "4.2.0b3" description = "A complete Python library for interacting with the XRP ledger (Smart Escrow beta)" license = "ISC" readme = "README.md" From 3fec6057240f660c4d866a553b181327e7504c64 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 29 May 2025 16:22:34 -0400 Subject: [PATCH 21/32] add workflow_dispatch to publish flow --- .github/workflows/publish_to_pypi.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish_to_pypi.yml b/.github/workflows/publish_to_pypi.yml index d3b5bcb1f..9c2e783e5 100644 --- a/.github/workflows/publish_to_pypi.yml +++ b/.github/workflows/publish_to_pypi.yml @@ -3,6 +3,7 @@ on: push: tags: - '*' + workflow_dispatch: jobs: build: From 1a46cb4fa8aad48dbf154983f0b45e3637812b00 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 29 May 2025 17:24:55 -0400 Subject: [PATCH 22/32] fix tests (hopefully) --- tests/integration/it_utils.py | 10 ++++++---- tests/integration/transactions/test_escrow.py | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/integration/it_utils.py b/tests/integration/it_utils.py index 26717a3b6..073e089f6 100644 --- a/tests/integration/it_utils.py +++ b/tests/integration/it_utils.py @@ -221,7 +221,7 @@ async def sign_and_reliable_submission_async( def accept_ledger( - use_json_client: bool = True, delay: float = LEDGER_ACCEPT_TIME + use_json_client: bool = True, delay: float = LEDGER_ACCEPT_TIME, wait: bool = False ) -> None: """ Allows integration tests for sync clients to send a `ledger_accept` request @@ -233,11 +233,12 @@ def accept_ledger( """ client = _choose_client(use_json_client) timer = SyncTestTimer(client, delay) - timer._timer.join() # Wait for the timer to finish + if wait: + timer._timer.join() # Wait for the timer to finish async def accept_ledger_async( - use_json_client: bool = True, delay: float = LEDGER_ACCEPT_TIME + use_json_client: bool = True, delay: float = LEDGER_ACCEPT_TIME, wait: bool = False ) -> None: """ Allows integration tests for async clients to send a `ledger_accept` request @@ -249,7 +250,8 @@ async def accept_ledger_async( """ client = _choose_client_async(use_json_client) timer = AsyncTestTimer(client, delay) - await timer._job() + if wait: + await timer._job() def _choose_client(use_json_client: bool) -> SyncClient: diff --git a/tests/integration/transactions/test_escrow.py b/tests/integration/transactions/test_escrow.py index e14e8fee7..ed4947903 100644 --- a/tests/integration/transactions/test_escrow.py +++ b/tests/integration/transactions/test_escrow.py @@ -54,7 +54,7 @@ async def test_all_fields_cancel(self, client): # TODO: check account_objects for _ in range(3): - await accept_ledger_async() + await accept_ledger_async(wait=True) escrow_cancel = EscrowCancel( account=ACCOUNT, @@ -88,7 +88,7 @@ async def test_all_fields_finish(self, client): # TODO: check account_objects for _ in range(2): - await accept_ledger_async() + await accept_ledger_async(wait=True) escrow_finish = EscrowFinish( account=ACCOUNT, From 217e815e6933afe357afe3d8325dbe0d7675764b Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 5 Jun 2025 11:01:59 -0400 Subject: [PATCH 23/32] fix definitions --- .../binarycodec/definitions/definitions.json | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/xrpl/core/binarycodec/definitions/definitions.json b/xrpl/core/binarycodec/definitions/definitions.json index 4899a4df0..cc34c5139 100644 --- a/xrpl/core/binarycodec/definitions/definitions.json +++ b/xrpl/core/binarycodec/definitions/definitions.json @@ -680,6 +680,56 @@ "type": "UInt32" } ], + [ + "ExtensionComputeLimit", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 53, + "type": "UInt32" + } + ], + [ + "ExtensionSizeLimit", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 54, + "type": "UInt32" + } + ], + [ + "GasPrice", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 55, + "type": "UInt32" + } + ], + [ + "ComputationAllowance", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 56, + "type": "UInt32" + } + ], + [ + "GasUsed", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 57, + "type": "UInt32" + } + ], [ "IndexNext", { @@ -1890,6 +1940,16 @@ "type": "Blob" } ], + [ + "FinishFunction", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 32, + "type": "Blob" + } + ], [ "Account", { @@ -3159,6 +3219,7 @@ "tecUNFUNDED_AMM": 162, "tecUNFUNDED_OFFER": 103, "tecUNFUNDED_PAYMENT": 104, + "tecWASM_REJECTED": 199, "tecWRONG_ASSET": 194, "tecXCHAIN_ACCOUNT_CREATE_PAST": 181, "tecXCHAIN_ACCOUNT_CREATE_TOO_MANY": 182, @@ -3197,8 +3258,10 @@ "tefNOT_MULTI_SIGNING": -184, "tefNO_AUTH_REQUIRED": -191, "tefNO_TICKET": -180, + "tefNO_WASM": -177, "tefPAST_SEQ": -190, "tefTOO_BIG": -181, + "tefWASM_FIELD_NOT_INCLUDED": -176, "tefWRONG_PRIOR": -189, "telBAD_DOMAIN": -398, From 0753bbf30c8b35cac397f36a4f38e915a5bb9f49 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 11 Jul 2025 01:19:47 +0530 Subject: [PATCH 24/32] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a05165105..e1172f00f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "xrpl-py" -version = "4.2.0b3" +version = "4.3.0b0" description = "A complete Python library for interacting with the XRP ledger (Smart Escrow beta)" license = "ISC" readme = "README.md" From b14bfbb7db533ecfef91baec16cfa64098280b91 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 30 Jul 2025 17:14:31 -0400 Subject: [PATCH 25/32] fix tests --- tests/integration/transactions/test_escrow.py | 154 ++++++++++-------- 1 file changed, 84 insertions(+), 70 deletions(-) diff --git a/tests/integration/transactions/test_escrow.py b/tests/integration/transactions/test_escrow.py index a3629d060..5cb1afa99 100644 --- a/tests/integration/transactions/test_escrow.py +++ b/tests/integration/transactions/test_escrow.py @@ -30,16 +30,23 @@ SOURCE_TAG = 11747 FINISH_FUNCTION = ( - "0061736d010000000105016000017f02190108686f73745f6c69620c6765" - "744c656467657253716e00000302010005030100100611027f00418080c0" - "000b7f00418080c0000b072e04066d656d6f727902000666696e69736800" - "010a5f5f646174615f656e6403000b5f5f686561705f6261736503010a09" - "010700100041044a0b004d0970726f64756365727302086c616e67756167" - "65010452757374000c70726f6365737365642d6279010572757374631d31" - "2e38352e31202834656231363132353020323032352d30332d3135290049" - "0f7461726765745f6665617475726573042b0f6d757461626c652d676c6f" - "62616c732b087369676e2d6578742b0f7265666572656e63652d74797065" - "732b0a6d756c746976616c7565" + "0061736d0100000001150460027f7f017f60037f7f7e017f6000017f60000002300208686f73745f6" + "c69620e6765745f6c65646765725f73716e000008686f73745f6c69620974726163655f6e756d0001" + "030302020305030100110619037f01418080c0000b7f00418b80c0000b7f00419080c0000b072e040" + "66d656d6f727902000666696e69736800020a5f5f646174615f656e6403010b5f5f686561705f6261" + "736503020a69026301027f23808080800041106b22002480808080002000410036020c02402000410" + "c6a41081080808080002201417f4a0d00418080c08000410b2001ac1081808080001a108380808000" + "000b200028020c2101200041106a248080808000200141044b0b0300000b0b140100418080c0000b0" + "b6572726f725f636f64653d00dd01046e616d6500100f6c65646765725f73716e2e7761736d01a301" + "0400355f5a4e387872706c5f73746434686f737431346765745f6c65646765725f73716e313768666" + "5343539333764623461656439366245012f5f5a4e387872706c5f73746434686f7374397472616365" + "5f6e756d3137686139376531613763346138636231333245020666696e69736803305f5a4e34636f7" + "2653970616e69636b696e673970616e69635f666d7431376862393162616461636536656538323837" + "45071201000f5f5f737461636b5f706f696e746572090a0100072e726f64617461004d0970726f647" + "56365727302086c616e6775616765010452757374000c70726f6365737365642d6279010572757374" + "631d312e38352e31202834656231363132353020323032352d30332d31352900490f7461726765745" + "f6665617475726573042b0a6d756c746976616c75652b0f6d757461626c652d676c6f62616c732b0f" + "7265666572656e63652d74797065732b087369676e2d657874" ) issuer = Wallet.create() @@ -52,19 +59,22 @@ class TestEscrow(IntegrationTestCase): @classmethod def setUpClass(cls): - global good_mpt_issuance_id, bad_mpt_issuance_id super().setUpClass() client = JSON_RPC_CLIENT # Create issuer, source, and destination wallets. - fund_wallet(issuer) - fund_wallet(source) - fund_wallet(destination) + cls.issuer = Wallet.create() + cls.source = Wallet.create() + cls.destination = Wallet.create() - good_mpt_issuance_id = create_mpt_token_and_authorize_source( - issuer, - source, + fund_wallet(cls.issuer) + fund_wallet(cls.source) + fund_wallet(cls.destination) + + cls.good_mpt_issuance_id = create_mpt_token_and_authorize_source( + cls.issuer, + cls.source, client, [ MPTokenIssuanceCreateFlag.TF_MPT_CAN_ESCROW, @@ -72,9 +82,9 @@ def setUpClass(cls): ], ) - bad_mpt_issuance_id = create_mpt_token_and_authorize_source( - issuer, - source, + cls.bad_mpt_issuance_id = create_mpt_token_and_authorize_source( + cls.issuer, + cls.source, client, ) @@ -113,6 +123,40 @@ async def test_all_fields_cancel(self, client): self.assertEqual(response.status, ResponseStatus.SUCCESS) self.assertEqual(response.result["engine_result"], "tesSUCCESS") + @test_async_and_sync(globals()) + async def test_all_fields_finish(self, client): + ledger = await client.request(Ledger(ledger_index="validated")) + close_time = ledger.result["ledger"]["close_time"] + escrow_create = EscrowCreate( + account=ACCOUNT, + amount=AMOUNT, + destination=DESTINATION.classic_address, + destination_tag=DESTINATION_TAG, + finish_after=close_time + 2, + source_tag=SOURCE_TAG, + ) + response = await sign_and_reliable_submission_async( + escrow_create, WALLET, client + ) + self.assertEqual(response.status, ResponseStatus.SUCCESS) + self.assertEqual(response.result["engine_result"], "tesSUCCESS") + sequence = response.result["tx_json"]["Sequence"] + # TODO: check account_objects + + for _ in range(2): + await accept_ledger_async(wait=True) + + escrow_finish = EscrowFinish( + account=ACCOUNT, + owner=ACCOUNT, + offer_sequence=sequence, + ) + response = await sign_and_reliable_submission_async( + escrow_finish, WALLET, client + ) + self.assertEqual(response.status, ResponseStatus.SUCCESS) + self.assertEqual(response.result["engine_result"], "tesSUCCESS") + @test_async_and_sync(globals()) async def test_mpt_based_escrow(self, client): # Create Escrow with MPToken. @@ -120,21 +164,21 @@ async def test_mpt_based_escrow(self, client): close_time = ledger.result["ledger"]["close_time"] escrowed_amount = MPTAmount( - mpt_issuance_id=good_mpt_issuance_id, + mpt_issuance_id=self.good_mpt_issuance_id, value="1", ) finish_after = close_time + 2 escrow_create = EscrowCreate( - account=source.classic_address, + account=self.source.classic_address, amount=escrowed_amount, - destination=destination.classic_address, + destination=self.destination.classic_address, finish_after=finish_after, cancel_after=close_time + 1000, ) response = await sign_and_reliable_submission_async( - escrow_create, source, client + escrow_create, self.source, client ) escrow_create_seq = response.result["tx_json"]["Sequence"] @@ -143,7 +187,7 @@ async def test_mpt_based_escrow(self, client): # Confirm Escrow ledger object was created. account_objects_response = await client.request( - AccountObjects(account=source.address, type=AccountObjectType.ESCROW) + AccountObjects(account=self.source.address, type=AccountObjectType.ESCROW) ) escrow_objects = account_objects_response.result["account_objects"] @@ -154,7 +198,7 @@ async def test_mpt_based_escrow(self, client): # Confirm MPToken ledger object was created. account_objects_response = await client.request( - AccountObjects(account=source.address, type=AccountObjectType.MPTOKEN) + AccountObjects(account=self.source.address, type=AccountObjectType.MPTOKEN) ) mptoken_objects = account_objects_response.result["account_objects"] self.assertTrue( @@ -168,7 +212,9 @@ async def test_mpt_based_escrow(self, client): # Confirm MPTokenIssuance ledger object was created. account_objects_response = await client.request( - AccountObjects(account=issuer.address, type=AccountObjectType.MPT_ISSUANCE) + AccountObjects( + account=self.issuer.address, type=AccountObjectType.MPT_ISSUANCE + ) ) mpt_issuance_objects = account_objects_response.result["account_objects"] @@ -192,19 +238,21 @@ async def test_mpt_based_escrow(self, client): # Finish the escrow. escrow_finish = EscrowFinish( - account=destination.classic_address, - owner=source.classic_address, + account=self.destination.classic_address, + owner=self.source.classic_address, offer_sequence=escrow_create_seq, ) response = await sign_and_reliable_submission_async( - escrow_finish, destination, client + escrow_finish, self.destination, client ) self.assertEqual(response.status, ResponseStatus.SUCCESS) self.assertEqual(response.result["engine_result"], "tesSUCCESS") # Confirm MPToken ledger object was created for destination. account_objects_response = await client.request( - AccountObjects(account=destination.address, type=AccountObjectType.MPTOKEN) + AccountObjects( + account=self.destination.address, type=AccountObjectType.MPTOKEN + ) ) dest_mptoken_objects = account_objects_response.result["account_objects"] @@ -224,62 +272,28 @@ async def test_mpt_based_escrow_failure(self, client): close_time = ledger.result["ledger"]["close_time"] escrowed_amount = MPTAmount( - mpt_issuance_id=bad_mpt_issuance_id, + mpt_issuance_id=self.bad_mpt_issuance_id, value="1", ) finish_after = close_time + 2 escrow_create = EscrowCreate( - account=source.classic_address, + account=self.source.classic_address, amount=escrowed_amount, - destination=destination.classic_address, + destination=self.destination.classic_address, finish_after=finish_after, cancel_after=close_time + 1000, ) # Transaction fails with tecNO_PERMISSION because lsfMPTCanEscrow is not set. response = await sign_and_reliable_submission_async( - escrow_create, source, client + escrow_create, self.source, client ) self.assertEqual(response.status, ResponseStatus.SUCCESS) self.assertEqual(response.result["engine_result"], "tecNO_PERMISSION") - @test_async_and_sync(globals()) - async def test_all_fields_finish(self, client): - ledger = await client.request(Ledger(ledger_index="validated")) - close_time = ledger.result["ledger"]["close_time"] - escrow_create = EscrowCreate( - account=ACCOUNT, - amount=AMOUNT, - destination=DESTINATION.classic_address, - destination_tag=DESTINATION_TAG, - finish_after=close_time + 2, - source_tag=SOURCE_TAG, - ) - response = await sign_and_reliable_submission_async( - escrow_create, WALLET, client - ) - self.assertEqual(response.status, ResponseStatus.SUCCESS) - self.assertEqual(response.result["engine_result"], "tesSUCCESS") - sequence = response.result["tx_json"]["Sequence"] - # TODO: check account_objects - - for _ in range(2): - await accept_ledger_async(wait=True) - - escrow_finish = EscrowFinish( - account=ACCOUNT, - owner=ACCOUNT, - offer_sequence=sequence, - ) - response = await sign_and_reliable_submission_async( - escrow_finish, WALLET, client - ) - self.assertEqual(response.status, ResponseStatus.SUCCESS) - self.assertEqual(response.result["engine_result"], "tesSUCCESS") - @test_async_and_sync(globals()) async def test_finish_function(self, client): ledger = await client.request(Ledger(ledger_index="validated")) @@ -303,7 +317,7 @@ async def test_finish_function(self, client): account=ACCOUNT, owner=ACCOUNT, offer_sequence=sequence, - computation_allowance=5, + computation_allowance=20000, ) response = await sign_and_reliable_submission_async( escrow_finish, WALLET, client From ab87981df036b6618e939c56ae26593a94e5e035 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 4 Aug 2025 16:36:07 -0400 Subject: [PATCH 26/32] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e1172f00f..f595c23ea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "xrpl-py" -version = "4.3.0b0" +version = "4.4.0b0" description = "A complete Python library for interacting with the XRP ledger (Smart Escrow beta)" license = "ISC" readme = "README.md" From afad8e706e868beb186354335b758b2bd19925e9 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 15 Sep 2025 18:04:38 -0400 Subject: [PATCH 27/32] binary codec changes --- .../fixtures/data/codec-fixtures.json | 425 ++++++++++++------ .../binarycodec/definitions/definitions.json | 18 +- xrpl/core/binarycodec/types/__init__.py | 2 + xrpl/core/binarycodec/types/int.py | 27 ++ xrpl/core/binarycodec/types/int32.py | 71 +++ 5 files changed, 406 insertions(+), 137 deletions(-) create mode 100644 xrpl/core/binarycodec/types/int.py create mode 100644 xrpl/core/binarycodec/types/int32.py diff --git a/tests/unit/core/binarycodec/fixtures/data/codec-fixtures.json b/tests/unit/core/binarycodec/fixtures/data/codec-fixtures.json index 1a5b866dd..ff856cf31 100644 --- a/tests/unit/core/binarycodec/fixtures/data/codec-fixtures.json +++ b/tests/unit/core/binarycodec/fixtures/data/codec-fixtures.json @@ -33,7 +33,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "059D1E86DE5DCCCF956BF4799675B2425AF9AD44FE4CCA6FEE1C812EEF6423E6", - "Indexes": ["908D554AA0D29F660716A3EE65C61DD886B744DDF60DE70E6B16EADB770635DB"] + "Indexes": [ + "908D554AA0D29F660716A3EE65C61DD886B744DDF60DE70E6B16EADB770635DB" + ] } }, { @@ -327,7 +329,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "17CC40C6872E0C0E658C49B75D0812A70D4161DDA53324DF51FA58D3819C814B", - "Indexes": ["571BF14F28C4D97871CDACD344A8CF57E6BA287BF0440B9E0D0683D02751CC7B"] + "Indexes": [ + "571BF14F28C4D97871CDACD344A8CF57E6BA287BF0440B9E0D0683D02751CC7B" + ] } }, { @@ -376,7 +380,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "1BCA9161A199AD5E907751CBF3FBA49689D517F0E8EE823AE17B737039B41DE1", - "Indexes": ["26B894EE68470AD5AEEB55D5EBF936E6397CEE6957B93C56A2E7882CA9082873"] + "Indexes": [ + "26B894EE68470AD5AEEB55D5EBF936E6397CEE6957B93C56A2E7882CA9082873" + ] } }, { @@ -440,7 +446,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "1F9FF48419CA69FDDCC294CCEEE608F5F8A8BE11E286AD5743ED2D457C5570C4", - "Indexes": ["7D4325BE338A40BBCBCC1F351B3272EB3E76305A878E76603DE206A795871619"] + "Indexes": [ + "7D4325BE338A40BBCBCC1F351B3272EB3E76305A878E76603DE206A795871619" + ] } }, { @@ -606,7 +614,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "289CFC476B5876F28C8A3B3C5B7058EC2BDF668C37B846EA7E5E1A73A4AA0816", - "Indexes": ["BC10E40AFB79298004CDE51CB065DBDCABA86EC406E3A1CF02CE5F8A9628A2BD"] + "Indexes": [ + "BC10E40AFB79298004CDE51CB065DBDCABA86EC406E3A1CF02CE5F8A9628A2BD" + ] } }, { @@ -709,7 +719,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "2C9F00EFA5CCBD43452EF364B12C8DFCEF2B910336E5EFCE3AA412A556991582", - "Indexes": ["F721E924498EE68BFF906CD856E8332073DD350BAC9E8977AC3F31860BA1E33A"] + "Indexes": [ + "F721E924498EE68BFF906CD856E8332073DD350BAC9E8977AC3F31860BA1E33A" + ] } }, { @@ -746,7 +758,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "2FB4904ACFB96228FC002335B1B5A4C5584D9D727BBE82144F0415EB4EA0C727", - "Indexes": ["5F22826818CC83448C9DF34939AB4019D3F80C70DEB8BDBDCF0496A36DC68719"], + "Indexes": [ + "5F22826818CC83448C9DF34939AB4019D3F80C70DEB8BDBDCF0496A36DC68719" + ], "TakerPaysIssuer": "2B6C42A95B3F7EE1971E4A10098E8F1B5F66AA08" } }, @@ -760,7 +774,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "2FB4904ACFB96228FC002335B1B5A4C5584D9D727BBE82145003BAF82D03A000", - "Indexes": ["5B7F148A8DDB4EB7386C9E75C4C1ED918DEDE5C52D5BA51B694D7271EF8BDB46"], + "Indexes": [ + "5B7F148A8DDB4EB7386C9E75C4C1ED918DEDE5C52D5BA51B694D7271EF8BDB46" + ], "TakerPaysIssuer": "2B6C42A95B3F7EE1971E4A10098E8F1B5F66AA08" } }, @@ -951,7 +967,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "3F2BADB38F12C87D111D3970CD1F05FE698DB86F14DC7C5FAEB05BFB6391B00E", - "Indexes": ["73E075E64CA5E7CE60FFCD5359C1D730EDFFEE7C4D992760A87DF7EA0A34E40F"] + "Indexes": [ + "73E075E64CA5E7CE60FFCD5359C1D730EDFFEE7C4D992760A87DF7EA0A34E40F" + ] } }, { @@ -976,7 +994,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "4235CD082112FB621C02D6DA2E4F4ACFAFC91CB0585E034B936C29ABF4A76B01", - "Indexes": ["6C4C3F1C6B9D76A6EF50F377E7C3991825694C604DBE0C1DD09362045EE41997"] + "Indexes": [ + "6C4C3F1C6B9D76A6EF50F377E7C3991825694C604DBE0C1DD09362045EE41997" + ] } }, { @@ -1075,7 +1095,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "48E91FD14597FB089654DADE7B70EB08CAF421EA611D703F3E871F7D4B5AAB5D", - "Indexes": ["25DCAC87FBE4C3B66A1AFDE3C3F98E5A16333975C4FD46682F7497F27DFB9766"] + "Indexes": [ + "25DCAC87FBE4C3B66A1AFDE3C3F98E5A16333975C4FD46682F7497F27DFB9766" + ] } }, { @@ -1137,7 +1159,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "4EFC0442D07AE681F7FDFAA89C75F06F8E28CFF888593440201B0320E8F2C7BD", - "Indexes": ["1595E5D5197330F58A479200A2FDD434D7A244BD1FFEC5E5EE8CF064AE77D3F5"] + "Indexes": [ + "1595E5D5197330F58A479200A2FDD434D7A244BD1FFEC5E5EE8CF064AE77D3F5" + ] } }, { @@ -1351,7 +1375,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "98082E695CAB618590BEEA0647A5F24D2B610A686ECD49310604FC7431FAAB0D", - "Indexes": ["9BF3216E42575CA5A3CB4D0F2021EE81D0F7835BA2EDD78E05CAB44B655962BB"] + "Indexes": [ + "9BF3216E42575CA5A3CB4D0F2021EE81D0F7835BA2EDD78E05CAB44B655962BB" + ] } }, { @@ -1556,7 +1582,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "62AE37A44FE44BDCFC2BA5DD14D74BEC0AC346DA2DC1F04756044364C5BB0000", - "Indexes": ["600A398F57CAE44461B4C8C25DE12AC289F87ED125438440B33B97417FE3D82C"], + "Indexes": [ + "600A398F57CAE44461B4C8C25DE12AC289F87ED125438440B33B97417FE3D82C" + ], "TakerPaysIssuer": "2B6C42A95B3F7EE1971E4A10098E8F1B5F66AA08" } }, @@ -1932,7 +1960,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "72D60CCD3905A3ABE19049B6EE76E8E0F3A2CBAC852625C757176F1B73EF617F", - "Indexes": ["AB124EEAB087452070EC70D9DEA1A22C9766FFBBEE1025FD46495CC74148CCA8"] + "Indexes": [ + "AB124EEAB087452070EC70D9DEA1A22C9766FFBBEE1025FD46495CC74148CCA8" + ] } }, { @@ -2061,7 +2091,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "80AB25842B230D48027800213EB86023A3EAF4430E22C092D333795FFF1E5219", - "Indexes": ["42E28285A82D01DCA856118A064C8AEEE1BF8167C08186DA5BFC678687E86F7C"] + "Indexes": [ + "42E28285A82D01DCA856118A064C8AEEE1BF8167C08186DA5BFC678687E86F7C" + ] } }, { @@ -2186,7 +2218,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "8ADF3C5527CCF6D0B5863365EF40254171536C3901F1CBD9E2BC5F918A7D492A", - "Indexes": ["BC10E40AFB79298004CDE51CB065DBDCABA86EC406E3A1CF02CE5F8A9628A2BD"] + "Indexes": [ + "BC10E40AFB79298004CDE51CB065DBDCABA86EC406E3A1CF02CE5F8A9628A2BD" + ] } }, { @@ -2587,7 +2621,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "A00CD19C13A5CFA3FECB409D42B38017C07A4AEAE05A7A00347DDA17199BA683", - "Indexes": ["E49318D6DF22411C3F35581B1D28297A36E47F68B45F36A587C156E6E43CE0A6"] + "Indexes": [ + "E49318D6DF22411C3F35581B1D28297A36E47F68B45F36A587C156E6E43CE0A6" + ] } }, { @@ -2634,7 +2670,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "A39F044D860C5B5846AA7E0FAAD44DC8897F0A62B2F628AA073B21B3EC146010", - "Indexes": ["CD34D8FF7C656B66E2298DB420C918FE27DFFF2186AC8D1785D8CBF2C6BC3488"] + "Indexes": [ + "CD34D8FF7C656B66E2298DB420C918FE27DFFF2186AC8D1785D8CBF2C6BC3488" + ] } }, { @@ -2683,7 +2721,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "A7E461C6DC98F472991FDE51FADDC0082D755F553F5849875D554B52624EF1C3", - "Indexes": ["116C6D5E5C6C59C9C5362B84CB9DD30BD3D4B7CB98CE993D49C068323BF19747"] + "Indexes": [ + "116C6D5E5C6C59C9C5362B84CB9DD30BD3D4B7CB98CE993D49C068323BF19747" + ] } }, { @@ -2717,7 +2757,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "AA539C8EECE0A0CFF0DBF3BFACD6B42CD4421715428AD90B034091BD3C721038", - "Indexes": ["72307CB57E53604A0C50E653AB10E386F3835460B5585B70CB7F668C1E04AC8B"] + "Indexes": [ + "72307CB57E53604A0C50E653AB10E386F3835460B5585B70CB7F668C1E04AC8B" + ] } }, { @@ -3777,7 +3819,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "D4A00D9B3452C7F93C5F0531FA8FFB4599FEEC405CA803FBEFE0FA22137D863D", - "Indexes": ["C1C5FB39D6C15C581D822DBAF725EF7EDE40BEC9F93C52398CF5CE9F64154D6C"] + "Indexes": [ + "C1C5FB39D6C15C581D822DBAF725EF7EDE40BEC9F93C52398CF5CE9F64154D6C" + ] } }, { @@ -3787,7 +3831,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "D4B68B54869E428428078E1045B8BB66C24DD101DB3FCCBB099929B3B63BCB40", - "Indexes": ["9A551971E78FE2FB80D930A77EA0BAC2139A49D6BEB98406427C79F52A347A09"] + "Indexes": [ + "9A551971E78FE2FB80D930A77EA0BAC2139A49D6BEB98406427C79F52A347A09" + ] } }, { @@ -3862,7 +3908,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "DD23E2C60C9BC58180AC6EA7C668233EC51A0947E42FD1FAD4F5FBAED9698D95", - "Indexes": ["908D554AA0D29F660716A3EE65C61DD886B744DDF60DE70E6B16EADB770635DB"] + "Indexes": [ + "908D554AA0D29F660716A3EE65C61DD886B744DDF60DE70E6B16EADB770635DB" + ] } }, { @@ -4013,7 +4061,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "E2EC9E1BC7B4667B7A5F2F68857F6E6A478A09B5BB4F99E09F694437C4152DED", - "Indexes": ["65492B9F30F1CBEA168509128EB8619BAE02A7A7A4725FF3F8DAA70FA707A26E"] + "Indexes": [ + "65492B9F30F1CBEA168509128EB8619BAE02A7A7A4725FF3F8DAA70FA707A26E" + ] } }, { @@ -4190,7 +4240,9 @@ "IndexPrevious": "0000000000000002", "Flags": 0, "RootIndex": "8E92E688A132410427806A734DF6154B7535E439B72DECA5E4BC7CE17135C5A4", - "Indexes": ["73E075E64CA5E7CE60FFCD5359C1D730EDFFEE7C4D992760A87DF7EA0A34E40F"] + "Indexes": [ + "73E075E64CA5E7CE60FFCD5359C1D730EDFFEE7C4D992760A87DF7EA0A34E40F" + ] } }, { @@ -4294,7 +4346,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "F774E0321809251174AC85531606FB46B75EEF9F842F9697531AA535D3D0C000", - "Indexes": ["D1CB738BD08AC36DCB77191DB87C6E40FA478B86503371ED497F30931D7F4F52"], + "Indexes": [ + "D1CB738BD08AC36DCB77191DB87C6E40FA478B86503371ED497F30931D7F4F52" + ], "TakerPaysIssuer": "E8ACFC6B5EF4EA0601241525375162F43C2FF285" } }, @@ -4355,7 +4409,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "F95F6D3A1EF7981E5CA4D5AEC4DA63392B126C76469735BCCA26150A1AF6D9C3", - "Indexes": ["CAD951AB279A749AE648FD1DFF56C021BD66E36187022E772C31FE52106CB13B"] + "Indexes": [ + "CAD951AB279A749AE648FD1DFF56C021BD66E36187022E772C31FE52106CB13B" + ] } }, { @@ -4456,9 +4512,9 @@ "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "XChainBridge": { "LockingChainDoor": "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL", - "LockingChainIssue": {"currency": "XRP"}, + "LockingChainIssue": { "currency": "XRP" }, "IssuingChainDoor": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", - "IssuingChainIssue": {"currency": "XRP"} + "IssuingChainIssue": { "currency": "XRP" } }, "Fee": "10", "Flags": 0, @@ -4476,9 +4532,9 @@ "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "XChainBridge": { "LockingChainDoor": "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL", - "LockingChainIssue": {"currency": "XRP"}, + "LockingChainIssue": { "currency": "XRP" }, "IssuingChainDoor": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", - "IssuingChainIssue": {"currency": "XRP"} + "IssuingChainIssue": { "currency": "XRP" } }, "Fee": "10", "Flags": 0, @@ -4496,9 +4552,9 @@ "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "XChainBridge": { "LockingChainDoor": "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL", - "LockingChainIssue": {"currency": "XRP"}, + "LockingChainIssue": { "currency": "XRP" }, "IssuingChainDoor": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", - "IssuingChainIssue": {"currency": "XRP"} + "IssuingChainIssue": { "currency": "XRP" } }, "Fee": "10", "Flags": 2147483648, @@ -4517,9 +4573,9 @@ "Amount": "10000", "XChainBridge": { "LockingChainDoor": "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL", - "LockingChainIssue": {"currency": "XRP"}, + "LockingChainIssue": { "currency": "XRP" }, "IssuingChainDoor": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", - "IssuingChainIssue": {"currency": "XRP"} + "IssuingChainIssue": { "currency": "XRP" } }, "Fee": "10", "Flags": 2147483648, @@ -4537,9 +4593,9 @@ "Amount": "10000", "XChainBridge": { "LockingChainDoor": "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL", - "LockingChainIssue": {"currency": "XRP"}, + "LockingChainIssue": { "currency": "XRP" }, "IssuingChainDoor": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", - "IssuingChainIssue": {"currency": "XRP"} + "IssuingChainIssue": { "currency": "XRP" } }, "Destination": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", "Fee": "10", @@ -4557,9 +4613,9 @@ "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "XChainBridge": { "LockingChainDoor": "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL", - "LockingChainIssue": {"currency": "XRP"}, + "LockingChainIssue": { "currency": "XRP" }, "IssuingChainDoor": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", - "IssuingChainIssue": {"currency": "XRP"} + "IssuingChainIssue": { "currency": "XRP" } }, "Amount": "1000000", "Fee": "10", @@ -4658,9 +4714,16 @@ "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMDeposit", "TxnSignature": "8073C588E7EF672DD171E414638D9AF8DBE9A1359E030DE3E1C9AA6A38A2CE9E138CB56482BB844F7228D48B1E4AD7D09BB7E9F639C115958EEEA374749CA00B", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, - "LPTokenOut": {"currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", "value": "1000"}, + "Asset": { "currency": "XRP" }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, + "LPTokenOut": { + "currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", + "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", + "value": "1000" + }, "Fee": "10", "Flags": 65536, "Sequence": 1432289, @@ -4672,8 +4735,11 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMDeposit", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { "currency": "XRP" }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", "Fee": "10", "Flags": 524288, @@ -4687,10 +4753,17 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMDeposit", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { "currency": "XRP" }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", - "Amount2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9", "value": "500"}, + "Amount2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9", + "value": "500" + }, "Fee": "10", "Flags": 1048576, "Sequence": 1432289, @@ -4703,10 +4776,17 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMDeposit", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { "currency": "XRP" }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", - "LPTokenOut": {"currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", "value": "1000"}, + "LPTokenOut": { + "currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", + "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", + "value": "1000" + }, "Fee": "10", "Flags": 2097152, "Sequence": 1432289, @@ -4719,8 +4799,11 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMDeposit", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { "currency": "XRP" }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", "EPrice": "25", "Fee": "10", @@ -4735,9 +4818,16 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMWithdraw", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, - "LPTokenIn": {"currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", "value": "1000"}, + "Asset": { "currency": "XRP" }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, + "LPTokenIn": { + "currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", + "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", + "value": "1000" + }, "Fee": "10", "Flags": 65536, "Sequence": 1432289, @@ -4750,8 +4840,11 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMWithdraw", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { "currency": "XRP" }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", "Fee": "10", "Flags": 524288, @@ -4765,10 +4858,17 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMWithdraw", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { "currency": "XRP" }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", - "Amount2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9", "value": "500"}, + "Amount2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9", + "value": "500" + }, "Fee": "10", "Flags": 1048576, "Sequence": 1432289, @@ -4781,10 +4881,17 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMWithdraw", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { "currency": "XRP" }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", - "LPTokenIn": {"currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", "value": "1000"}, + "LPTokenIn": { + "currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", + "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", + "value": "1000" + }, "Fee": "10", "Flags": 2097152, "Sequence": 1432289, @@ -4797,8 +4904,11 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMWithdraw", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { "currency": "XRP" }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", "EPrice": "25", "Fee": "10", @@ -4813,11 +4923,24 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMBid", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, - "AuthAccounts": [{"AuthAccount": {"Account": "rEaHTti4HZsMBpxTAF4ncWxkcdqDh1h6P7"}}], - "BidMax": {"currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", "value": "35"}, - "BidMin": {"currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", "value": "25"}, + "Asset": { "currency": "XRP" }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, + "AuthAccounts": [ + { "AuthAccount": { "Account": "rEaHTti4HZsMBpxTAF4ncWxkcdqDh1h6P7" } } + ], + "BidMax": { + "currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", + "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", + "value": "35" + }, + "BidMin": { + "currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", + "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", + "value": "25" + }, "Fee": "10", "Flags": 0, "Sequence": 1432289, @@ -4830,8 +4953,11 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMVote", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { "currency": "XRP" }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "TradingFee": 234, "Fee": "10", "Flags": 0, @@ -4841,74 +4967,105 @@ } }, { - "binary": "120007220000000024000195F964400000170A53AC2065D5460561EC9DE000000000000000000000000000494C53000000000092D705968936C419CE614BF264B5EEB1CEA47FF468400000000000000A7321028472865AF4CB32AA285834B57576B7290AA8C31B459047DB27E16F418D6A71667447304502202ABE08D5E78D1E74A4C18F2714F64E87B8BD57444AFA5733109EB3C077077520022100DB335EE97386E4C0591CAC024D50E9230D8F171EEB901B5E5E4BD6D1E0AEF98C811439408A69F0895E62149CFCC006FB89FA7D1E6E5D", - "json": { - "Account": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", - "Fee": "10", - "Flags": 0, - "Sequence": 103929, - "SigningPubKey": - "028472865AF4CB32AA285834B57576B7290AA8C31B459047DB27E16F418D6A7166", - "TakerGets": { - "value": "1694.768", - "currency": "ILS", - "issuer": "rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9" - }, - "TakerPays": "98957503520", - "TransactionType": "OfferCreate", - "TxnSignature": "304502202ABE08D5E78D1E74A4C18F2714F64E87B8BD57444AFA5733109EB3C077077520022100DB335EE97386E4C0591CAC024D50E9230D8F171EEB901B5E5E4BD6D1E0AEF98C" - } - }, - { - "binary": "120040210000F7E0228000000024000009186840000000000000C87321ED510865F867CDFCB944D435812ACF23D231E5C14534B146BCE46A2F794D198B777440D05A89D0B489DEC1CECBE0D33BA656C929CDCCC75D4D41B282B378544975B87A70C3E42147D980D1F6E2E4DC6316C99D7E2D4F6335F147C71C0DAA0D6516150D8114DB9157872FA63FAF7432CD300911A43B981B85A28514EBA79C385B47C50D52445DF2676EEC0231F732CEF01DEF203400000001E1EF203400000015E1F1", - "json": { - "Account": "rMryaYXZMchTWBovAzEsMzid9FUwmrmcH7", - "Authorize": "r4Vp2qvKR59guHDn4Yzw9owTzDVnt6TJZA", - "Fee": "200", - "Flags": 2147483648, - "NetworkID": 63456, - "Permissions": [ - { - "Permission": { - "PermissionValue": "Payment" - } - }, - { - "Permission": { - "PermissionValue": "TrustSet" - } - } - ], - "Sequence": 2328, - "SigningPubKey": "ED510865F867CDFCB944D435812ACF23D231E5C14534B146BCE46A2F794D198B77", - "TransactionType": "DelegateSet", - "TxnSignature": "D05A89D0B489DEC1CECBE0D33BA656C929CDCCC75D4D41B282B378544975B87A70C3E42147D980D1F6E2E4DC6316C99D7E2D4F6335F147C71C0DAA0D6516150D" - } + "binary": "120007220000000024000195F964400000170A53AC2065D5460561EC9DE000000000000000000000000000494C53000000000092D705968936C419CE614BF264B5EEB1CEA47FF468400000000000000A7321028472865AF4CB32AA285834B57576B7290AA8C31B459047DB27E16F418D6A71667447304502202ABE08D5E78D1E74A4C18F2714F64E87B8BD57444AFA5733109EB3C077077520022100DB335EE97386E4C0591CAC024D50E9230D8F171EEB901B5E5E4BD6D1E0AEF98C811439408A69F0895E62149CFCC006FB89FA7D1E6E5D", + "json": { + "Account": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", + "Fee": "10", + "Flags": 0, + "Sequence": 103929, + "SigningPubKey": "028472865AF4CB32AA285834B57576B7290AA8C31B459047DB27E16F418D6A7166", + "TakerGets": { + "value": "1694.768", + "currency": "ILS", + "issuer": "rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9" + }, + "TakerPays": "98957503520", + "TransactionType": "OfferCreate", + "TxnSignature": "304502202ABE08D5E78D1E74A4C18F2714F64E87B8BD57444AFA5733109EB3C077077520022100DB335EE97386E4C0591CAC024D50E9230D8F171EEB901B5E5E4BD6D1E0AEF98C" + } + }, + { + "binary": "120040210000F7E0228000000024000009186840000000000000C87321ED510865F867CDFCB944D435812ACF23D231E5C14534B146BCE46A2F794D198B777440D05A89D0B489DEC1CECBE0D33BA656C929CDCCC75D4D41B282B378544975B87A70C3E42147D980D1F6E2E4DC6316C99D7E2D4F6335F147C71C0DAA0D6516150D8114DB9157872FA63FAF7432CD300911A43B981B85A28514EBA79C385B47C50D52445DF2676EEC0231F732CEF01DEF203400000001E1EF203400000015E1F1", + "json": { + "Account": "rMryaYXZMchTWBovAzEsMzid9FUwmrmcH7", + "Authorize": "r4Vp2qvKR59guHDn4Yzw9owTzDVnt6TJZA", + "Fee": "200", + "Flags": 2147483648, + "NetworkID": 63456, + "Permissions": [ + { + "Permission": { + "PermissionValue": "Payment" + } + }, + { + "Permission": { + "PermissionValue": "TrustSet" + } + } + ], + "Sequence": 2328, + "SigningPubKey": "ED510865F867CDFCB944D435812ACF23D231E5C14534B146BCE46A2F794D198B77", + "TransactionType": "DelegateSet", + "TxnSignature": "D05A89D0B489DEC1CECBE0D33BA656C929CDCCC75D4D41B282B378544975B87A70C3E42147D980D1F6E2E4DC6316C99D7E2D4F6335F147C71C0DAA0D6516150D" + } }, { "binary": "12004173008114204288D2E47F8EF6C99BCC457966320D124097119300038D7EA4C68000FFFFFFF40010140103180000000000000000000000005553440000000000204288D2E47F8EF6C99BCC457966320D12409711", "json": { - "Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", - "TransactionType": "VaultCreate", - "SigningPubKey": "", - "Asset": {"currency": "USD", "issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW"}, - "AssetsMaximum": "1000", + "Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + "TransactionType": "VaultCreate", + "SigningPubKey": "", + "Asset": { + "currency": "USD", + "issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW" + }, + "AssetsMaximum": "1000", "WithdrawalPolicy": 1 } + }, + { + "binary": "201C0000000020390000197CA1FFFFFF00F8E511006125002C6B905563F4B97FFBA6D65B7C507DD24E157ADF1BED3AFF2B8EC73741B8E1BEE9F1A0A55698DC3588FBDB6A91CCF5DB14E8523E8DB7E4574C92818E87A2236A5906C71021E624002C6B8F624000000005F5E100E1E7220000000024002C6B902D00000000624000000005E69EB48114F69B176FEEA1193FE503C3D229BCBA1126916B02E1E1F10310C7", + "json": { + "AffectedNodes": [ + { + "ModifiedNode": { + "FinalFields": { + "Account": "rP7Ap93CjnFxzcGXPszoD9CQHniSJYCboN", + "Balance": "98999988", + "Flags": 0, + "OwnerCount": 0, + "Sequence": 2911120 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "98DC3588FBDB6A91CCF5DB14E8523E8DB7E4574C92818E87A2236A5906C71021", + "PreviousFields": { "Balance": "100000000", "Sequence": 2911119 }, + "PreviousTxnID": "63F4B97FFBA6D65B7C507DD24E157ADF1BED3AFF2B8EC73741B8E1BEE9F1A0A5", + "PreviousTxnLgrSeq": 2911120 + } + } + ], + "GasUsed": 6524, + "TransactionIndex": 0, + "TransactionResult": "tecWASM_REJECTED", + "WasmReturnCode": -256 + } } ], - "ledgerData": [{ - "binary": "01E91435016340767BF1C4A3EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F873B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D521276CDE21276CE60A00", - "json": { - "account_hash": "3B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D5", - "close_flags": 0, - "close_time": 556231910, - "close_time_resolution": 10, - "ledger_index": 32052277, - "parent_close_time": 556231902, - "parent_hash": "EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6", - "total_coins": "99994494362043555", - "transaction_hash": "DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F87" + "ledgerData": [ + { + "binary": "01E91435016340767BF1C4A3EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F873B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D521276CDE21276CE60A00", + "json": { + "account_hash": "3B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D5", + "close_flags": 0, + "close_time": 556231910, + "close_time_resolution": 10, + "ledger_index": 32052277, + "parent_close_time": 556231902, + "parent_hash": "EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6", + "total_coins": "99994494362043555", + "transaction_hash": "DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F87" + } } - }] + ] } diff --git a/xrpl/core/binarycodec/definitions/definitions.json b/xrpl/core/binarycodec/definitions/definitions.json index cdaed3f60..c48a30d3e 100644 --- a/xrpl/core/binarycodec/definitions/definitions.json +++ b/xrpl/core/binarycodec/definitions/definitions.json @@ -2190,6 +2190,16 @@ "type": "Number" } ], + [ + "WasmReturnCode", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 1, + "type": "Int32" + } + ], [ "TransactionMetaData", { @@ -3309,6 +3319,7 @@ "temBAD_TICK_SIZE": -269, "temBAD_TRANSFER_FEE": -251, "temBAD_TRANSFER_RATE": -280, + "temBAD_WASM": -249, "temBAD_WEIGHT": -270, "temCANNOT_PREAUTH_SELF": -267, "temDISABLED": -273, @@ -3339,7 +3350,6 @@ "terLAST": -91, "terNO_ACCOUNT": -96, "terNO_AMM": -87, - "tedADDRESS_COLLISION": -86, "terNO_AUTH": -95, "terNO_LINE": -94, "terNO_RIPPLE": -90, @@ -3405,10 +3415,10 @@ "TicketCreate": 10, "TrustSet": 20, "UNLModify": 102, - "VaultCreate": 65, "VaultClawback": 70, - "VaultDeposit": 68, + "VaultCreate": 65, "VaultDelete": 67, + "VaultDeposit": 68, "VaultSet": 66, "VaultWithdraw": 69, "XChainAccountCreateCommit": 44, @@ -3430,6 +3440,8 @@ "Hash160": 17, "Hash192": 21, "Hash256": 5, + "Int32": 10, + "Int64": 11, "Issue": 24, "LedgerEntry": 10002, "Metadata": 10004, diff --git a/xrpl/core/binarycodec/types/__init__.py b/xrpl/core/binarycodec/types/__init__.py index 66e14cc0d..958d6e6fa 100644 --- a/xrpl/core/binarycodec/types/__init__.py +++ b/xrpl/core/binarycodec/types/__init__.py @@ -9,6 +9,7 @@ from xrpl.core.binarycodec.types.hash160 import Hash160 from xrpl.core.binarycodec.types.hash192 import Hash192 from xrpl.core.binarycodec.types.hash256 import Hash256 +from xrpl.core.binarycodec.types.int32 import Int32 from xrpl.core.binarycodec.types.issue import Issue from xrpl.core.binarycodec.types.number import Number from xrpl.core.binarycodec.types.path_set import PathSet @@ -32,6 +33,7 @@ "Hash160", "Hash192", "Hash256", + "Int32", "Issue", "Number", "PathSet", diff --git a/xrpl/core/binarycodec/types/int.py b/xrpl/core/binarycodec/types/int.py new file mode 100644 index 000000000..e9ae5fd65 --- /dev/null +++ b/xrpl/core/binarycodec/types/int.py @@ -0,0 +1,27 @@ +"""Base class for serializing and deserializing signed integers. +See `UInt Fields `_ +""" + +from __future__ import annotations + +from typing_extensions import Final, Self + +from xrpl.core.binarycodec.types.uint import UInt + +_WIDTH: Final[int] = 4 # 32 / 8 + + +class Int(UInt): + """Base class for serializing and deserializing unsigned integers. + See `UInt Fields `_ + """ + + @property + def value(self: Self) -> int: + """ + Get the value of the Int represented by `self.buffer`. + + Returns: + The int value of the Int. + """ + return int.from_bytes(self.buffer, byteorder="big", signed=True) diff --git a/xrpl/core/binarycodec/types/int32.py b/xrpl/core/binarycodec/types/int32.py new file mode 100644 index 000000000..3488c49cc --- /dev/null +++ b/xrpl/core/binarycodec/types/int32.py @@ -0,0 +1,71 @@ +"""Class for serializing and deserializing a 32-bit Int. +See `UInt Fields `_ +""" + +from __future__ import annotations + +from typing import Optional, Type, Union + +from typing_extensions import Final, Self + +from xrpl.core.binarycodec.binary_wrappers.binary_parser import BinaryParser +from xrpl.core.binarycodec.exceptions import XRPLBinaryCodecException +from xrpl.core.binarycodec.types.int import Int + +_WIDTH: Final[int] = 4 # 32 / 8 + + +class Int32(Int): + """ + Class for serializing and deserializing a 32-bit Int. + See `UInt Fields `_ + """ + + def __init__(self: Self, buffer: bytes = bytes(_WIDTH)) -> None: + """Construct a new Int32 type from a ``bytes`` value.""" + super().__init__(buffer) + + @classmethod + def from_parser( + cls: Type[Self], parser: BinaryParser, _length_hint: Optional[int] = None + ) -> Self: + """ + Construct a new Int32 type from a BinaryParser. + + Args: + parser: A BinaryParser to construct a Int32 from. + + Returns: + The Int32 constructed from parser. + """ + return cls(parser.read(_WIDTH)) + + @classmethod + def from_value(cls: Type[Self], value: Union[str, int]) -> Self: + """ + Construct a new Int32 type from a number. + + Args: + value: The number to construct a Int32 from. + + Returns: + The Int32 constructed from value. + + Raises: + XRPLBinaryCodecException: If a Int32 could not be constructed from value. + """ + if not isinstance(value, (str, int)): + raise XRPLBinaryCodecException( + "Invalid type to construct a Int32: expected str or int," + " received {value.__class__.__name__}." + ) + + if isinstance(value, int): + value_bytes = (value).to_bytes(_WIDTH, byteorder="big", signed=True) + return cls(value_bytes) + + if isinstance(value, str) and value.isdigit(): + value_bytes = (int(value)).to_bytes(_WIDTH, byteorder="big", signed=True) + return cls(value_bytes) + + raise XRPLBinaryCodecException("Cannot construct Int32 from given value") From 7cf2d6406df61b37aaa42702c7ac43a258c713b9 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 15 Sep 2025 18:16:35 -0400 Subject: [PATCH 28/32] model/autofill changes --- xrpl/asyncio/transaction/main.py | 13 +++++++++++++ .../transactions/pseudo_transactions/set_fee.py | 6 ++++++ 2 files changed, 19 insertions(+) diff --git a/xrpl/asyncio/transaction/main.py b/xrpl/asyncio/transaction/main.py index 09cb7def6..08e6887e1 100644 --- a/xrpl/asyncio/transaction/main.py +++ b/xrpl/asyncio/transaction/main.py @@ -41,6 +41,10 @@ _REQUIRED_NETWORKID_VERSION = "1.11.0" _MICRO_DROPS_PER_DROP = 1_000_000 + +_WASM_FIXED_UPLOAD_COST = 100 +_WASM_DROPS_PER_BYTE = 5 + T = TypeVar("T", bound=Transaction, default=Transaction) @@ -493,6 +497,15 @@ async def _calculate_fee_per_transaction_type( base_fee = net_fee + if transaction.transaction_type == TransactionType.ESCROW_CREATE: + escrow_create = cast(EscrowCreate, transaction) + if escrow_create.finish_function is not None: + base_fee += _WASM_FIXED_UPLOAD_COST + base_fee += ( + _WASM_DROPS_PER_BYTE + * len(escrow_create.finish_function.encode("utf-8")) + ) // 2 + # EscrowFinish Transaction with Fulfillment # https://xrpl.org/escrowfinish.html#escrowfinish-fields if transaction.transaction_type == TransactionType.ESCROW_FINISH: diff --git a/xrpl/models/transactions/pseudo_transactions/set_fee.py b/xrpl/models/transactions/pseudo_transactions/set_fee.py index 37b58c98e..c411bcdf7 100644 --- a/xrpl/models/transactions/pseudo_transactions/set_fee.py +++ b/xrpl/models/transactions/pseudo_transactions/set_fee.py @@ -90,6 +90,12 @@ class SetFee(PseudoTransaction): :meta hide-value: """ + extension_compute_limit: Optional[int] = None + + extension_size_limit: Optional[int] = None + + gas_price: Optional[int] = None + transaction_type: PseudoTransactionType = field( default=PseudoTransactionType.SET_FEE, init=False, From 7130525d76ef248b2180c935370fa7cdf345c6cb Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 15 Sep 2025 18:19:02 -0400 Subject: [PATCH 29/32] fix tests --- tests/integration/transactions/test_escrow.py | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/tests/integration/transactions/test_escrow.py b/tests/integration/transactions/test_escrow.py index 5cb1afa99..dcda2d6d9 100644 --- a/tests/integration/transactions/test_escrow.py +++ b/tests/integration/transactions/test_escrow.py @@ -30,23 +30,21 @@ SOURCE_TAG = 11747 FINISH_FUNCTION = ( - "0061736d0100000001150460027f7f017f60037f7f7e017f6000017f60000002300208686f73745f6" - "c69620e6765745f6c65646765725f73716e000008686f73745f6c69620974726163655f6e756d0001" - "030302020305030100110619037f01418080c0000b7f00418b80c0000b7f00419080c0000b072e040" - "66d656d6f727902000666696e69736800020a5f5f646174615f656e6403010b5f5f686561705f6261" - "736503020a69026301027f23808080800041106b22002480808080002000410036020c02402000410" - "c6a41081080808080002201417f4a0d00418080c08000410b2001ac1081808080001a108380808000" - "000b200028020c2101200041106a248080808000200141044b0b0300000b0b140100418080c0000b0" - "b6572726f725f636f64653d00dd01046e616d6500100f6c65646765725f73716e2e7761736d01a301" - "0400355f5a4e387872706c5f73746434686f737431346765745f6c65646765725f73716e313768666" - "5343539333764623461656439366245012f5f5a4e387872706c5f73746434686f7374397472616365" - "5f6e756d3137686139376531613763346138636231333245020666696e69736803305f5a4e34636f7" - "2653970616e69636b696e673970616e69635f666d7431376862393162616461636536656538323837" - "45071201000f5f5f737461636b5f706f696e746572090a0100072e726f64617461004d0970726f647" - "56365727302086c616e6775616765010452757374000c70726f6365737365642d6279010572757374" - "631d312e38352e31202834656231363132353020323032352d30332d31352900490f7461726765745" - "f6665617475726573042b0a6d756c746976616c75652b0f6d757461626c652d676c6f62616c732b0f" - "7265666572656e63652d74797065732b087369676e2d657874" + "0061736d010000000108026000017f60000002160103656e760e6765745f6c65646765725f" + "73716e000003030201000503010002063e0a7f004180080b7f004180080b7f004180100b7f" + "004180100b7f00418090040b7f004180080b7f00418090040b7f00418080080b7f0041000b" + "7f0041010b07b0010d066d656d6f72790200115f5f7761736d5f63616c6c5f63746f727300" + "010666696e69736800020362756603000c5f5f64736f5f68616e646c6503010a5f5f646174" + "615f656e6403020b5f5f737461636b5f6c6f7703030c5f5f737461636b5f6869676803040d" + "5f5f676c6f62616c5f6261736503050b5f5f686561705f6261736503060a5f5f686561705f" + "656e6403070d5f5f6d656d6f72795f6261736503080c5f5f7461626c655f6261736503090a" + "150202000b1001017f100022004100200041044b1b0b007f0970726f647563657273010c70" + "726f6365737365642d62790105636c616e675f31392e312e352d776173692d73646b202868" + "747470733a2f2f6769746875622e636f6d2f6c6c766d2f6c6c766d2d70726f6a6563742061" + "62346235613264623538323935386166316565333038613739306366646234326264323437" + "32302900490f7461726765745f6665617475726573042b0f6d757461626c652d676c6f6261" + "6c732b087369676e2d6578742b0f7265666572656e63652d74797065732b0a6d756c746976" + "616c7565" ) issuer = Wallet.create() From 94f32cf830e9b02aff9335074e5506fb5b98b15b Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 15 Sep 2025 18:23:18 -0400 Subject: [PATCH 30/32] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f595c23ea..91d245b3b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "xrpl-py" -version = "4.4.0b0" +version = "4.4.0b1" description = "A complete Python library for interacting with the XRP ledger (Smart Escrow beta)" license = "ISC" readme = "README.md" From 1fe939a29e834606b7a0b428f4f64e9b358cb9be Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 29 Oct 2025 13:09:29 -0400 Subject: [PATCH 31/32] update definitions --- tools/generate_definitions.py | 2 +- .../binarycodec/definitions/definitions.json | 20 ++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/generate_definitions.py b/tools/generate_definitions.py index 8355559cd..a5aa581f6 100644 --- a/tools/generate_definitions.py +++ b/tools/generate_definitions.py @@ -321,7 +321,7 @@ def _unhex(x: str) -> str: # Example line: # TRANSACTION(ttCHECK_CREATE, 16, CheckCreate, ({ tx_hits = re.findall( - r"^ *TRANSACTION\(tt[A-Z_]+ *,* ([0-9]+) *, *([A-Za-z]+).*$", + r"^ *TRANSACTION\(tt[A-Z_]+[ \n]*,* ([0-9]+)[ \n]*,[ \n]*([A-Za-z]+).*$", transactions_file, re.MULTILINE, ) diff --git a/xrpl/core/binarycodec/definitions/definitions.json b/xrpl/core/binarycodec/definitions/definitions.json index c48a30d3e..f63c27a4b 100644 --- a/xrpl/core/binarycodec/definitions/definitions.json +++ b/xrpl/core/binarycodec/definitions/definitions.json @@ -681,7 +681,7 @@ } ], [ - "ExtensionComputeLimit", + "MutableFlags", { "isSerialized": true, "isSigningField": true, @@ -691,7 +691,7 @@ } ], [ - "ExtensionSizeLimit", + "ExtensionComputeLimit", { "isSerialized": true, "isSigningField": true, @@ -701,7 +701,7 @@ } ], [ - "GasPrice", + "ExtensionSizeLimit", { "isSerialized": true, "isSigningField": true, @@ -711,7 +711,7 @@ } ], [ - "ComputationAllowance", + "GasPrice", { "isSerialized": true, "isSigningField": true, @@ -721,7 +721,7 @@ } ], [ - "GasUsed", + "ComputationAllowance", { "isSerialized": true, "isSigningField": true, @@ -730,6 +730,16 @@ "type": "UInt32" } ], + [ + "GasUsed", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 58, + "type": "UInt32" + } + ], [ "IndexNext", { From 52aafa2371169451884035ef10dc1975c6b279b6 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 29 Oct 2025 13:12:23 -0400 Subject: [PATCH 32/32] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ab0257f73..2310b2240 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "xrpl-py" -version = "4.4.0b1" +version = "4.4.0b2" description = "A complete Python library for interacting with the XRP ledger (Smart Escrow beta)" license = "ISC" readme = "README.md"