Compare commits

...

4 Commits

Author SHA1 Message Date
rachelflynn
b1eaf8c051 Merge master into add-calculate-reserves-tutorial 2026-04-02 10:22:17 -04:00
rachelflynn
f2109aab33 Fix Java code sample for calculate-reserves tutorial 2026-04-01 16:39:34 -04:00
rachelflynn
41788b9323 fix: use account instead of address in step 5 2026-04-01 15:32:08 -04:00
rachelflynn
04cfa17880 add: calculate reserves tutorial and code samples 2026-04-01 15:27:58 -04:00
12 changed files with 439 additions and 4 deletions

View File

@@ -0,0 +1,57 @@
// Set up client ----------------------
package main
import (
"fmt"
"github.com/Peersyst/xrpl-go/xrpl/queries/account"
"github.com/Peersyst/xrpl-go/xrpl/queries/server"
"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
"github.com/Peersyst/xrpl-go/xrpl/websocket"
)
func main() {
client := websocket.NewClient(
websocket.NewClientConfig().
WithHost("wss://s.devnet.rippletest.net:51233"),
)
defer client.Disconnect()
if err := client.Connect(); err != nil {
panic(err)
}
// Look up reserve values ----------------------
res, err := client.Request(&server.InfoRequest{})
if err != nil {
panic(err)
}
var serverInfo server.InfoResponse
if err := res.GetResult(&serverInfo); err != nil {
panic(err)
}
baseReserve := serverInfo.Info.ValidatedLedger.ReserveBaseXRP
reserveInc := serverInfo.Info.ValidatedLedger.ReserveIncXRP
fmt.Printf("Base reserve: %v XRP\n", baseReserve)
fmt.Printf("Incremental reserve: %v XRP\n", reserveInc)
// Look up owner count ----------------------
address := types.Address("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")
accountInfo, err := client.GetAccountInfo(&account.InfoRequest{Account: address})
if err != nil {
panic(err)
}
ownerCount := accountInfo.AccountData.OwnerCount
// Calculate total reserve ----------------------
totalReserve := float64(baseReserve) + (float64(ownerCount) * float64(reserveInc))
fmt.Printf("Owner count: %v\n", ownerCount)
fmt.Printf("Total reserve: %v XRP\n", totalReserve)
}

View File

@@ -0,0 +1,16 @@
module calculate-reserves
go 1.26.1
require github.com/Peersyst/xrpl-go v0.1.17
require (
github.com/bsv-blockchain/go-sdk v1.2.9 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/crypto v0.44.0 // indirect
)

View File

@@ -0,0 +1,30 @@
github.com/Peersyst/xrpl-go v0.1.17 h1:jOI2es/dzzRm6/WMVCjr7H3fci47XB2kRkezfbddDB0=
github.com/Peersyst/xrpl-go v0.1.17/go.mod h1:38j60Mr65poIHdhmjvNXnwbcUFNo8J7CBDot7ZWgrb8=
github.com/bsv-blockchain/go-sdk v1.2.9 h1:LwFzuts+J5X7A+ECx0LNowtUgIahCkNNlXckdiEMSDk=
github.com/bsv-blockchain/go-sdk v1.2.9/go.mod h1:KiHWa/hblo3Bzr+IsX11v0sn1E6elGbNX0VXl5mOq6E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2/go.mod h1:uGfjDyePSpa75cSQLzNdVmWlbQMBuiJkvXw/MNKRY4M=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 h1:5RVFMOWjMyRy8cARdy79nAmgYw3hK/4HUq48LQ6Wwqo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -0,0 +1,47 @@
// Set up client ----------------------
import okhttp3.HttpUrl;
import org.xrpl.xrpl4j.client.JsonRpcClientErrorException;
import org.xrpl.xrpl4j.client.XrplClient;
import org.xrpl.xrpl4j.model.client.accounts.AccountInfoRequestParams;
import org.xrpl.xrpl4j.model.client.common.LedgerSpecifier;
import org.xrpl.xrpl4j.model.transactions.Address;
import java.math.BigDecimal;
public class CalculateReserves {
public static void main(String[] args) throws JsonRpcClientErrorException {
HttpUrl rippledUrl = HttpUrl.get("https://s.devnet.rippletest.net:51234/");
XrplClient xrplClient = new XrplClient(rippledUrl);
// Look up reserve values ----------------------
var serverInfo = xrplClient.serverInformation();
var validatedLedger = serverInfo.info().validatedLedger().get();
BigDecimal baseReserve = validatedLedger.reserveBaseXrp().toXrp();
BigDecimal reserveInc = validatedLedger.reserveIncXrp().toXrp();
System.out.println("Base reserve: " + baseReserve + " XRP");
System.out.println("Incremental reserve: " + reserveInc + " XRP");
// Look up owner count ----------------------
Address address = Address.of("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh");
var accountInfo = xrplClient.accountInfo(
AccountInfoRequestParams.builder()
.account(address)
.ledgerSpecifier(LedgerSpecifier.VALIDATED)
.build()
);
long ownerCount = accountInfo.accountData().ownerCount().longValue();
// Calculate total reserve ----------------------
BigDecimal totalReserve = baseReserve.add(reserveInc.multiply(BigDecimal.valueOf(ownerCount)));
System.out.println("Owner count: " + ownerCount);
System.out.println("Total reserve: " + totalReserve + " XRP");
}
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>calculate-reserves</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.xrpl</groupId>
<artifactId>xrpl4j-client</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,46 @@
// Set up client ----------------------
import okhttp3.HttpUrl;
import org.xrpl.xrpl4j.client.JsonRpcClientErrorException;
import org.xrpl.xrpl4j.client.XrplClient;
import org.xrpl.xrpl4j.model.client.accounts.AccountInfoRequestParams;
import org.xrpl.xrpl4j.model.client.common.LedgerSpecifier;
import org.xrpl.xrpl4j.model.transactions.Address;
import java.math.BigDecimal;
public class CalculateReserves {
public static void main(String[] args) throws JsonRpcClientErrorException {
HttpUrl rippledUrl = HttpUrl.get("https://s.devnet.rippletest.net:51234/");
XrplClient xrplClient = new XrplClient(rippledUrl);
// Look up reserve values ----------------------
var serverInfo = xrplClient.serverInformation();
var validatedLedger = serverInfo.info().validatedLedger().get();
BigDecimal baseReserve = validatedLedger.reserveBaseXrp().toXrp();
BigDecimal reserveInc = validatedLedger.reserveIncXrp().toXrp();
System.out.println("Base reserve: " + baseReserve + " XRP");
System.out.println("Incremental reserve: " + reserveInc + " XRP");
// Look up owner count ----------------------
Address address = Address.of("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh");
var accountInfo = xrplClient.accountInfo(
AccountInfoRequestParams.builder()
.account(address)
.ledgerSpecifier(LedgerSpecifier.VALIDATED)
.build()
);
long ownerCount = accountInfo.accountData().ownerCount().longValue();
// Calculate total reserve ----------------------
BigDecimal totalReserve = baseReserve.add(reserveInc.multiply(BigDecimal.valueOf(ownerCount)));
System.out.println("Owner count: " + ownerCount);
System.out.println("Total reserve: " + totalReserve + " XRP");
}
}

View File

@@ -0,0 +1,33 @@
// Set up client ----------------------
import xrpl from 'xrpl'
const client = new xrpl.Client('wss://s.devnet.rippletest.net:51233')
await client.connect()
// Look up reserve values ----------------------
const serverInfo = await client.request({ command: 'server_info' })
const validatedLedger = serverInfo.result.info.validated_ledger
const baseReserve = validatedLedger.reserve_base_xrp
const reserveInc = validatedLedger.reserve_inc_xrp
console.log(`Base reserve: ${baseReserve} XRP`)
console.log(`Incremental reserve: ${reserveInc} XRP`)
// Look up owner count ----------------------
const address = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh" // replace with any address
const accountInfo = await client.request({ command: "account_info", account: address })
const ownerCount = accountInfo.result.account_data.OwnerCount
// Calculate total reserve ----------------------
const totalReserve = baseReserve + (ownerCount * reserveInc)
console.log(`Owner count: ${ownerCount}`)
console.log(`Total reserve: ${totalReserve} XRP`)
await client.disconnect()

View File

@@ -0,0 +1,34 @@
# Set up client ----------------------
from xrpl.clients import JsonRpcClient
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
# Look up reserve values ----------------------
from xrpl.models.requests import ServerInfo
response = client.request(ServerInfo())
validated_ledger = response.result["info"]["validated_ledger"]
base_reserve = validated_ledger["reserve_base_xrp"]
reserve_inc = validated_ledger["reserve_inc_xrp"]
print(f"Base reserve: {base_reserve} XRP")
print(f"Incremental reserve: {reserve_inc} XRP")
# Look up owner count ----------------------
from xrpl.models.requests import AccountInfo
address = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh" # replace with any address
response = client.request(AccountInfo(account=address))
owner_count = response.result["account_data"]["OwnerCount"]
# Calculate total reserve ----------------------
total_reserve = base_reserve + (owner_count * reserve_inc)
print(f"Owner count: {owner_count}")
print(f"Total reserve: {total_reserve} XRP")

View File

@@ -0,0 +1,150 @@
---
seo:
description: Look up and calculate base and owner reserve requirements for an XRPL account.
labels:
- Accounts
---
# Calculate Account Reserves
This tutorial demonstrates how to look up and calculate the [reserve requirements](https://xrpl.org/docs/concepts/accounts/reserves) for an XRP Ledger account. Reserves are the minimum amount of XRP an account must hold based on its activity on the ledger.
## Goals
By the end of this tutorial, you should be able to:
- Look up an account's current [base](https://xrpl.org/docs/concepts/accounts/reserves#base-reserve-and-owner-reserve) and incremental reserve values.
- Determine an account's [owner reserve](https://xrpl.org/docs/concepts/accounts/reserves#owner-reserves).
- Calculate an account's total reserve requirement.
## Prerequisites
To complete this tutorial, you need:
- A basic understanding of the XRP Ledger.
- An XRP Ledger [client library](https://xrpl.org/docs/references/client-libraries) set up.
## Source Code
You can find this tutorial's example source code in the [code samples section of this website's repository](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/calculate-reserves).
## Steps
### 1. Install dependencies
Install dependencies for your language from the code sample folder.
{% tabs %}
{% tab label="JavaScript" %}
```bash
npm install xrpl
```
{% /tab %}
{% tab label="Python" %}
```bash
pip install xrpl-py
```
{% /tab %}
{% tab label="Go" %}
```bash
go mod tidy
```
{% /tab %}
{% tab label="Java" %}
```bash
mvn compile
```
{% /tab %}
{% /tabs %}
### 2. Set up client
Import the XRPL library and create a client connection to a testnet server.
{% tabs %}
{% tab label="JavaScript" %}
{% code-snippet file="/_code-samples/calculate-reserves/js/calculate_reserves.js" language="js" from="// Set up client" to="// Look up reserve values" /%}
{% /tab %}
{% tab label="Python" %}
{% code-snippet file="/_code-samples/calculate-reserves/py/calculate_reserves.py" language="py" from="# Set up client" to="# Look up reserve values" /%}
{% /tab %}
{% tab label="Go" %}
{% code-snippet file="/_code-samples/calculate-reserves/go/calculate_reserves.go" language="go" from="// Set up client" to="// Look up reserve values" /%}
{% /tab %}
{% tab label="Java" %}
{% code-snippet file="/_code-samples/calculate-reserves/java/CalculateReserves.java" language="java" from="// Set up client" to="// Look up reserve values" /%}
{% /tab %}
{% /tabs %}
### 3. Look up reserve values
Retrieve the base and incremental reserve values using the [`server_info`](https://xrpl.org/docs/references/http-websocket-apis/public-api-methods/server-info-methods/server_info) or [`server_state`](https://xrpl.org/docs/references/http-websocket-apis/public-api-methods/server-info-methods/server_state) method. This example uses `server_info` to return values in decimal XRP instead of integer drops.
{% tabs %}
{% tab label="JavaScript" %}
{% code-snippet file="/_code-samples/calculate-reserves/js/calculate_reserves.js" language="js" from="// Look up reserve values" to="// Look up owner count"/%}
{% /tab %}
{% tab label="Python" %}
{% code-snippet file="/_code-samples/calculate-reserves/py/calculate_reserves.py" language="py" from="# Look up reserve values" to="# Look up owner count"/%}
{% /tab %}
{% tab label="Go" %}
{% code-snippet file="/_code-samples/calculate-reserves/go/calculate_reserves.go" language="go" from="// Look up reserve values" to="// Look up owner count"/%}
{% /tab %}
{% tab label="Java" %}
{% code-snippet file="/_code-samples/calculate-reserves/java/CalculateReserves.java" language="java" from="// Look up reserve values" to="// Look up owner count" /%}
{% /tab %}
{% /tabs %}
### 4. Determine owner reserve
Once you have the incremental reserve value, multiply that by the number of objects the account owns to determine the owner reserve. You can call [`account_info`](https://xrpl.org/docs/references/http-websocket-apis/public-api-methods/account-methods/account_info) and take `account_data.OwnerCount` to retrieve an account's total number of objects.
{% tabs %}
{% tab label="JavaScript" %}
{% code-snippet file="/_code-samples/calculate-reserves/js/calculate_reserves.js" language="js" from="// Look up owner count" to="// Calculate total reserve"/%}
{% /tab %}
{% tab label="Python" %}
{% code-snippet file="/_code-samples/calculate-reserves/py/calculate_reserves.py" language="py" from="# Look up owner count" to="# Calculate total reserve"/%}
{% /tab %}
{% tab label="Go" %}
{% code-snippet file="/_code-samples/calculate-reserves/go/calculate_reserves.go" language="go" from="// Look up owner count" to="// Calculate total reserve" /%}
{% /tab %}
{% tab label="Java" %}
{% code-snippet file="/_code-samples/calculate-reserves/java/CalculateReserves.java" language="java" from="// Look up owner count" to="// Calculate total reserve" /%}
{% /tab %}
{% /tabs %}
### 5. Calculate total reserve
Use the following formula to calculate an account's total reserve requirement:
`total reserve = reserve_base_xrp + (OwnerCount × reserve_inc_xrp)`
{% tabs %}
{% tab label="JavaScript" %}
{% code-snippet file="/_code-samples/calculate-reserves/js/calculate_reserves.js" language="js" from="// Calculate total reserve"/%}
{% /tab %}
{% tab label="Python" %}
{% code-snippet file="/_code-samples/calculate-reserves/py/calculate_reserves.py" language="py" from="# Calculate total reserve"/%}
{% /tab %}
{% tab label="Go" %}
{% code-snippet file="/_code-samples/calculate-reserves/go/calculate_reserves.go" language="go" from="// Calculate total reserve" /%}
{% /tab %}
{% tab label="Java" %}
{% code-snippet file="/_code-samples/calculate-reserves/java/CalculateReserves.java" language="java" from="// Calculate total reserve" /%}
{% /tab %}
{% /tabs %}
## See Also
Concepts:
- [Reserves](https://xrpl.org/docs/concepts/accounts/reserves)
Tutorials:
- [Calculate and Display the Reserve Requirement (Python)](https://xrpl.org/docs/tutorials/sample-apps/build-a-desktop-wallet-in-python#3-display-an-account)
References:
- [server_info](https://xrpl.org/docs/references/http-websocket-apis/public-api-methods/server-info-methods/server_info)
- [server_state](https://xrpl.org/docs/references/http-websocket-apis/public-api-methods/server-info-methods/server_state)
- [account_info](https://xrpl.org/docs/references/http-websocket-apis/public-api-methods/account-methods/account_info)

2
package-lock.json generated
View File

@@ -27,7 +27,7 @@
"react18-json-view": "^0.2.6",
"smol-toml": "^1.3.1",
"use-query-params": "^2.2.1",
"xrpl": "^4.2.5"
"xrpl": "^4.6.0"
},
"devDependencies": {
"bootstrap": "^4.6.2",

View File

@@ -30,7 +30,7 @@
"react18-json-view": "^0.2.6",
"smol-toml": "^1.3.1",
"use-query-params": "^2.2.1",
"xrpl": "^4.2.5"
"xrpl": "^4.6.0"
},
"overrides": {
"react": "^19.1.0",

View File

@@ -326,8 +326,7 @@
- page: docs/tutorials/best-practices/key-management/remove-a-regular-key-pair.md
- page: docs/tutorials/best-practices/key-management/offline-account-setup.md
- page: docs/tutorials/best-practices/key-management/set-up-multi-signing.md
- page: docs/tutorials/best-practices/key-management/send-a-multi-signed-transaction.md
- page: docs/tutorials/best-practices/key-management/delete-an-account.md
- page: docs/tutorials/best-practices/key-management/send-a-multi-signed-transaction.md
- group: Advanced Developer Topics
groupTranslationKey: sidebar.docs.tutorials.advancedDeveloperTopics
expanded: false