Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
f0a0f58
models for SAV transactions and requests
ckeshava Jan 23, 2025
e4e9ec5
initial framework of integration tests; definitions file
ckeshava Jan 24, 2025
5d015a3
provide MPT support for SAV transaction fields
ckeshava Feb 4, 2025
6ea3965
Test extreme values in the serialzation of STAmount
ckeshava Feb 4, 2025
f06f909
Problems in STAmount: Unable to (de)serialize extreme values
ckeshava Feb 4, 2025
2858df2
[WIP] use struct library to pack Number data
ckeshava Feb 4, 2025
3e86842
Merge remote-tracking branch 'upstream/main' into sav
ckeshava Feb 27, 2025
ea1ef24
[WIP] VaultClawback integ tests need to be completed; Errors regardin…
ckeshava Feb 27, 2025
6966ae7
add integ test for VaultClawback transaction
ckeshava Feb 27, 2025
24b4df0
Enforce proper serialization of Number types
ckeshava Mar 4, 2025
3646909
docs explanation of transaction models
ckeshava Mar 5, 2025
307c515
handle 0 case in Number type
ckeshava Mar 5, 2025
e97a4b7
simplify the extractNumberParts logic; Avoid using magic numbers;
ckeshava Mar 5, 2025
1617cad
introduce model for MPTIssue
ckeshava Mar 5, 2025
671690a
Update VaultCreate model to include Withdrawal Policy
ckeshava Mar 6, 2025
b09b37a
remove irrelevant tests for amount binary codec
ckeshava Mar 6, 2025
537cc2f
reorder the REQUIRED fields to be at the top of the transactions mode…
ckeshava Mar 6, 2025
6c4f801
pretty print of Number values
ckeshava Mar 6, 2025
2765937
update the data member name of the MPTIssue class
ckeshava Mar 6, 2025
18bfd1c
pacify linter errors
ckeshava Mar 6, 2025
f967f23
Update tests/unit/core/binarycodec/types/test_number.py
ckeshava Mar 6, 2025
eb78553
Accept mypy suggestions
ckeshava Mar 7, 2025
4cb1d02
use custom method of Number class for debugging unit tests
ckeshava Mar 7, 2025
f4830a0
Update definitions, transaction-models with the latest cpp implementa…
ckeshava Jun 3, 2025
0abade7
Update CHANGELOG.md
ckeshava Jun 3, 2025
a1073b3
Model and Integ-tests for VaultInfo Request
ckeshava Jun 4, 2025
dd20aa8
Merge branch 'main' into sav
ckeshava Jun 4, 2025
4e7343b
fix linter errors
ckeshava Jun 4, 2025
edd5400
remove unused type:ignore directives
ckeshava Jun 4, 2025
d7a903f
Merge branch 'main' into sav
ckeshava Jun 4, 2025
c90479c
Use updated name for withdrawal policy
ckeshava Jun 13, 2025
5a3b29c
Merge branch 'main' into sav
ckeshava Jun 13, 2025
12b7819
Merge branch 'sav' of https://github.com/ckeshava/xrpl-py into HEAD
ckeshava Jun 13, 2025
f00a4c5
update flag values in VaultCreate transaction
ckeshava Jun 13, 2025
afbd4e5
Update .ci-config/rippled.cfg
ckeshava Jun 13, 2025
27ff509
Merge branch 'main' into sav
ckeshava Jun 20, 2025
b2c2de7
Update xrpl/core/binarycodec/types/number.py
ckeshava Jun 20, 2025
9488ae9
remove duplicate entries in the tec-codes and transaction-types of de…
ckeshava Jun 20, 2025
ebb70ec
Address comments from Raj Patel
ckeshava Jun 20, 2025
2dc7e25
fix: update the length of domain_id field check
ckeshava Jun 20, 2025
a2619de
VaultCreate: Add enum for representing Withdrawal Strategy input
ckeshava Jun 20, 2025
56a19e8
vault_info: additional validation for request input specification'
ckeshava Jun 23, 2025
de2131e
fix: update the import statements
ckeshava Jun 23, 2025
4b2084d
Update tests/unit/models/requests/test_vault_info.py
ckeshava Jun 23, 2025
eb0260e
fix: Length field check in Hash256 fields for VaultCreate transaction
ckeshava Jun 23, 2025
4e9a805
fix: Update length checkk on VaultSet transaction
ckeshava Jun 23, 2025
9c11f46
remove integ test -- code is already covered under binary_codec tests
ckeshava Jun 24, 2025
e6f591f
vault_clawback: do not allow XRP amounts inside VaultClawback transac…
ckeshava Jun 25, 2025
3661d9a
address comments from Phu
ckeshava Jun 30, 2025
260b69f
Merge branch 'main' into sav
ckeshava Jul 2, 2025
217cace
Update xrpl/models/requests/vault_info.py
ckeshava Jul 2, 2025
4e728b5
Update xrpl/models/transactions/vault_delete.py
ckeshava Jul 2, 2025
6a1be36
Update xrpl/core/binarycodec/definitions/definitions.json
ckeshava Jul 2, 2025
dfc19ff
address PR comments from Omart
ckeshava Jul 2, 2025
34cee18
revert clawback transaction model
ckeshava Jul 2, 2025
16bbc80
fix typo in the declaration of Clawback Amount
ckeshava Jul 2, 2025
25e204e
remove unneeded import
ckeshava Jul 2, 2025
9144d2c
address Omar PR suggestions
ckeshava Jul 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .ci-config/rippled.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ fixEnforceNFTokenTrustline
fixReducedOffersV2
DeepFreeze
PermissionedDomains
SingleAssetVault

# This section can be used to simulate various FeeSettings scenarios for rippled node in standalone mode
[voting]
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- Improved validation for models to also check param types
- Support for Single Asset Vault (XLS-65d)

## [4.1.0] - 2025-2-13

Expand Down
135 changes: 135 additions & 0 deletions tests/integration/transactions/test_sav.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
from tests.integration.integration_test_case import IntegrationTestCase
from tests.integration.it_utils import (
fund_wallet_async,
sign_and_reliable_submission_async,
test_async_and_sync,
)
from tests.integration.reusable_values import WALLET
from xrpl.models import (
Payment,
TrustSet,
VaultClawback,
VaultCreate,
VaultDelete,
VaultDeposit,
VaultSet,
VaultWithdraw,
)
from xrpl.models.amounts.issued_currency_amount import IssuedCurrencyAmount
from xrpl.models.currencies import IssuedCurrency
from xrpl.models.requests import AccountObjects
from xrpl.models.requests.account_objects import AccountObjectType
from xrpl.models.response import ResponseStatus
from xrpl.utils import str_to_hex
from xrpl.wallet import Wallet


class TestSingleAssetVault(IntegrationTestCase):
@test_async_and_sync(globals())
async def test_sav_lifecycle(self, client):

vault_owner = Wallet.create()
await fund_wallet_async(vault_owner)

issuer_wallet = Wallet.create()
await fund_wallet_async(issuer_wallet)

# Step-0.a: Prerequisites: Set up the IOU trust line
tx = TrustSet(
account=WALLET.address,
limit_amount=IssuedCurrencyAmount(
currency="USD", issuer=issuer_wallet.address, value="1000"
),
)
response = await sign_and_reliable_submission_async(tx, WALLET, client)
self.assertEqual(response.status, ResponseStatus.SUCCESS)
self.assertEqual(response.result["engine_result"], "tesSUCCESS")

# Step-0.b: Send the payment of IOUs from issuer_wallet to WALLET
tx = Payment(
account=issuer_wallet.address,
amount=IssuedCurrencyAmount(
currency="USD", issuer=issuer_wallet.address, value="1000"
),
destination=WALLET.address,
)
response = await sign_and_reliable_submission_async(tx, issuer_wallet, client)
self.assertEqual(response.status, ResponseStatus.SUCCESS)
self.assertEqual(response.result["engine_result"], "tesSUCCESS")

# Step-1: Create a vault
tx = VaultCreate(
account=vault_owner.address,
asset=IssuedCurrency(currency="USD", issuer=issuer_wallet.address),
asset_maximum="1000",
withdrawal_policy=1,
)
response = await sign_and_reliable_submission_async(tx, vault_owner, client)
self.assertEqual(response.status, ResponseStatus.SUCCESS)
self.assertEqual(response.result["engine_result"], "tesSUCCESS")

# Verify the existence of the vault with account_objects RPC call
account_objects_response = await client.request(
AccountObjects(account=vault_owner.address, type=AccountObjectType.VAULT)
)
self.assertEqual(len(account_objects_response.result["account_objects"]), 1)

VAULT_ID = account_objects_response.result["account_objects"][0]["index"]

# Step-2: Update the characteristics of the vault with VaultSet transaction
tx = VaultSet(
account=vault_owner.address,
vault_id=VAULT_ID,
data=str_to_hex("auxilliary data pertaining to the vault"),
)
response = await sign_and_reliable_submission_async(tx, vault_owner, client)
self.assertEqual(response.status, ResponseStatus.SUCCESS)
self.assertEqual(response.result["engine_result"], "tesSUCCESS")

# Step-3: Execute a VaultDeposit transaction
tx = VaultDeposit(
account=WALLET.address,
vault_id=VAULT_ID,
amount=IssuedCurrencyAmount(
currency="USD", issuer=issuer_wallet.address, value="10"
),
)
response = await sign_and_reliable_submission_async(tx, WALLET, client)
self.assertEqual(response.status, ResponseStatus.SUCCESS)
self.assertEqual(response.result["engine_result"], "tesSUCCESS")

# Step-4: Execute a VaultWithdraw transaction
tx = VaultWithdraw(
account=WALLET.address,
vault_id=VAULT_ID,
amount=IssuedCurrencyAmount(
currency="USD", issuer=issuer_wallet.address, value="9"
),
)
response = await sign_and_reliable_submission_async(tx, WALLET, client)
self.assertEqual(response.status, ResponseStatus.SUCCESS)
self.assertEqual(response.result["engine_result"], "tesSUCCESS")

# Step-5: Execute a VaultClawback transaction from issuer_wallet
tx = VaultClawback(
holder=WALLET.address,
account=issuer_wallet.address,
vault_id=VAULT_ID,
# Note: Although the amount is specified as 9, 1 unit of the IOU will be
# clawed back, because that is the remaining balance in the vault
amount=IssuedCurrencyAmount(
currency="USD", issuer=issuer_wallet.address, value="9"
),
)
response = await sign_and_reliable_submission_async(tx, issuer_wallet, client)
self.assertEqual(response.status, ResponseStatus.SUCCESS)
self.assertEqual(response.result["engine_result"], "tesSUCCESS")

# Step-6: Delete the Vault with VaultDelete transaction
tx = VaultDelete(
account=vault_owner.address,
vault_id=VAULT_ID,
)
response = await sign_and_reliable_submission_async(tx, vault_owner, client)
self.assertEqual(response.status, ResponseStatus.SUCCESS)
self.assertEqual(response.result["engine_result"], "tesSUCCESS")
42 changes: 42 additions & 0 deletions tests/unit/core/binarycodec/types/test_number.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import unittest

from xrpl.core.binarycodec.types.number import Number


class TestNumber(unittest.TestCase):
def test_serialization_and_deserialization(self):
serialized_number = Number.from_value("124")
self.assertEqual(serialized_number.to_json(), "124")

serialized_number = Number.from_value("1000")
self.assertEqual(serialized_number.to_json(), "1000")

serialized_number = Number.from_value("0")
self.assertEqual(serialized_number.to_json(), "0")

serialized_number = Number.from_value("-1")
self.assertEqual(serialized_number.to_json(), "-1")

serialized_number = Number.from_value("-10")
self.assertEqual(serialized_number.to_json(), "-10")

serialized_number = Number.from_value("123.456")
self.assertEqual(serialized_number.to_json(), "123.456")

serialized_number = Number.from_value("1.456e-45")
self.assertEqual(serialized_number.to_json(), "1456000000000000e-60")

serialized_number = Number.from_value("0.456e34")
self.assertEqual(serialized_number.to_json(), "4560000000000000e18")

serialized_number = Number.from_value("4e34")
self.assertEqual(serialized_number.to_json(), "4000000000000000e19")

def extreme_limits(self):
lowest_mantissa = "-9223372036854776"
serialized_number = Number.from_value(lowest_mantissa + "e3")
self.assertEqual(serialized_number.hex(), "FFDF3B645A1CAC0800000003")

highest_mantissa = "9223372036854776"
serialized_number = Number.from_value(highest_mantissa + "e3")
self.assertEqual(serialized_number.hex(), "0020C49BA5E353F700000003")
1 change: 1 addition & 0 deletions xrpl/asyncio/transaction/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ async def _calculate_fee_per_transaction_type(
if transaction.transaction_type in (
TransactionType.ACCOUNT_DELETE,
TransactionType.AMM_CREATE,
TransactionType.VAULT_CREATE,
):
base_fee = await _fetch_owner_reserve_fee(client)

Expand Down
78 changes: 78 additions & 0 deletions xrpl/core/binarycodec/definitions/definitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -1260,6 +1260,16 @@
"type": "Hash256"
}
],
[
"VaultID",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 35,
"type": "Hash256"
}
],
[
"hash",
{
Expand Down Expand Up @@ -2030,6 +2040,56 @@
"type": "AccountID"
}
],
[
"Number",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 1,
"type": "Number"
}
],
[
"AssetAvailable",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 2,
"type": "Number"
}
],
[
"AssetMaximum",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 3,
"type": "Number"
}
],
[
"AssetTotal",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 4,
"type": "Number"
}
],
[
"LossUnrealized",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 5,
"type": "Number"
}
],
[
"TransactionMetaData",
{
Expand Down Expand Up @@ -2639,6 +2699,16 @@
"type": "UInt8"
}
],
[
"WithdrawalPolicy",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 20,
"type": "UInt8"
}
],
[
"TakerPaysCurrency",
{
Expand Down Expand Up @@ -2886,6 +2956,7 @@
"RippleState": 114,
"SignerList": 83,
"Ticket": 84,
"Vault" : 131,
"XChainOwnedClaimID": 113,
"XChainOwnedCreateAccountClaimID": 116
},
Expand Down Expand Up @@ -3123,6 +3194,12 @@
"TicketCreate": 10,
"TrustSet": 20,
"UNLModify": 102,
"VaultCreate": 64,
"VaultClawback": 69,
"VaultDeposit": 67,
"VaultDelete": 66,
"VaultSet": 65,
"VaultWithdraw": 68,
"XChainAccountCreateCommit": 44,
"XChainAddAccountCreateAttestation": 46,
"XChainAddClaimAttestation": 45,
Expand All @@ -3146,6 +3223,7 @@
"LedgerEntry": 10002,
"Metadata": 10004,
"NotPresent": 0,
"Number": 9,
"PathSet": 18,
"STArray": 15,
"STObject": 14,
Expand Down
2 changes: 2 additions & 0 deletions xrpl/core/binarycodec/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from xrpl.core.binarycodec.types.hash192 import Hash192
from xrpl.core.binarycodec.types.hash256 import Hash256
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
from xrpl.core.binarycodec.types.st_array import STArray
from xrpl.core.binarycodec.types.st_object import STObject
Expand All @@ -32,6 +33,7 @@
"Hash192",
"Hash256",
"Issue",
"Number",
"PathSet",
"STObject",
"STArray",
Expand Down
Loading
Loading