mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2026-04-29 15:37:48 +00:00
165 lines
5.8 KiB
Python
165 lines
5.8 KiB
Python
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
from xrpl.clients import JsonRpcClient
|
|
from xrpl.models import VaultWithdraw
|
|
from xrpl.models.requests import VaultInfo, LedgerEntry
|
|
from xrpl.transaction import submit_and_wait
|
|
from xrpl.wallet import Wallet
|
|
|
|
# Auto-run setup if needed
|
|
if not os.path.exists("vault_setup.json"):
|
|
print("\n=== Vault setup data doesn't exist. Running setup script... ===\n")
|
|
subprocess.run([sys.executable, "vault_setup.py"], check=True)
|
|
|
|
# Load setup data
|
|
with open("vault_setup.json", "r") as f:
|
|
setup_data = json.load(f)
|
|
|
|
# Connect to the network
|
|
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
|
|
|
|
# You can replace these values with your own
|
|
depositor = Wallet.from_seed(setup_data["depositor"]["seed"])
|
|
vault_id = setup_data["vault_id"]
|
|
asset_mpt_issuance_id = setup_data["mpt_issuance_id"]
|
|
share_mpt_issuance_id = setup_data["vault_share_mpt_issuance_id"]
|
|
|
|
print(f"Depositor address: {depositor.address}")
|
|
print(f"Vault ID: {vault_id}")
|
|
print(f"Asset MPT issuance ID: {asset_mpt_issuance_id}")
|
|
print(f"Vault share MPT issuance ID: {share_mpt_issuance_id}")
|
|
|
|
withdraw_amount = 1
|
|
|
|
# Get initial vault state
|
|
print("\n=== Getting initial vault state... ===")
|
|
initial_vault_info = client.request(
|
|
VaultInfo(
|
|
vault_id=vault_id,
|
|
ledger_index="validated"
|
|
)
|
|
)
|
|
|
|
print("Initial vault state:")
|
|
print(f" Assets Total: {initial_vault_info.result['vault']['AssetsTotal']}")
|
|
print(f" Assets Available: {initial_vault_info.result['vault']['AssetsAvailable']}")
|
|
|
|
# Check depositor's share balance
|
|
print("\n=== Checking depositor's share balance... ===")
|
|
try:
|
|
share_balance_result = client.request(
|
|
LedgerEntry(
|
|
mptoken={
|
|
"mpt_issuance_id": share_mpt_issuance_id,
|
|
"account": depositor.address
|
|
},
|
|
ledger_index="validated"
|
|
)
|
|
)
|
|
|
|
share_balance = share_balance_result.result["node"]["MPTAmount"]
|
|
print(f"Shares held: {share_balance}")
|
|
except Exception as error:
|
|
error_data = getattr(error, 'data', {})
|
|
if 'error' in error_data and error_data['error'] == 'entryNotFound':
|
|
print(f"Error: The depositor doesn't hold any vault shares with ID: {share_mpt_issuance_id}.", file=sys.stderr)
|
|
else:
|
|
print(f"Error checking MPT: {error}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
# Prepare VaultWithdraw transaction
|
|
print("\n=== Preparing VaultWithdraw transaction ===")
|
|
vault_withdraw_tx = VaultWithdraw(
|
|
account=depositor.address,
|
|
vault_id=vault_id,
|
|
amount={
|
|
"mpt_issuance_id": asset_mpt_issuance_id,
|
|
"value": str(withdraw_amount)
|
|
}
|
|
# Optional: Add destination field to send assets to a different account
|
|
# destination="rGg4tHPRGJfewwJkd8immCFx9uSo2GgcoY"
|
|
)
|
|
|
|
print(json.dumps(vault_withdraw_tx.to_xrpl(), indent=2))
|
|
|
|
# Submit VaultWithdraw transaction
|
|
print("\n=== Submitting VaultWithdraw transaction... ===")
|
|
withdraw_result = submit_and_wait(vault_withdraw_tx, client, depositor, autofill=True)
|
|
|
|
if withdraw_result.result["meta"]["TransactionResult"] != "tesSUCCESS":
|
|
result_code = withdraw_result.result["meta"]["TransactionResult"]
|
|
print(f"Error: Unable to withdraw from vault: {result_code}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
print("Withdrawal successful!")
|
|
|
|
# Extract vault state from transaction metadata
|
|
print("\n=== Vault state after withdrawal ===")
|
|
affected_nodes = withdraw_result.result["meta"]["AffectedNodes"]
|
|
vault_node = None
|
|
for node in affected_nodes:
|
|
if "ModifiedNode" in node or "DeletedNode" in node:
|
|
modified_node = node["ModifiedNode"] if "ModifiedNode" in node else node["DeletedNode"]
|
|
if modified_node["LedgerEntryType"] == "Vault" and modified_node["LedgerIndex"] == vault_id:
|
|
vault_node = node
|
|
break
|
|
|
|
if vault_node:
|
|
if "DeletedNode" in vault_node:
|
|
print(" Vault empty (all assets withdrawn)")
|
|
else:
|
|
vault_fields = vault_node["ModifiedNode"]["FinalFields"]
|
|
print(f" Assets Total: {vault_fields['AssetsTotal']}")
|
|
print(f" Assets Available: {vault_fields['AssetsAvailable']}")
|
|
|
|
# Get the depositor's share balance
|
|
print("\n=== Depositor's share balance ===")
|
|
depositor_share_node = None
|
|
for node in affected_nodes:
|
|
if "ModifiedNode" in node or "DeletedNode" in node:
|
|
modified_node = node["ModifiedNode"] if "ModifiedNode" in node else node["DeletedNode"]
|
|
if "FinalFields" in modified_node:
|
|
fields = modified_node["FinalFields"]
|
|
if (modified_node["LedgerEntryType"] == "MPToken" and
|
|
fields["Account"] == depositor.address and
|
|
fields["MPTokenIssuanceID"] == share_mpt_issuance_id):
|
|
depositor_share_node = node
|
|
break
|
|
|
|
if depositor_share_node:
|
|
if "DeletedNode" in depositor_share_node:
|
|
print("No more shares held (redeemed all shares)")
|
|
else:
|
|
share_fields = depositor_share_node["ModifiedNode"]["FinalFields"]
|
|
print(f"Shares held: {share_fields['MPTAmount']}")
|
|
|
|
# Get the depositor's asset balance
|
|
print("\n=== Depositor's asset balance ===")
|
|
depositor_asset_node = None
|
|
for node in affected_nodes:
|
|
if "ModifiedNode" in node:
|
|
asset_node = node["ModifiedNode"]
|
|
fields = asset_node["FinalFields"]
|
|
elif "CreatedNode" in node:
|
|
asset_node = node["CreatedNode"]
|
|
fields = asset_node["NewFields"]
|
|
else:
|
|
continue
|
|
|
|
if (asset_node["LedgerEntryType"] == "MPToken" and
|
|
fields["Account"] == depositor.address and
|
|
fields["MPTokenIssuanceID"] == asset_mpt_issuance_id):
|
|
depositor_asset_node = node
|
|
break
|
|
|
|
if depositor_asset_node:
|
|
if "ModifiedNode" in depositor_asset_node:
|
|
asset_fields = depositor_asset_node["ModifiedNode"]["FinalFields"]
|
|
else:
|
|
asset_fields = depositor_asset_node["CreatedNode"]["NewFields"]
|
|
print(f"Balance: {asset_fields['MPTAmount']}")
|
|
|