Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

aquarius-sdk

The Python SDK for Aquarius — swaps, liquidity, and rewards on Stellar.

Status: 0.6.x — swaps and the liquidity lifecycle are complete and verified with real testnet transactions. Concentrated liquidity position management is available as a beta surface (the contracts are under an ongoing external audit). The API may still change before 1.0.

Swap through a specific pool

client.quote()/swap() route through the path-finding API. To pin a swap to one pool you trust — your own routing, API independence — quote and swap on the pool itself; the estimate comes from the router's on-chain estimate_swap:

pool = next(p for p in client.pools_for_pair(XLM, AQUA) if p.fee_bps == 10)

quote = pool.quote(XLM, AQUA, amount_in=100_0000000)   # no signer needed
receipt = quote.execute()                              # swaps in this pool only
# or: pool.swap(XLM, AQUA, amount_in=100_0000000, retries=3)

Exact input only — the router has no single-pool strict-receive; for exact output use client.quote(..., amount_out=...).

Concentrated liquidity positions (beta)

A position is the key (owner, tick_lower, tick_upper) on the pool contract — no NFTs, merged on re-deposit, at most 20 ranges per account. Quotes come from the contract's own estimators; execute/withdraw_position derive real slippage guards from them:

pool = next(p for p in aqua.pools_for_pair(XLM, AQUA) if p.type == "concentrated")

est = pool.estimate_position_deposit(
    {XLM: 10_0000000, AQUA: 100_0000000},
    price_range=("0.9", "1.1"),   # snaps to tick spacing; or tick_range=(lower, upper)
)
opened = est.execute(slippage=0.01)          # min-liquidity guard from the estimate

pool.position_ranges()                        # all of the signer's ranges
pool.position_range_status(est.tick_lower, est.tick_upper)  # in_range / below / above
pool.position_value(est.tick_lower, est.tick_upper)  # principal / fees / total, split
pool.claim_position_fees(est.tick_lower, est.tick_upper)
pool.withdraw_position(est.tick_lower, est.tick_upper)  # full close, auto-claims fees

tick_from_price, price_at_tick, and snap_tick are exported for range math — integer-exact and identical across both language packages.

pip install aquarius-sdk
from stellar_sdk import Keypair
from aquarius import AquariusClient, Asset, XLM, SlippageError

AQUA = Asset.classic("AQUA", "GBNZ...AQUA")

aqua = AquariusClient(network="mainnet", signer=Keypair.from_secret(secret))

# exact input: quote, inspect, execute
quote = aqua.quote(XLM, AQUA, amount_in=100_0000000, slippage=0.01)
receipt = quote.execute()

# exact output: pass amount_out instead — strict-receive throughout
quote = aqua.quote(XLM, AQUA, amount_out=500_0000000)

Provider fees

Pass the collector configuration with the quote. The SDK keeps the fee math exact, routes through the collector, and sends output to recipient without requiring that address to sign:

from aquarius import ProviderFeeConfig

provider_fee = ProviderFeeConfig(
    contract_id="C...",
    fee_fraction=30,   # 30 / fee_denominator=10_000 -> 0.3% of the output
    fee_denominator=10_000,
    recipient="G...",
)

quote = aqua.quote(
    XLM,
    AQUA,
    amount_in=100_0000000,
    slippage=0.005,
    provider_fee=provider_fee,
)
receipt = quote.execute()

Omit recipient to send output back to the signer through the collector's legacy swap methods. Use amount_out instead of amount_in for an exact-output provider swap.

Liquidity

pools = aqua.pools_for_pair(XLM, AQUA)          # discovered on-chain, sorted by type and fee
pool = pools[0]                                  # Pool(type="volatile", fee_bps=10, ...)

result = pool.deposit({XLM: 50_0000000, AQUA: 2500_0000000}, slippage=0.01)
print(result.shares)                             # pool share tokens minted

pool.pending_rewards()                           # accrued AQUA, in stroops
pool.claim_rewards()
pool.withdraw(result.shares, slippage=0.01)

aqua.positions()                                 # every pool where the signer holds shares

Deposit and withdrawal guards come from a simulation of the exact call, reduced by slippage — quoted-versus-executed drift is bounded the same way as for swaps. Reads (reserves(), pending_rewards(), pools_for_pair()) need no signer.

What the SDK handles for you

  • Routing — quotes come from the find-path API; the swap chain XDR is passed through untouched.
  • Transaction lifecycle — simulation, assembly, submission with congestion retries (same-hash resubmission with backoff), and confirmation polling.
  • Fixed authorization — every contract write and unsigned transaction uses client-built authorization trees. Preparation simulates in enforce mode, uses the response for resources, and preserves the exact operation and auth through restore and sequence retries. RPC-returned auth is never added, including when the supplied list is empty.
  • Archived state — if simulation reports expired ledger entries, the SDK restores them (one extra signed transaction) and retries automatically.
  • Typed errors — SlippageError (with requote()), PausedError (kill switches — not your bug), NoRouteError, UserRejectedError, TxTimeoutError.

Signers

A stellar-sdk Keypair works as-is. Custom signers provide public_key plus sign(tx_xdr) -> str returning the signed envelope XDR. Reads — quote() — need no signer at all.

Escape hatches

quote.build_transaction() returns the simulated, unsigned envelope XDR for external signing flows, with the same fixed authorization as execute(). client.api is the typed REST client.

client.contract_call(fn, *scvals) invokes the router raw and authorizes only that exact root call with source-account credentials. Raw calls that previously relied on simulation to discover nested permissions must now provide those permissions explicitly with auth=[...], or use the corresponding high-level method such as pool.deposit(). An incomplete tree fails during enforced simulation before the contract transaction is signed.

For example, an explicit raw reward claim mirrors the router and pool calls:

from stellar_sdk import scval
from aquarius.authorization import authorized_invocation, source_account_entry

user = scval.to_address(public_key)  # the transaction source account
args = [
    user,
    scval.to_vec([scval.to_address(token) for token in pool.tokens]),
    scval.to_bytes(pool.pool_hash),
]
entry = source_account_entry(authorized_invocation(
    aqua.network.router, "claim", args,
    [authorized_invocation(pool.address, "claim", [user])],
))
aqua.contract_call("claim", *args, auth=[entry])

Pass auth=[] when the call requires no authorization; the empty list remains empty after assembly. Reads and estimates can still use recording simulation, but their recorded auth never enters a transaction for signing. Archived-state restoration remains a separate footprint operation when a signer is available.

Infrastructure

Defaults point at the protocol's own endpoints: the mainnet RPC is https://soroban-rpc.aqua.network — the same node the Aquarius web app and backend use. Running your own infrastructure? Every endpoint is overridable:

aqua = AquariusClient(
    network="mainnet",
    rpc_url="https://your-rpc.example.com",
    horizon_url="https://your-horizon.example.com",
)

Fees

base_fee (default 100_000 stroops) is the inclusion fee bid. On top of it, every Soroban transaction declares a resource fee taken from simulation, raised by resource_fee_headroom (default 0.5, i.e. +50%; 0 disables):

aqua = AquariusClient(network="mainnet", signer=signer, resource_fee_headroom=0.3)

The declared resource fee is a cap: the network charges the non-refundable part plus the refundable part actually consumed (rent, events, return value) and refunds the rest, so headroom costs nothing unless it is used. The refundable part depends on ledger state at apply time, so the bare simulated fee can fall short and fail the transaction on-chain with INVOKE_HOST_FUNCTION_INSUFFICIENT_REFUNDABLE_FEE. The headroom is applied before signing (also to automatic restore transactions and to quote.build_transaction()), so wallets see and sign the final fee.

The source account must hold the full declared fee — inclusion fee plus resource fee plus headroom: it is debited before execution, and the unused part is refunded after apply. When spending the whole XLM balance, leave that margin. Re-preparing the XDR from quote.build_transaction() with stellar-sdk's own prepare_transaction re-simulates and replaces the resource fee, which drops the headroom.

Declared CPU instructions are a hard limit too: a transaction that needs more than it declares fails on-chain with INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED, and actual usage can exceed the simulated count by several percent. So the simulated instructions are raised by instruction_headroom (default 0.25, i.e. +25%; 0 disables), capped at the network's per-transaction limit (read from the network config and cached), and the resource fee by the compute fee of the added instructions — non-refundable, under 0.0001 XLM for a typical swap at current mainnet rates — before the fee headroom is applied on top. Restore transactions run no contract code and keep the simulated instructions.

aqua = AquariusClient(network="mainnet", signer=signer, instruction_headroom=0.4)

Amounts

All amounts are integers in token base units (stroops for classic assets: 1 token = 10^7).

Questions and integration help: Discord.

Release files for aquarius-sdk 0.6.0a1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aquarius-sdk 0.6.0a1
File Size Uploaded
aquarius_sdk-0.6.0a1.tar.gz 56.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aquarius-sdk 0.6.0a1
File Interpreter ABI Platform
aquarius_sdk-0.6.0a1-py3-none-any.whl Python 3 none any Details

Total release size: 98.7 kB

Release files / aquarius_sdk-0.6.0a1.tar.gz

Download URL aquarius_sdk-0.6.0a1.tar.gz
Size 56.9 kB
Tags Source
SHA-256 checksum
How to use checksums
4e65dc261e87c36ede7cb61bdb1b7df17c6b92ddb9d685570b241a0ab87a6814
BLAKE2b-256 checksum
How to use checksums
c528eea50b107b9a60503b15b360377f57259363b84e1a245abcc38b651a24a6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / aquarius_sdk-0.6.0a1-py3-none-any.whl

Download URL aquarius_sdk-0.6.0a1-py3-none-any.whl
Size 41.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f4e1b0b55e7e74fbc3b3eb3c4c4e50c3b8e3c896487047a4b38c9e72b28ddd14
BLAKE2b-256 checksum
How to use checksums
2aaa5e6affb4666024247da062546e923628c72394450b5224ce71fee35bf07f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.6.0a1 This release

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page