# Executing Swaps Through Specific Pool

In this example we will swap 1 XLM to AQUA with Aquarius AMM. The swap will be executed by calling corresponding method of specific liquidity pool.&#x20;

Direct swap through specific pool is good for contract sub-invocations as it requires less resources than chained path swap. But direct swap may lead to less optimal result.

:point\_up: Please make sure account has established trustline for asset to receive. Otherwise, swap will fail until trustline is created. For more information please refer to[ documentation on Stellar.org](https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines).

Scroll [here](#complete-code-examples) to see the complete code.&#x20;

### Executing Swap: Step by Step Guide

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

1\. **Identify pool address**: This part was covered earlier, please check [corresponding article](https://docs.aqua.network/developers/prerequisites-and-basics#get-pool-contract-id-and-pool-hash).

2\. **Specify user secret key, pool address, amount in, input and output token indices**: You need to specify pool address, the amount of the input token you want to swap in stroops and swap direction by in and out tokens.

{% tabs %}
{% tab title="Python" %}

```python
# Your Secret Key (keep it secure!)
user_secret_key = "S......."
# XLM/AQUA pool address
pool_address = "CCY2PXGMKNQHO7WNYXEWX76L2C5BH3JUW3RCATGUYKY7QQTRILBZIFWV"

# Amount in (0.1 XLM), in stroops (1 XLM = 10^7 stroops)
amount_in = 1000000
# tokens are [XLM, AQUA], so XLM index is 0
in_idx = 0
out_idx = 1
# slippage percent
slippage_percent = 1
```

{% endtab %}

{% tab title="Javascript" %}

```typescript
// Your Secret Key (keep it secure!)
const userSecretKey = "S.......";
// XLM/AQUA pool address
const poolAddress = "CCY2PXGMKNQHO7WNYXEWX76L2C5BH3JUW3RCATGUYKY7QQTRILBZIFWV";
// 0.1 XLM in stroops
const amountIn = 1000000;
// tokens are [XLM, AQUA], so XLM index is 0
const inIdx = 0;
const outIdx = 1;
// slippage percent
const slippagePercent = 1;
```

{% endtab %}
{% endtabs %}

3\. **Calculate minimum amount of token to receive**: This can be achieved by simulating *estimate\_swap* pool method.

{% tabs %}
{% tab title="Python" %}

```python
def estimate_swap():
    print("Estimating swap amount...")
    soroban_server = SorobanServer(soroban_server_url)
    keypair = Keypair.from_secret(user_secret_key)

    source_account = soroban_server.load_account(keypair.public_key)
    tx = (
        TransactionBuilder(
            source_account=source_account,
            network_passphrase=Network.PUBLIC_NETWORK_PASSPHRASE,
            base_fee=100
        )
        .append_invoke_contract_function_op(
            contract_id=pool_address,
            function_name="estimate_swap",
            parameters=[
                scval.to_uint32(in_idx),
                scval.to_uint32(out_idx),
                scval.to_uint128(amount_in),
            ]
        )
        .set_timeout(300)
        .build()
    )

    print("Simulating 'estimate_swap' transaction...")
    sim_result = soroban_server.simulate_transaction(tx)
    if not sim_result or sim_result.error:
        print("Simulation failed.", sim_result.error if sim_result else "")
        return math.nan

    retval = xdr.SCVal.from_xdr(sim_result.results[0].xdr)
    estimated = u128_to_int(retval.u128)
    print(f"Estimated result: {estimated / 1e7}")
    return estimated
```

{% endtab %}

{% tab title="Javascript" %}

```typescript
async function estimateSwap() {
    const sorobanServer = new rpc.Server(sorobanServerUrl);

    const amount = new XdrLargeInt("u128", amountIn.toFixed()).toU128();

    const inIdxSCVal = xdr.ScVal.scvU32(inIdx);
    const outIdxSCVal = xdr.ScVal.scvU32(outIdx);

    const keypair = Keypair.fromSecret(userSecretKey);
    // Load the user 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(
                "estimate_swap",
                inIdxSCVal,
                outIdxSCVal,
                amount,
            ),
        )
        .setTimeout(TimeoutInfinite)
        .build();

    // Simulate the result
    const simulateResult = await sorobanServer.simulateTransaction(tx);

    if (!simulateResult.result) {
        console.log(simulateResult.error);
        console.log("Unable to simulate transaction");
        return NaN;
    }

    const result = u128ToInt(simulateResult.result.retval.value());

    console.log(`Estimated result: ${result}`);

    return result;
}
```

{% endtab %}
{% endtabs %}

4\. **Perform swap operation by submitting corresponding transaction.**

{% tabs %}
{% tab title="Python" %}

```python
def execute_swap():
    print("Executing swap...")
    soroban_server = SorobanServer(soroban_server_url)
    horizon_server = Server(horizon_server_url)
    keypair = Keypair.from_secret(user_secret_key)

    estimated_result = estimate_swap()
    if math.isnan(estimated_result):
        print("Estimation failed. Cannot proceed with swap.")
        return

    # Calculate minimum out after slippage
    slippage_coefficient = (100 - slippage_percent) / 100.0
    minimum_out = math.floor(estimated_result * slippage_coefficient)

    # Build swap transaction
    source_account = soroban_server.load_account(keypair.public_key)
    tx = (
        TransactionBuilder(
            source_account=source_account,
            network_passphrase=Network.PUBLIC_NETWORK_PASSPHRASE,
            base_fee=100
        )
        .append_invoke_contract_function_op(
            contract_id=pool_address,
            function_name="swap",
            parameters=[
                scval.to_address(keypair.public_key),
                scval.to_uint32(in_idx),
                scval.to_uint32(out_idx),
                scval.to_uint128(amount_in),
                scval.to_uint128(minimum_out),
            ]
        )
        .set_timeout(300)
        .build()
    )

    print("Preparing transaction for submission...")
    prepared_tx = soroban_server.prepare_transaction(tx)
    prepared_tx.sign(keypair)

    print("Submitting transaction to Horizon...")
    response = horizon_server.submit_transaction(prepared_tx)
    if 'result_meta_xdr' not in response:
        print("Transaction failed.")
        return

    meta = xdr.TransactionMeta.from_xdr(response['result_meta_xdr'])
    if meta.v3 and meta.v3.soroban_meta:
        out_value = u128_to_int(meta.v3.soroban_meta.return_value.u128)
        print("Swap successful!")
        print(f"Received token out: {out_value / 1e7}")
    else:
        print("No result returned by the contract.")
```

{% endtab %}

{% tab title="Javascript" %}

```typescript
async function executeSwap() {
    const sorobanServer = new rpc.Server(sorobanServerUrl);
    const horizonServer = new Horizon.Server(horizonServerUrl);

    const amount = new XdrLargeInt("u128", amountIn.toFixed()).toU128();

    const slippageCoefficient = (100 - slippagePercent) / 100;
    const estimatedResult = await estimateSwap();
    const estimateWithSlippage = Math.floor(estimatedResult * slippageCoefficient);
    const minimumOut = new XdrLargeInt("u128", estimateWithSlippage.toFixed()).toU128();

    const inIdxSCVal = xdr.ScVal.scvU32(inIdx);
    const outIdxSCVal = xdr.ScVal.scvU32(outIdx);

    const keypair = Keypair.fromSecret(userSecretKey);
    // Load the user account information from Soroban server
    const account = await sorobanServer.getAccount(keypair.publicKey());

    const contract = new Contract(poolAddress);

    // Build the swap transaction
    const tx = new TransactionBuilder(account, {
        fee: BASE_FEE,
        networkPassphrase: Networks.PUBLIC,
    })
        // Append the invoke_contract_function operation for swap
        .addOperation(
            contract.call(
                "swap",
                xdr.ScVal.scvAddress(
                    Address.fromString(keypair.publicKey()).toScAddress(),
                ),
                inIdxSCVal,
                outIdxSCVal,
                amount,
                minimumOut,
            ),
        )
        .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 swapped amount
    const outValue = u128ToInt(returnValue.value());

    console.log("Swap successful!");
    console.log(`Received token out: ${outValue / 1e7}`);
}
```

{% endtab %}
{% endtabs %}

### Complete Code Examples

This code swaps 1 XLM to AQUA with Aquarius AMM on mainnet.

To successfully execute the code, provide the secret key of a Stellar account with at least 3 XLM and an established trustline for AQUA.

<details>

<summary>Copy the full code JavaScript</summary>

```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, pool address, amount in and direction

// User secret key (ensure this is kept secure)
const userSecretKey = "S.......";
// XLM/AQUA pool address
const poolAddress = "CCY2PXGMKNQHO7WNYXEWX76L2C5BH3JUW3RCATGUYKY7QQTRILBZIFWV";
// 0.1 XLM in stroops
const amountIn = 1000000;
// tokens are [XLM, AQUA], so XLM index is 0
const inIdx = 0;
const outIdx = 1;
// slippage percent
const slippagePercent = 1;

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

// ==========================
// Swap Function
// ==========================

async function estimateSwap() {
    const sorobanServer = new rpc.Server(sorobanServerUrl);

    const amount = new XdrLargeInt("u128", amountIn.toFixed()).toU128();

    const inIdxSCVal = xdr.ScVal.scvU32(inIdx);
    const outIdxSCVal = xdr.ScVal.scvU32(outIdx);

    const keypair = Keypair.fromSecret(userSecretKey);
    // Load the user 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(
                "estimate_swap",
                inIdxSCVal,
                outIdxSCVal,
                amount,
            ),
        )
        .setTimeout(TimeoutInfinite)
        .build();

    // Simulate the result
    const simulateResult = await sorobanServer.simulateTransaction(tx);

    if (!simulateResult.result) {
        console.log(simulateResult.error);
        console.log("Unable to simulate transaction");
        return NaN;
    }

    const result = u128ToInt(simulateResult.result.retval.value());

    console.log(`Estimated result: ${result}`);

    return result;
}

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

    const amount = new XdrLargeInt("u128", amountIn.toFixed()).toU128();

    const slippageCoefficient = (100 - slippagePercent) / 100;
    const estimatedResult = await estimateSwap();
    const estimateWithSlippage = Math.floor(estimatedResult * slippageCoefficient);
    const minimumOut = new XdrLargeInt("u128", estimateWithSlippage.toFixed()).toU128();

    const inIdxSCVal = xdr.ScVal.scvU32(inIdx);
    const outIdxSCVal = xdr.ScVal.scvU32(outIdx);

    const keypair = Keypair.fromSecret(userSecretKey);
    // Load the user account information from Soroban server
    const account = await sorobanServer.getAccount(keypair.publicKey());

    const contract = new Contract(poolAddress);

    // Build the swap transaction
    const tx = new TransactionBuilder(account, {
        fee: BASE_FEE,
        networkPassphrase: Networks.PUBLIC,
    })
        // Append the invoke_contract_function operation for swap
        .addOperation(
            contract.call(
                "swap",
                xdr.ScVal.scvAddress(
                    Address.fromString(keypair.publicKey()).toScAddress(),
                ),
                inIdxSCVal,
                outIdxSCVal,
                amount,
                minimumOut,
            ),
        )
        .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 swapped amount
    const outValue = u128ToInt(returnValue.value());

    console.log("Swap successful!");
    console.log(`Received token out: ${outValue / 1e7}`);
}

// ==========================
// Entry Point
// ==========================
executeSwap();

```

</details>

<details>

<summary>Copy the full code Python</summary>

```python
from stellar_sdk import (
    Keypair,
    TransactionBuilder,
    Network,
    Server,
    xdr,
    scval,
    SorobanServer,
)
import math

# =========================================
# Configuration and Input Variables
# =========================================

user_secret_key = "S......"  # Keep this secret
pool_address = "CCY2PXGMKNQHO7WNYXEWX76L2C5BH3JUW3RCATGUYKY7QQTRILBZIFWV"

# 0.1 XLM in stroops (1 XLM = 10^7 stroops)
amount_in = 1000000

# Token indices: [XLM, AQUA]
in_idx = 0
out_idx = 1

# Slippage in percent
slippage_percent = 1

# Servers
soroban_server_url = "https://mainnet.sorobanrpc.com"
horizon_server_url = "https://horizon.stellar.org"


# =========================================
# Utility Functions
# =========================================
def u128_to_int(parts: xdr.UInt128Parts) -> int:
    """Convert Uint128Parts to Python int."""
    return (parts.hi.uint64 << 64) + parts.lo.uint64


# =========================================
# Soroban Functions
# =========================================
def estimate_swap():
    print("Estimating swap amount...")
    soroban_server = SorobanServer(soroban_server_url)
    keypair = Keypair.from_secret(user_secret_key)

    source_account = soroban_server.load_account(keypair.public_key)
    tx = (
        TransactionBuilder(
            source_account=source_account,
            network_passphrase=Network.PUBLIC_NETWORK_PASSPHRASE,
            base_fee=100
        )
        .append_invoke_contract_function_op(
            contract_id=pool_address,
            function_name="estimate_swap",
            parameters=[
                scval.to_uint32(in_idx),
                scval.to_uint32(out_idx),
                scval.to_uint128(amount_in),
            ]
        )
        .set_timeout(300)
        .build()
    )

    print("Simulating 'estimate_swap' transaction...")
    sim_result = soroban_server.simulate_transaction(tx)
    if not sim_result or sim_result.error:
        print("Simulation failed.", sim_result.error if sim_result else "")
        return math.nan

    retval = xdr.SCVal.from_xdr(sim_result.results[0].xdr)
    estimated = u128_to_int(retval.u128)
    print(f"Estimated result: {estimated / 1e7}")
    return estimated


def execute_swap():
    print("Executing swap...")
    soroban_server = SorobanServer(soroban_server_url)
    horizon_server = Server(horizon_server_url)
    keypair = Keypair.from_secret(user_secret_key)

    estimated_result = estimate_swap()
    if math.isnan(estimated_result):
        print("Estimation failed. Cannot proceed with swap.")
        return

    # Calculate minimum out after slippage
    slippage_coefficient = (100 - slippage_percent) / 100.0
    minimum_out = math.floor(estimated_result * slippage_coefficient)

    # Build swap transaction
    source_account = soroban_server.load_account(keypair.public_key)
    tx = (
        TransactionBuilder(
            source_account=source_account,
            network_passphrase=Network.PUBLIC_NETWORK_PASSPHRASE,
            base_fee=100
        )
        .append_invoke_contract_function_op(
            contract_id=pool_address,
            function_name="swap",
            parameters=[
                scval.to_address(keypair.public_key),
                scval.to_uint32(in_idx),
                scval.to_uint32(out_idx),
                scval.to_uint128(amount_in),
                scval.to_uint128(minimum_out),
            ]
        )
        .set_timeout(300)
        .build()
    )

    print("Preparing transaction for submission...")
    prepared_tx = soroban_server.prepare_transaction(tx)
    prepared_tx.sign(keypair)

    print("Submitting transaction to Horizon...")
    response = horizon_server.submit_transaction(prepared_tx)
    if 'result_meta_xdr' not in response:
        print("Transaction failed.")
        return

    meta = xdr.TransactionMeta.from_xdr(response['result_meta_xdr'])
    if meta.v3 and meta.v3.soroban_meta:
        out_value = u128_to_int(meta.v3.soroban_meta.return_value.u128)
        print("Swap successful!")
        print(f"Received token out: {out_value / 1e7}")
    else:
        print("No result returned by the contract.")


# =========================================
# Entry Point
# =========================================
if __name__ == "__main__":
    execute_swap()

```

</details>
