Deposit Liquidity

Example of code that deposits liquidity into Aquarius pool

On this page, we demonstrate how to deposit 0.1 XLM and 25 AQUA into a specific AQUA/XLM pool. Scroll here to see the complete code.

Executing Deposit: Step by Step Guide

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

  1. Specify user secret key, amounts for deposit and pool address: To deposit into a pool, you need your user secret key, the amounts to deposit (specified in stroops) and the pool address. The amounts must be passed to the contract call in the same order as they are indexed in the pool (an example of token sorting can be found here).

# Distributor's secret key (ensure this is kept secure)
user_secret_key = "S..."
# XLM/AQUA pool address 
pool_address = "CCY2PXGMKNQHO7WNYXEWX76L2C5BH3JUW3RCATGUYKY7QQTRILBZIFWV"
# 0.1 XLM in stroops
amount_a = 1_000000
# 25 AQUA in stroops
amount_b = 25_0000000
  1. Make a contract call to the pool's "deposit" method.

def execute_deposit():
   # 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 deposit 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 deposit
   tx = tx_builder.append_invoke_contract_function_op(
       contract_id=pool_address,
       function_name="deposit",
       parameters=[
           Address(keypair.public_key).to_xdr_sc_val(),  # Distributor's address
           scval.to_vec([
               scval.to_uint128(amount_a),  # Amount of XLM to deposit
               scval.to_uint128(amount_b),  # Amount of AQUA to deposit
           ]),
           scval.to_uint128(0),  # Additional parameter (e.g., minimum shares)
       ],
   ).build()

   # Prepare and sign the transaction
   prepared_tx = server.prepare_transaction(tx)
   prepared_tx.sign(keypair)

   # Submit the transaction to the Horizon server
   tx_response = horizon_server.submit_transaction(prepared_tx)

   # Parse the transaction metadata to extract results
   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("Transaction did not return a result. Deposit failed.")

   # Extract deposited amounts and shares from the transaction result
   deposit_a, deposit_b = map(u128_to_int, [r.u128 for r in tx_result.vec.sc_vec[0].vec.sc_vec])
   shares_amount = u128_to_int(tx_result.vec.sc_vec[1].u128)

   print("Deposit successful!")
   print(f"Deposited Amounts: Token A = {deposit_a}, Token B = {deposit_b}")
   print(f"Received Shares: {shares_amount}")

Complete Code Examples

This code deposits 0.1 XLM and 25 AQUA to the pool with Aquarius AMM on mainnet.

To successfully execute the code, provide the secret key of a Stellar account with at least 5 XLM and 25 AQUA.

Copy the full code Python
# deposit.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, amounts for deposit and pool address

# Distributor's secret key (ensure this is kept secure)
user_secret_key = "S..."
# XLM/AQUA pool address 
pool_address = "CCY2PXGMKNQHO7WNYXEWX76L2C5BH3JUW3RCATGUYKY7QQTRILBZIFWV"
# 0.1 XLM in stroops
amount_a = 1_000000
# 25 AQUA in stroops
amount_b = 25_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 (value.hi.uint64 << 64) + value.lo.uint64


# ==========================
# Deposit Function
# ==========================

# Step 2. Make a contract call to the pool's "deposit" method.
def execute_deposit():
   # 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 deposit 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 deposit
   tx = tx_builder.append_invoke_contract_function_op(
       contract_id=pool_address,
       function_name="deposit",
       parameters=[
           Address(keypair.public_key).to_xdr_sc_val(),  # Distributor's address
           scval.to_vec([
               scval.to_uint128(amount_a),  # Amount of XLM to deposit
               scval.to_uint128(amount_b),  # Amount of AQUA to deposit
           ]),
           scval.to_uint128(0),  # Additional parameter (e.g., minimum shares)
       ],
   ).build()

   # Prepare and sign the transaction
   prepared_tx = server.prepare_transaction(tx)
   prepared_tx.sign(keypair)

   # Submit the transaction to the Horizon server
   tx_response = horizon_server.submit_transaction(prepared_tx)

   # Parse the transaction metadata to extract results
   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("Transaction did not return a result. Deposit failed.")

   # Extract deposited amounts and shares from the transaction result
   deposit_a, deposit_b = map(u128_to_int, [r.u128 for r in tx_result.vec.sc_vec[0].vec.sc_vec])
   shares_amount = u128_to_int(tx_result.vec.sc_vec[1].u128)

   print("Deposit successful!")
   print(f"Deposited Amounts: Token A = {deposit_a}, Token B = {deposit_b}")
   print(f"Received Shares: {shares_amount}")


# ==========================
# Entry Point
# ==========================

if __name__ == "__main__":
   execute_deposit()
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, amounts for deposit and pool address

// Distributor's secret key (ensure this is kept secure)
const userSecretKey = "S...";
// XLM/AQUA pool address
const poolAddress = "CCY2PXGMKNQHO7WNYXEWX76L2C5BH3JUW3RCATGUYKY7QQTRILBZIFWV"
// 0.1 XLM in stroops
const amountA = 1000000;
// 25 AQUA in stroops
const amountB = 250000000;


// ==========================
// 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;
    }
}

// ==========================
// Deposit Function
// ==========================

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

    const amountAU128 = new XdrLargeInt('u128', amountA.toFixed()).toU128();
    const amountBU128 = new XdrLargeInt('u128', amountB.toFixed()).toU128();

    const minimumShares = new XdrLargeInt('u128', '1').toU128(); // 0.0000001

    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 deposit transaction
    const tx = new TransactionBuilder(account, {
        fee: BASE_FEE,
        networkPassphrase: Networks.PUBLIC,
    })
    // Append the invoke_contract_function operation for deposit
    .addOperation(contract.call(
        'deposit',
        xdr.ScVal.scvAddress(Address.fromString(keypair.publicKey()).toScAddress()), // Distributor's address
        xdr.ScVal.scvVec([amountAU128, amountBU128]), // Amounts of Token A and Token B to deposit
        minimumShares, // Additional parameter (e.g., minimum shares)
    )).setTimeout(TimeoutInfinite).build();


    // Prepare and sign the transaction
    const preparedTx = await sorobanServer.prepareTransaction(tx);
    preparedTx.sign(keypair);

    // Submit the transaction to the Horizon server
    const result = await horizonServer.submitTransaction(preparedTx);

    // Parse the transaction metadata to extract results
    const meta = (await sorobanServer.getTransaction(result.id)).resultMetaXdr;
    const returnValue = meta.v3().sorobanMeta().returnValue();

    // Extract deposited amounts and shares from the transaction result
    const [deposited, share] = returnValue.value();
    const [depositedA, depositedB] = deposited.value().map(value => u128ToInt(value.value()));
    const shareValue =  u128ToInt(share.value());


    console.log('Deposit successful!');
    console.log(`Deposited Amounts: Token A = ${depositedA / 1e7}, Token B = ${depositedB / 1e7}`);
    console.log(`Received Shares: ${shareValue / 1e7}`);
}

// ==========================
// Entry Point
// ==========================
executeDeposit();

Last updated