♒
Aquarius Guide
  • 👋Welcome to Aquarius
  • Developers
    • Integrating with Aquarius
    • Aquarius Soroban Functions
    • Code Examples
      • Prerequisites & Basics
      • Executing Swaps Through Optimal Path
      • Executing Swaps Through Specific Pool
      • Deposit Liquidity
      • Withdraw Liquidity
      • Get Pools Info
      • Claim LP Rewards
      • Add Fees To Swap
        • Deploying a New Fee Collector
        • Executing Swaps with Provider Fees
        • Claiming & Swapping Accumulated Fees
  • Ecosystem Overview
    • 🌐What is Stellar?
      • What are Lumens (XLM)?
      • What are Anchors?
      • What are Trustlines?
      • How much are network fees on Stellar?
      • What are network reserves?
      • Where to trade Stellar assets?
    • 🧮What is Soroban?
  • AQUA tokens
    • ♒What are AQUA tokens?
      • AQUAnomics
      • AQUA Wallets
      • Where can I buy AQUA?
  • ICE
    • 🧊ICE tokens: locking AQUA and getting benefits
    • ICE boosts - how to maximize LP rewards
  • Aquarius AMMs
    • 💱What are Aquarius AMMs?
      • Pools
        • Creating a Pool
        • Deposit & Withdraw Liquidity
      • Swap
      • System limitations
        • Aquarius AMM: Limitations in Support for Fee-on-Transfer, Rebasing, and Deflationary Tokens
        • Aquarius AMM: Token Address Migration Limitations and Mitigation Strategy
  • My Aquarius
    • 👤My Aquarius
      • Main Overview
      • Balances
      • My Liquidity
      • SDEX Rewards
      • Liquidity Votes
      • Governance Votes
      • Airdrop #2
      • ICE Locks
      • Payments History
  • Aquarius AQUA Rewards
    • 🗳️Aquarius voting
      • Aquarius voting: asset Flag Restrictions
    • 🪙SDEX Rewards
    • 🤖Aquarius AMM Rewards
  • Bribes
    • 🎁What are bribes?
      • What are the advantages of protocol level bribes?
  • Aquarius Governance
    • 🧑‍⚖️Aquarius Governance: Community-Led Decision Making
  • Airdrops
    • 1️⃣The Initial Airdrop
      • Am I Eligible For the Initial Airdrop?
      • How can I see if I am eligible?
      • What are Claimable Balances?
      • How is the Initial airdrop distributed?
      • Where can I find more information?
    • 🌠Airdrop #2
      • How could I have been eligible for Airdrop #2?
      • How can I see if I am eligible?
      • When was the Airdrop #2 snapshot?
      • Were there any CEX's taking part?
      • How big was Airdrop #2?
      • How will the airdrop be distributed and for how long?
      • Could I have increased my potential reward?
      • Where can I find more information?
  • Signers Guild
    • 📜What is the signers guild?
      • What percentage of the AQUA supply will be controlled by the Signers Guild?
      • Who will be in the Signers Guild?
      • How does the Signing process work?
      • What will be expected from a guild member?
      • How can I sign up for this position?
      • What are wallets that Guild members will manage?
      • How can I learn more about this?
  • Guides
    • ❔How to use AQUA Locker tool and get ICE tokens
    • ❔How to vote for markets on Aquarius
    • How to create bribes
    • ❔How to use Aquarius Governance
      • How to make a governance vote
      • How to create a proposal
    • ❔How to earn SDEX rewards
    • ❔How to earn AMM rewards
  • Technical Documents
    • 📜Audits
    • 🪲Bug Bounties
    • 🛄Claimable Balances
    • 🗳️The Aquarius Voting Mechanism
    • 🎁SDEX v2 proposal & algorithm
    • ⏩ICE Boost Formula
  • Useful Links
    • Aquarius Home
    • Liquidity Voting
    • Liquidity Rewards
    • Aquarius Bribes
    • ICE locker
    • Aquarius Governance
    • Airdrop #2
Powered by GitBook
On this page
  • Executing Withdraw: Step by Step Guide
  • Complete Code Examples
  1. Developers
  2. Code Examples

Withdraw Liquidity

Example of code that withdraw liquidity from Aquarius pool

PreviousDeposit LiquidityNextGet Pools Info

Last updated 4 months ago

In this section, we demonstrate how to withdraw 1 share from a specific Aquarius AMM pool. For this example, we will use this .

Scroll to see the complete code.

Executing Withdraw: Step by Step Guide

To perform a withdraw, you need to follow these steps:

  1. Specify user secret key, share amount for withdraw and pool address: To withdraw from a pool, you need your user secret key, the amount for withdraw (specified in stroops), and the pool address. You need to already have a share in this pool, make a beforehand.

# Distributor's secret key (ensure this is kept secure)
user_secret_key = "S..."
# XLM/AQUA pool address 
pool_address = "CCY2PXGMKNQHO7WNYXEWX76L2C5BH3JUW3RCATGUYKY7QQTRILBZIFWV"
# 1 share in stroops
share_amount = 1_0000000
// Distributor's secret key (ensure this is kept secure)
const userSecretKey = "S...";
// XLM/AQUA pool address 
const poolAddress = "CCY2PXGMKNQHO7WNYXEWX76L2C5BH3JUW3RCATGUYKY7QQTRILBZIFWV";
// 1 share in stroops
const shareAmount = 10000000;
  1. Make a contract call to the pool's "withdraw" method.

def execute_withdraw():
   # Initialize Soroban and Horizon servers
   server = SorobanServer(SOROBAN_SERVER_RPC)
   horizon_server = Server(HORIZON_SERVER)

   # Load distributor's keypair using the secret key
   keypair = Keypair.from_secret(user_secret_key)

   # Load the distributor's account information from Soroban server
   account = server.load_account(keypair.public_key)

   # Build the withdraw transaction
   tx_builder = TransactionBuilder(
       source_account=account,
       network_passphrase=NETWORK_PASSPHRASE,
       base_fee=1000000  # Set base fee; adjust as necessary
   ).set_timeout(3600)  # Set transaction timeout

   # Append the invoke_contract_function operation for withdraw
   tx = tx_builder.append_invoke_contract_function_op(
       contract_id=pool_address,
       function_name="withdraw",
       parameters=[
           Address(keypair.public_key).to_xdr_sc_val(),  # Distributor's address
           scval.to_uint128(share_amount),  # Amount of shares to redeem
           scval.to_vec([
               scval.to_uint128(1),  # Minimum amount of XLM to receive
               scval.to_uint128(1),  # Minimum amount of AQUA to receive
           ]),
       ],
   )
   tx = server.prepare_transaction(tx.build())
   tx.sign(keypair)

   tx_response = horizon_server.submit_transaction(tx)
   transaction_meta = xdr.TransactionMeta.from_xdr(tx_response['result_meta_xdr'])
   tx_result = transaction_meta.v3.soroban_meta.return_value
   if not tx_result:
       raise RuntimeError

   amount_a, amount_b = map(u128_to_int, [r.u128 for r in tx_result.vec.sc_vec])
   print("Withdrawal successful!")
   print(f"Received Amounts: Token A = {amount_a}, Token B = {amount_b}")
async function executeWithdraw() {
    const sorobanServer = new rpc.Server(sorobanServerUrl);
    const horizonServer = new Horizon.Server(horizonServerUrl);

    const sharesToRedeemU128 = new XdrLargeInt('u128', shareAmount.toFixed()).toU128();
    const minimumAmount = new XdrLargeInt('u128', '1').toU128(); // 0.0000001

    // Load distributor's keypair using the secret key
    const keypair = Keypair.fromSecret(userSecretKey);
    
    // Load the distributor's account information from Soroban server
    const account = await sorobanServer.getAccount(keypair.publicKey());

    const contract = new Contract(poolAddress);

    // Build the withdraw transaction
    const tx = new TransactionBuilder(account, {
        fee: BASE_FEE,
        networkPassphrase: Networks.PUBLIC,
    })
    // Append the invoke_contract_function operation for withdraw
    .addOperation(contract.call(
        'withdraw',
        xdr.ScVal.scvAddress(Address.fromString(keypair.publicKey()).toScAddress()), // Distributor's address
        sharesToRedeemU128, // Amount of shares to redeem
        xdr.ScVal.scvVec([minimumAmount, minimumAmount]), // Minimum amounts of Token A and Token B to receive
    )).setTimeout(TimeoutInfinite).build();

    const preparedTx = await sorobanServer.prepareTransaction(tx);

    preparedTx.sign(keypair);

    const result = await horizonServer.submitTransaction(preparedTx);

    const meta = (await sorobanServer.getTransaction(result.id)).resultMetaXdr;

    const returnValue = meta.v3().sorobanMeta().returnValue();

    const [withdrawalA, withdrawalB] = returnValue.value().map(value => u128ToInt(value.value()));

    console.log('Withdrawal successful!');
    console.log(`Received Amounts: Token A = ${withdrawalA / 1e7}, Token B = ${withdrawalB / 1e7}`);
}

Complete Code Examples

This code withdraw 1 share from the pool with Aquarius AMM on mainnet.

Copy the full code Python
# withdraw.py

from typing import List

from stellar_sdk import Address, Keypair, scval, SorobanServer, xdr, TransactionBuilder, Server, Network
from stellar_sdk.xdr import UInt128Parts

# Step 1. Specify user secret key, amount for withdraw and pool address
# Distributor's secret key (ensure this is kept secure)
user_secret_key = "S..."
# XLM/AQUA pool address 
pool_address = "CCY2PXGMKNQHO7WNYXEWX76L2C5BH3JUW3RCATGUYKY7QQTRILBZIFWV"
# 1 share in stroops
share_amount = 1_0000000

# ==========================
# Configuration Variables
# ==========================

# Soroban and Horizon server RPC endpoints
SOROBAN_SERVER_RPC = 'https://mainnet.sorobanrpc.com'
HORIZON_SERVER = 'https://horizon.stellar.org'

# Stellar network passphrase
NETWORK_PASSPHRASE = Network.PUBLIC_NETWORK_PASSPHRASE

# ==========================
# Utility Functions
# ==========================

def u128_to_int(value: UInt128Parts) -> int:
   """
   Converts UInt128Parts from Stellar's XDR to a Python integer.

   Args:
       value (UInt128Parts): UInt128Parts object from Stellar SDK.

   Returns:
       int: Corresponding Python integer.
   """
   return int(value.hi.uint64 << 64) + value.lo.uint64


# ==========================
# Withdraw Function
# ==========================

# Step 2. Make a contract call to the pool's "withdraw" method.
def execute_withdraw():
   # Initialize Soroban and Horizon servers
   server = SorobanServer(SOROBAN_SERVER_RPC)
   horizon_server = Server(HORIZON_SERVER)

   # Load distributor's keypair using the secret key
   keypair = Keypair.from_secret(user_secret_key)

   # Load the distributor's account information from Soroban server
   account = server.load_account(keypair.public_key)

   # Build the withdraw transaction
   tx_builder = TransactionBuilder(
       source_account=account,
       network_passphrase=NETWORK_PASSPHRASE,
       base_fee=1000000  # Set base fee; adjust as necessary
   ).set_timeout(3600)  # Set transaction timeout

   # Append the invoke_contract_function operation for withdraw
   tx = tx_builder.append_invoke_contract_function_op(
       contract_id=pool_address,
       function_name="withdraw",
       parameters=[
           Address(keypair.public_key).to_xdr_sc_val(),  # Distributor's address
           scval.to_uint128(share_amount),  # Amount of shares to redeem
           scval.to_vec([
               scval.to_uint128(1),  # Minimum amount of XLM to receive
               scval.to_uint128(1),  # Minimum amount of AQUA to receive
           ]),
       ],
   )
   tx = server.prepare_transaction(tx.build())
   tx.sign(keypair)

   tx_response = horizon_server.submit_transaction(tx)
   transaction_meta = xdr.TransactionMeta.from_xdr(tx_response['result_meta_xdr'])
   tx_result = transaction_meta.v3.soroban_meta.return_value
   if not tx_result:
       raise RuntimeError

   amount_a, amount_b = map(u128_to_int, [r.u128 for r in tx_result.vec.sc_vec])
   print("Withdrawal successful!")
   print(f"Received Amounts: Token A = {amount_a}, Token B = {amount_b}")


# ==========================
# Entry Point
# ==========================
if __name__ == "__main__":
   execute_withdraw()
Copy the full code JavaScript
const StellarSdk = require('@stellar/stellar-sdk');
const {
    Address,
    Contract,
    TransactionBuilder,
    rpc,
    Horizon,
    BASE_FEE,
    Networks,
    xdr,
    TimeoutInfinite,
    XdrLargeInt,
    Keypair,
} = StellarSdk;

// Step 1. Specify user secret key, amount for withdraw and pool addresss
// Distributor's secret key (ensure this is kept secure)
const userSecretKey = "S...";
// XLM/AQUA pool address 
const poolAddress = "CCY2PXGMKNQHO7WNYXEWX76L2C5BH3JUW3RCATGUYKY7QQTRILBZIFWV";
// 1 share in stroops
const shareAmount = 10000000;

// ==========================
// Configuration Variables
// ==========================

// Soroban and Horizon server RPC endpoints
const sorobanServerUrl = 'https://mainnet.sorobanrpc.com';
const horizonServerUrl = 'https://horizon.stellar.org';

// ==========================
// Utility Functions
// ==========================

function u128ToInt(value) {
    /**
     * Converts UInt128Parts from Stellar's XDR to a JavaScript number.
     *
     * @param {Object} value - UInt128Parts object from Stellar SDK, with `hi` and `lo` properties.
     * @returns {number|null} Corresponding JavaScript number, or null if the number is too large.
     */
    const result = (BigInt(value.hi()._value) << 64n) + BigInt(value.lo()._value);

    // Check if the result is within the safe integer range for JavaScript numbers
    if (result <= BigInt(Number.MAX_SAFE_INTEGER)) {
        return Number(result);
    } else {
        console.warn("Value exceeds JavaScript's safe integer range");
        return null;
    }
}

// ==========================
// Withdraw Function
// ==========================

// Step 2. Make a contract call to the pool's "withdraw" method.
async function executeWithdraw() {
    const sorobanServer = new rpc.Server(sorobanServerUrl);
    const horizonServer = new Horizon.Server(horizonServerUrl);

    const sharesToRedeemU128 = new XdrLargeInt('u128', shareAmount.toFixed()).toU128();
    const minimumAmount = new XdrLargeInt('u128', '1').toU128(); // 0.0000001

    // Load distributor's keypair using the secret key
    const keypair = Keypair.fromSecret(userSecretKey);
    
    // Load the distributor's account information from Soroban server
    const account = await sorobanServer.getAccount(keypair.publicKey());

    const contract = new Contract(poolAddress);

    // Build the withdraw transaction
    const tx = new TransactionBuilder(account, {
        fee: BASE_FEE,
        networkPassphrase: Networks.PUBLIC,
    })
    // Append the invoke_contract_function operation for withdraw
    .addOperation(contract.call(
        'withdraw',
        xdr.ScVal.scvAddress(Address.fromString(keypair.publicKey()).toScAddress()), // Distributor's address
        sharesToRedeemU128, // Amount of shares to redeem
        xdr.ScVal.scvVec([minimumAmount, minimumAmount]), // Minimum amounts of Token A and Token B to receive
    )).setTimeout(TimeoutInfinite).build();

    const preparedTx = await sorobanServer.prepareTransaction(tx);

    preparedTx.sign(keypair);

    const result = await horizonServer.submitTransaction(preparedTx);

    const meta = (await sorobanServer.getTransaction(result.id)).resultMetaXdr;

    const returnValue = meta.v3().sorobanMeta().returnValue();

    const [withdrawalA, withdrawalB] = returnValue.value().map(value => u128ToInt(value.value()));

    console.log('Withdrawal successful!');
    console.log(`Received Amounts: Token A = ${withdrawalA / 1e7}, Token B = ${withdrawalB / 1e7}`);
}

// ==========================
// Entry Point
// ==========================
executeWithdraw();

To successfully execute the code, provide the secret key of a Stellar account with at least 1 share in the .

pool XLM / AQUA
this XLM-AQUA pool
deposit
here