The v1 routes are available on mainnet and testnet. These examples read mainnet.
For testnet transactions, select testnet and use its API, RPC, contracts,
and token addresses together.
1. Read positions and supported assets
Call the API from any language. These responses are arrays.Link: <...>; rel="next" until the header is
absent. Resolve relative links against the URL of the page you just read.
Keep requests on the same endpoint, reject cycles, and check HTTP errors.
An empty page can still have a next link.
The optional SDK read client handles pagination. It has no Stellar SDK runtime
dependency. Public response types are available from the same entry.
URL and
URLSearchParams, plus fetch and cancellation support. Your wallet runtime
may already provide them. If compatible URL support is missing, install
react-native-url-polyfill@2.0.0.
Load import 'react-native-url-polyfill/auto' first in the app entry point,
before SDK and app imports. Direct HTTP reads do not require the SDK reader.
read.assets({ usage: 'borrow' }) for a borrowing screen. Pass an
AbortSignal when a screen closes or the selected wallet changes.
See the integrator API reference for
fields, pagination, and freshness rules.
2. Select a market
Let the user choose an asset and one of itsspokes. Preserve hubId,
spokeId, and sac together. The same token can appear in several hubs or spokes.
A symbol such as USDC is a label, not a transaction identifier.
For new supply, check canOpenAccount, canSupply, and
supplyCapacity.amountRaw. For a top-up, select an existing account and use its
spoke. These fields help your interface explain whether supply appears available.
Simulation and ledger execution enforce the current contract rules.
Keep API data, RPC, contract addresses, market selection, and signing passphrase
on the same network. Use addresses to verify
contract wiring. Reading the API does not require an API key.
3. Prepare a supply transaction for the wallet
The caller needs a funded Stellar account, XLM for fees, and the selected tokens. XLM supply uses its Stellar Asset Contract address, not the stringXLM. Keep
enough spendable XLM for fees and account reserves.
Builders are synchronous and make no RPC requests. Their xdr is unsigned and
unprepared. Fetch the current source sequence, build the transaction, then call
prepareStellarTxXdr before signing. Preparation adds the Soroban footprint,
authorization entries, and resource fees.
The following functions continue from the initialization above. Supply amounts
are decimal integer strings in token base units. For a 7-decimal token,
"1.25" becomes "12500000". Use parseStellarTokenAmount for decimal input.
It checks precision, positive amounts, and the i128 range through the SDK.
TextEncoder and TextDecoder
first. Use your wallet integration’s Stellar SDK and Metro runtime setup.
Verify preparation, signing, submission, and recovery on the target device.
asset: selectedAsset.sac, hubId, spokeId, and a positive raw amount
string as amount. Use the SDK helper to convert decimal input:
accountNonce: '0' to create an account. For a top-up, use the selected
position’s accountId and its spoke.
In an owner wallet flow, recheck owner_of(accountId) on
deployment.positionNftContract before preparation. Indexed ownership can lag
an NFT transfer. Other supply permissions are covered in
Supply.
The authorization check compares the prepared invocation with the builder
output and limits caller token transfers to the requested supply. If the check
fails, do not send the XDR to the wallet.
The result of prepareSupply is unsigned XDR ready for the wallet to sign.
Show the network, token, amount, account, spoke, hub, and estimated fee first.
Keep the prepared authorization entries; they cover the controller invocation
and nested token transfer. See position NFT
for its ownership view.
sourceSequence is the Stellar source account sequence. accountNonce is the
lending account id. They are unrelated. A wallet can own several accounts on
one spoke. Never infer its account id from a spoke, token, or first position.
4. Sign, submit and confirm
Connect the prepared XDR to your wallet provider. Sign withdeployment.passphrase and the selected caller. Keep private keys in the wallet.
The XOXNO builder and preparation helper do not sign or broadcast.
This example receives your wallet callback and durable pending-transaction
storage. Store the network with the hash and signed XDR before submission.
XDR does not contain a network passphrase. Recovery must use the recorded
network and its RPC, even if the user has since switched networks.
Run browser signing in the client. A native wallet uses the same prepared
XDR and signing network in its own signing flow.
For
UNKNOWN, query server.getTransaction(hash) again. If you retry submission,
send the same signed XDR and retain its hash. A later rejection does not prove
that the original failed. Do not sign a replacement while the original envelope
remains valid. After its timebound expires, resolve the original hash before
deciding whether a replacement is needed.
Expiry alone does not prove failure. If lookup remains NOT_FOUND, check the
original network’s retained transaction history and reconcile ledger and account
state. If the available history cannot prove the outcome, keep the operation
unresolved and do not automatically repeat it.
Serialize actions from the same Stellar source account to avoid sequence races.
After SUCCESS, store a new lending account id from result.returnValue,
decoded with scValToNative. Reconcile it with the indexed positions and NFT
ownership.
Mark the pending record terminal on SUCCESS, FAILED, or a definitive
first-send rejection. An indexer delay means the interface is refreshing,
not that supply should be repeated.
5. Display the wallet’s positions
UseaccountId as the position id within its network and nftContract.
Show spokeName, then display supplied and borrow as separate lists.
Use each leg’s hubId and sac together as its key.
Keep
amountRaw and accountId as strings. Do not convert them to JavaScript
numbers. The API applies interest indexes; do not apply legacy RAY conversion
again. USD values and risk remain indexed estimates.
This small formatter works in a browser or React Native application:
nftImage with an HTML image in a browser. In React Native, use your
SVG renderer; native Image does not provide portable SVG support.
For example, SvgUri from react-native-svg accepts a URL. Use native Image
for supported raster token logos and an SVG renderer for SVG logos.
Use the public HTTPS API from a mobile device. For local development, configure
a reachable server URL: a physical device’s localhost refers to the device,
not your computer.
Show loading, empty, error, and incomplete-data states separately. A failed
request is not an empty portfolio. Discard an old wallet result when selection
changes. Check each field even when another field makes the item incomplete.
Read spendable wallet balances through Horizon or the token contract’s balance
view. Before receiving a classic issued asset, check its code/issuer trustline.
This includes borrow, withdraw, and possible refunds. XLM and pure Soroban tokens
need no classic trustline. A SAC address alone cannot identify the code/issuer.
Other lending actions
Use the same build → prepare → sign → submit → confirm lifecycle for every action.
Repay has no repay-all sentinel. To close debt, use the ceiled debt with an accrual buffer; excess is refunded. Withdrawal and borrowing must satisfy the account’s current risk checks and pool liquidity. See withdraw, borrow, and repay.
Agent instructions and integration checks
Agents should follow the same explicit user intent and wallet signing boundary as a human integration. Use the skills already maintained in XOXNO/rs-lending-xlm:
The SDK skill includes
reads.md, positions.md, transactions.md, and frontend.md; the data skill includes api.md. Check the installed SDK exports and deployed routes before copying an example.
Before shipping, verify:
- The selected network matches API, metadata, contracts, RPC, and the signing passphrase.
- The user selected an explicit reserve tuple and, for an existing position, an explicit account id with current NFT ownership.
- Amounts use integer base units; v1 positions need no RAY conversion; missing values remain unavailable.
- Only prepared XDR reaches the signer; the signed envelope and hash survive app reloads.
- Success requires ledger
SUCCESS; uncertain submission cannot trigger a second supply. - Position rows, prices, balances, and ownership reconcile after confirmation, including when the indexer lags.
- Testnet covers new supply, existing-account top-up, withdrawal, wallet rejection, metadata/price unavailability, and recovery after a submission timeout.

