# Deposit into a Vault

This tutorial shows you how to deposit assets into a [single asset vault](/ja/docs/concepts/tokens/single-asset-vaults). The example demonstrates depositing into a private vault with credential-based access control, however you can easily use the same code to deposit into a public vault.

When you deposit into a vault, you receive shares that represent your proportional ownership of the vault's assets. For example, in an institutional lending context, depositing into a vault allows you to pool your assets with other depositors to participate in larger lending markets.

Warning
Anyone can create a public vault, and malicious vault owners can drain your assets. Always verify that the vault owner and vault settings meet your standards before depositing assets.

SingleAssetVault
## Goals

By the end of this tutorial, you will be able to:

- Deposit assets into a private/public vault.
- Check the depositing account's share balance and the vault's state after a successful deposit.


## Prerequisites

To complete this tutorial, you should:

- Have a basic understanding of the XRP Ledger.
- Have access to an existing vault. This tutorial uses a preconfigured vault. To create your own vault, see [Create a Single Asset Vault](/ja/docs/tutorials/defi/lending/use-single-asset-vaults/create-a-single-asset-vault).
- Have an XRP Ledger client library set up in your development environment. This page provides examples for the following:
  - **JavaScript** with the [xrpl.js library](https://github.com/XRPLF/xrpl.js). See [Get Started Using JavaScript](/docs/tutorials/get-started/get-started-javascript) for setup steps.
  - **Python** with the [xrpl-py library](https://github.com/XRPLF/xrpl-py). See [Get Started Using Python](/docs/tutorials/get-started/get-started-python) for setup steps.


## Source Code

You can find the complete source code for this tutorial's examples in the code samples section of this website's repository.

## Steps

### 1. Install dependencies

JavaScript
From the code sample folder, use `npm` to install dependencies:


```bash
npm install xrpl
```

Python
From the code sample folder, set up a virtual environment and use `pip` to install dependencies:


```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

### 2. Set up client and accounts

To get started, import the necessary libraries and instantiate a client to connect to the XRPL. This example imports:

JavaScript
- `xrpl`: Used for XRPL client connection and transaction handling.
- `fs` and `child_process`: Used to run tutorial setup scripts.



```js
// IMPORTANT: This example deposits into an existing PRIVATE vault.
// The depositor account used has valid credentials in the vault's Permissioned Domain.
// Without valid credentials, the VaultDeposit transaction will fail.
// If you want to deposit into a public vault, you can replace the vaultID and shareMPTIssuanceId 
// values with your own.

import xrpl from "xrpl"
import { execSync } from "child_process"
import fs from "fs"

// Auto-run setup if needed
if (!fs.existsSync("vaultSetup.json")) {
  console.log(`\n=== Vault setup data doesn't exist. Running setup script... ===\n`)
  execSync("node vaultSetup.js", { stdio: "inherit" })
}

// Load setup data
const setupData = JSON.parse(fs.readFileSync("vaultSetup.json", "utf8"))

// Connect to the network
const client = new xrpl.Client("wss://s.devnet.rippletest.net:51233")
await client.connect()
```

Python
- `json`: Used for loading and formatting JSON data.
- `os`, `subprocess`, `sys`: Used for file handling and running setup scripts.
- `xrpl`: Used for XRPL client connection and transaction handling.



```py
# IMPORTANT: This example deposits into an existing PRIVATE vault.
# The depositor account used has valid credentials in the vault's Permissioned Domain.
# Without valid credentials, the VaultDeposit transaction will fail.
# If you want to deposit into a public vault, you can replace the vault_id and share_mpt_issuance_id
# values with your own.

import json
import os
import subprocess
import sys

from xrpl.clients import JsonRpcClient
from xrpl.models import VaultDeposit
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")
```

Provide the depositing account and specify the vault details. The depositor must have a balance of the vault's asset to deposit.

JavaScript

```js
// You can replace these values with your own
const depositor = xrpl.Wallet.fromSeed(setupData.depositor.seed)
const vaultID = setupData.vaultID
const assetMPTIssuanceId = setupData.mptIssuanceId
const shareMPTIssuanceId = setupData.vaultShareMPTIssuanceId

console.log(`Depositor address: ${depositor.address}`)
console.log(`Vault ID: ${vaultID}`)
console.log(`Asset MPT issuance ID: ${assetMPTIssuanceId}`)
console.log(`Vault share MPT issuance ID: ${shareMPTIssuanceId}`)

const depositAmount = 1
```

This example uses an existing vault, depositor account, and MPT from the `vaultSetup.js` script, but you can replace these values with your own.

Python

```py
# 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}")

deposit_amount = 1
```

This example uses an existing vault, depositor account, and MPT from the `vault_setup.py` script, but you can replace these values with your own.

The preconfigured depositor account has:

- Valid [Credentials](/ja/docs/concepts/decentralized-storage/credentials) in the vault's [Permissioned Domain](/ja/docs/concepts/tokens/decentralized-exchange/permissioned-domains).
- A positive balance of the MPT in the vault.


### 3. Check initial vault state

Use the [vault_info method](/docs/references/http-websocket-apis/public-api-methods/vault-methods/vault_info) to retrieve the vault's current state, including its total value and available liquidity.

JavaScript

```js
// Get initial vault state ----------------------
console.log("\n=== Getting initial vault state... ===")
const initialVaultInfo = await client.request({
  command: "vault_info",
  vault_id: vaultID,
  ledger_index: "validated"
})

console.log(` - Total vault value: ${initialVaultInfo.result.vault.AssetsTotal}`)
console.log(` - Available assets: ${initialVaultInfo.result.vault.AssetsAvailable}`)
```

Python

```py
# Get initial vault state
print("\n=== Getting initial vault state... ===")
initial_vault_info = client.request(
    VaultInfo(
        vault_id=vault_id,
        ledger_index="validated"
    )
)

print(f" - Total vault value: {initial_vault_info.result['vault']['AssetsTotal']}")
print(f" - Available assets: {initial_vault_info.result['vault']['AssetsAvailable']}")
```

### 4. Check depositor's asset balance

Before depositing, verify that the depositor has sufficient balance of the vault's asset. If the depositor doesn't have enough funds, the transaction will fail with a `tecINSUFFICIENT_FUNDS` error.

JavaScript

```js
// Check depositor's asset balance ----------------------
console.log("\n=== Checking depositor's balance... ===")
try {
  // Use ledger_entry to get specific MPT issuance balance
  const ledgerEntryResult = await client.request({
    command: "ledger_entry",
    mptoken: {
      mpt_issuance_id: assetMPTIssuanceId,
      account: depositor.address
    },
    ledger_index: "validated"
  })

  const balance = ledgerEntryResult.result.node?.MPTAmount
  console.log(`Balance: ${balance}`)

  // Check if balance is sufficient
  if (balance < depositAmount) {
    console.error(`Error: Insufficient balance! Have ${balance}, need ${depositAmount}`)
    await client.disconnect()
    process.exit(1)
  }
} catch (error) {
  if (error.data?.error === 'entryNotFound') {
    console.error(`Error: The depositor doesn't hold any assets with ID: ${assetMPTIssuanceId}`)
  } else {
    console.error(`Error checking MPT: ${error}`)
  }
  await client.disconnect()
  process.exit(1)
}
```

Python

```py
# Check depositor's asset balance
print("\n=== Checking depositor's balance... ===")
try:
    # Use ledger_entry to get specific MPT issuance balance
    ledger_entry_result = client.request(
        LedgerEntry(
            mptoken={
                "mpt_issuance_id": asset_mpt_issuance_id,
                "account": depositor.address
            },
            ledger_index="validated"
        )
    )

    balance = ledger_entry_result.result["node"]["MPTAmount"]
    print(f"Balance: {balance}")

    # Check if balance is sufficient
    if int(balance) < deposit_amount:
        print(f"Error: Insufficient balance! Have {balance}, need {deposit_amount}", file=sys.stderr)
        sys.exit(1)
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 assets with ID: {asset_mpt_issuance_id}", file=sys.stderr)
    else:
        print(f"Error checking MPT: {error}", file=sys.stderr)
    sys.exit(1)
```

### 5. Prepare VaultDeposit transaction

Create a [VaultDeposit transaction](/docs/references/protocol/transactions/types/vaultdeposit) object to deposit assets into the vault.

JavaScript

```js
// Prepare VaultDeposit transaction ----------------------
console.log(`\n=== VaultDeposit transaction ===`)
const vaultDepositTx = {
  TransactionType: "VaultDeposit",
  Account: depositor.address,
  VaultID: vaultID,
  Amount: {
    mpt_issuance_id: assetMPTIssuanceId,
    value: depositAmount.toString()
  }
}

// Validate the transaction structure before submitting
xrpl.validate(vaultDepositTx)
console.log(JSON.stringify(vaultDepositTx, null, 2))
```

The transaction specifies the depositing account, the vault's unique identifier (`VaultID`), and the amount to deposit. The asset in the `Amount` field must match the vault's asset type, otherwise the transaction will fail with a `tecWRONG_ASSET` error.

Python

```py
# Prepare VaultDeposit transaction
print("\n=== VaultDeposit transaction ===")
vault_deposit_tx = VaultDeposit(
    account=depositor.address,
    vault_id=vault_id,
    amount={
        "mpt_issuance_id": asset_mpt_issuance_id,
        "value": str(deposit_amount)
    }
)

print(json.dumps(vault_deposit_tx.to_xrpl(), indent=2))
```

The transaction specifies the depositing account, the vault's unique identifier (`vault_id`), and the amount to deposit. The asset in the `amount` field must match the vault's asset type, otherwise the transaction will fail with a `tecWRONG_ASSET` error.

### 6. Submit VaultDeposit transaction

Submit the `VaultDeposit` transaction to the XRP Ledger.

JavaScript

```js
// Submit VaultDeposit transaction ----------------------
console.log("\n=== Submitting VaultDeposit transaction... ===")
const depositResult = await client.submitAndWait(vaultDepositTx, {
  wallet: depositor,
  autofill: true,
})
if (depositResult.result.meta.TransactionResult !== "tesSUCCESS") {
  const result_code = depositResult.result.meta.TransactionResult
  console.error("Error: Unable to deposit:", result_code)
  await client.disconnect()
  process.exit(1)
}
console.log("Deposit successful!")
```

Python

```py
# Submit VaultDeposit transaction
print("\n=== Submitting VaultDeposit transaction... ===")
deposit_result = submit_and_wait(vault_deposit_tx, client, depositor, autofill=True)

if deposit_result.result["meta"]["TransactionResult"] != "tesSUCCESS":
    result_code = deposit_result.result["meta"]["TransactionResult"]
    print(f"Error: Unable to deposit: {result_code}", file=sys.stderr)
    sys.exit(1)

print("Deposit successful!")
```

When depositing into a private vault, the transaction verifies that the depositor has valid credentials in the vault's permissioned domain. Without valid credentials, the `VaultDeposit` transaction fails with a `tecNO_AUTH` error.

If the transaction succeeds, the vault:

- Transfers the assets from the depositing account to the vault's pseudo-account.
- Issues vault shares to the depositor.


Note
Transfer fees are not charged on `VaultDeposit` transactions.

### 7. Verify deposit and check share balance

After depositing, verify the vault's updated state. You can extract this information directly from the transaction metadata without making additional API calls:

JavaScript

```js
// Extract vault state from transaction metadata ----------------------
console.log("\n=== Vault state after deposit ===")
const affectedNodes = depositResult.result.meta.AffectedNodes
const vaultNode = affectedNodes.find(
  (node) => {
    return (
      node.ModifiedNode &&
      node.ModifiedNode.LedgerEntryType === "Vault" &&
      node.ModifiedNode.LedgerIndex === vaultID
    )
  }
)
if (vaultNode) {
  const vaultFields = vaultNode.ModifiedNode.FinalFields
  console.log(` - Total vault value: ${vaultFields.AssetsTotal}`)
  console.log(` - Available assets: ${vaultFields.AssetsAvailable}`)
}
```

Python

```py
# Extract vault state from transaction metadata
print("\n=== Vault state after deposit ===")
affected_nodes = deposit_result.result["meta"]["AffectedNodes"]
vault_node = None
for node in affected_nodes:
    if "ModifiedNode" in node:
        modified = node["ModifiedNode"]
        if modified["LedgerEntryType"] == "Vault" and modified["LedgerIndex"] == vault_id:
            vault_node = node
            break

if vault_node:
    vault_fields = vault_node["ModifiedNode"]["FinalFields"]
    print(f" - Total vault value: {vault_fields['AssetsTotal']}")
    print(f" - Available assets: {vault_fields['AssetsAvailable']}")
```

Finally, check that the depositing account has received the shares.

JavaScript

```js
// Get the depositor's share balance ----------------------
console.log("\n=== Depositor's share balance ==")
const depositorShareNode = affectedNodes.find((node) => {
  const shareNode = node.ModifiedNode || node.CreatedNode
  const fields = shareNode?.FinalFields || shareNode?.NewFields
  return (
    shareNode &&
    shareNode.LedgerEntryType === "MPToken" &&
    fields?.Account === depositor.address &&
    fields?.MPTokenIssuanceID === shareMPTIssuanceId
  )
})
if (depositorShareNode) {
  const shareNode = depositorShareNode.ModifiedNode || depositorShareNode.CreatedNode
  const shareFields = shareNode.FinalFields || shareNode.NewFields
  console.log(`Shares held: ${shareFields.MPTAmount}`)
}

await client.disconnect()
```

Python

```py
# 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:
        share_node = node["ModifiedNode"]
        fields = share_node["FinalFields"]
    elif "CreatedNode" in node:
        share_node = node["CreatedNode"]
        fields = share_node["NewFields"]
    else:
        continue

    if (share_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 "ModifiedNode" in depositor_share_node:
        share_fields = depositor_share_node["ModifiedNode"]["FinalFields"]
    else:
        share_fields = depositor_share_node["CreatedNode"]["NewFields"]
    print(f"Shares held: {share_fields['MPTAmount']}")
```

The code checks for both `ModifiedNode` and `CreatedNode` because on the first deposit, a new MPToken entry is created for the depositor's shares (`CreatedNode`). On subsequent deposits, the depositor's existing share balance is updated (`ModifiedNode`).

## See Also

**Concepts**:

- [Single Asset Vaults](/ja/docs/concepts/tokens/single-asset-vaults)
- [Credentials](/ja/docs/concepts/decentralized-storage/credentials)
- [Permissioned Domains](/ja/docs/concepts/tokens/decentralized-exchange/permissioned-domains)


**Tutorials**:

- [Create a Single Asset Vault](/ja/docs/tutorials/defi/lending/use-single-asset-vaults/create-a-single-asset-vault)
- [Withdraw from a Vault](/ja/docs/tutorials/defi/lending/use-single-asset-vaults/withdraw-from-a-vault)


**References**:

- [VaultDeposit transaction](/docs/references/protocol/transactions/types/vaultdeposit)
- [vault_info method](/docs/references/http-websocket-apis/public-api-methods/vault-methods/vault_info)