Withdraw Liquidity
Example of code that withdraw liquidity from Aquarius pool
Last updated
Example of code that withdraw liquidity from Aquarius pool
Last updated
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.
To perform a withdraw, you need to follow these steps:
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;
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}`);
}
This code withdraw 1 share from the pool with Aquarius AMM on mainnet.
# 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()
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 .