# Deploying a New Fee Collector

To start receiving fees from swaps you will need to deploy the fee collector contract instance using the **Provider Swap Fee Factory**:

Provider Swap Fee Factory address is `CA4Q2T6FRAFYJYSMDJV7F6B7RL5PS6QS2UOZHBMCT2KSMGQRAAKP2MKO`

* **Function:**\
  `deploy_swap_fee_contract(operator: Address, fee_destination: Address, max_swap_fee_fraction: u32, swap_fee_fraction_denominator: u32) -> Address`
* **Returns:**\
  Address of the newly deployed **ProviderSwapFeeCollector**.

Parameters explained:

* `operator`- an address that will be able to [claim fees](https://docs.aqua.network/developers/code-examples/add-fees-to-swap/claiming-and-swapping-accumulated-fees)
* `fee_destination` - an address that will be able to receive the claimed fees.&#x20;
* `max_swap_fee_fraction` - maximum value of a swap fee that a given fee collector instance can accept. &#x20;
* `swap_fee_fraction_denominator` - basis points denominator. 10000 works well as starting point. however, it can be increased for extended fee resolution.

Notes:

* `operator` and `fee_destination` addresses can be the same but we recommend using different addresses for greater security.
* `fee_destination` must have all the trustlines in case the `operator` withdraw "raw" fees accumulated in various currencies. Aquarius has a mechanism to settle fees in one single currency though.
* on [executing swaps with fees](https://docs.aqua.network/developers/code-examples/add-fees-to-swap/executing-swaps-with-provider-fees) you can set a dynamic fee but not exceeding the `max_swap_fee_fraction` parameter.

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

```python
import binascii

from stellar_sdk import Keypair, Network, scval, Server, SorobanServer, StrKey, TransactionBuilder, xdr


def main():
    # =========================================
    # Configuration & Setup
    # =========================================
    # Operator account to be assigned as the fee contract operator
    operator_secret_key = "SA..........."
    operator_keypair = Keypair.from_secret(operator_secret_key)

    # Address to receive the swap fees
    fee_destination_address = "GC..........."

    # Factory contract for provider swap fee contracts (already deployed on network)
    provider_fee_factory_contract_id = "CA4Q2T6FRAFYJYSMDJV7F6B7RL5PS6QS2UOZHBMCT2KSMGQRAAKP2MKO"

    # Maximum allowed swap fee in basis points
    #   (depends on denominator, e.g. 100 bps with 10000 denominator = 1% fee)
    max_swap_fee_bps = 100    # 100 bps = 1% = 100 / 10000
    swap_fee_bps_denominator = 10000

    # Soroban and Horizon server endpoints (adjust for your network)
    soroban_server = SorobanServer("https://mainnet.sorobanrpc.com")
    horizon_server = Server("https://horizon.stellar.org/")
    network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE

    # =========================================
    # Build Transaction to Deploy Provider Swap Fee Contract
    # =========================================
    # This transaction calls:
    #   deploy_swap_fee_contract(
    #       operator: Address,
    #       fee_destination: Address,
    #       swap_fee_bps: u32,
    #       swap_fee_fraction_denominator: u32,
    #   )
    # on the provider fee factory contract; it returns the address of the newly deployed fee contract.

    # Load operator account from Horizon (must have sufficient XLM)
    source_account = horizon_server.load_account(operator_keypair.public_key)

    # Build transaction
    tx = (
        TransactionBuilder(
            source_account=source_account,
            network_passphrase=network_passphrase,
            base_fee=10000
        )
        .set_timeout(300)
        .append_invoke_contract_function_op(
            contract_id=provider_fee_factory_contract_id,
            function_name="deploy_swap_fee_contract",
            parameters=[
                # operator address (as an SCVal address)
                scval.to_address(operator_keypair.public_key),
                # fee destination address (as an SCVal address)
                scval.to_address(fee_destination_address),
                # max swap fee in basis points (as a uint32)
                scval.to_uint32(max_swap_fee_bps),
                # swap fee bps denominator (as a uint32)
                scval.to_uint32(swap_fee_bps_denominator),
            ]
        )
        .build()
    )

    prepared_tx = soroban_server.prepare_transaction(tx)

    # Sign the transaction with the operator keypair
    prepared_tx.sign(operator_keypair)

    print("Submitting transaction to Horizon...")
    horizon_response = horizon_server.submit_transaction(prepared_tx)
    if not horizon_response['successful']:
        print("Transaction submission failed.")
        return

    response = soroban_server.get_transaction(horizon_response['hash'])
    if not response.result_meta_xdr:
        print("No meta in response.")
        return

    meta = xdr.TransactionMeta.from_xdr(response.result_meta_xdr)
    if meta.v3 and meta.v3.soroban_meta:
        address = StrKey.encode_contract(
            binascii.unhexlify(meta.v3.soroban_meta.return_value.address.contract_id.hash.hex()))
        print("Deploy successful!")
        print(f"Deployed address: {address}")
    else:
        print("No result returned by the contract.")


if __name__ == "__main__":
    main()

```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const {
    Keypair,
    Networks,
    Horizon,
    TransactionBuilder,
    rpc,
    nativeToScVal,
    Address,
    Operation,
    StrKey,
} = require('@stellar/stellar-sdk');

async function main() {
    // =========================================
    // Configuration & Setup
    // =========================================
    
    // Operator account to be assigned as the fee contract operator
    const operatorSecretKey = 'SA...........';
    // Address to receive the swap fees
    const feeDestinationAddress = 'GC...........';
    // Factory contract for provider swap fee contracts (already deployed on network)
    const providerFeeFactoryContractId = 'CA4Q2T6FRAFYJYSMDJV7F6B7RL5PS6QS2UOZHBMCT2KSMGQRAAKP2MKO';
    // Maximum allowed swap fee in basis points
    //   (depends on denominator, e.g. 100 bps with 10000 denominator = 1% fee)
    const maxSwapFeeBps = 100;
    const swapFeeBpsDenominator = 10000;

    // Soroban and Horizon server endpoints (adjust for your network)
    const sorobanServer = new rpc.Server('https://mainnet.sorobanrpc.com');
    const horizonServer = new Horizon.Server('https://horizon.stellar.org');
    const networkPassphrase = Networks.PUBLIC;

    const operatorKeypair = Keypair.fromSecret(operatorSecretKey);

    // =========================================
    // Load operator account
    // =========================================
    const account = await horizonServer.loadAccount(operatorKeypair.publicKey());

    // =========================================
    // Build transaction
    // =========================================
    
    // This transaction calls:
    //   deploy_swap_fee_contract(
    //       operator: Address,
    //       fee_destination: Address,
    //       swap_fee_bps: u32,
    //       swap_fee_fraction_denominator: u32,
    //   )
    // on the provider fee factory contract; it returns the address of the newly deployed fee contract.

    // Build transaction
    const tx = new TransactionBuilder(account, {
        fee: '10000',
        networkPassphrase,
    })
        .setTimeout(300)
        .addOperation(
            Operation.invokeContractFunction({
                contract: providerFeeFactoryContractId,
                function: 'deploy_swap_fee_contract',
                args: [
                    nativeToScVal(new Address(operatorKeypair.publicKey())),
                    nativeToScVal(new Address(feeDestinationAddress)),
                    nativeToScVal(maxSwapFeeBps, { type: 'u32' }),
                    nativeToScVal(swapFeeBpsDenominator, { type: 'u32' }),
                ]
            }),
        )
        .build();

    const preparedTx = await sorobanServer.prepareTransaction(tx);

    // Sign the transaction with the operator keypair
    preparedTx.sign(operatorKeypair);

    console.log('Submitting transaction to Horizon...');
    try {
        const txResponse = await horizonServer.submitTransaction(preparedTx);

        if (!txResponse.successful) {
            console.error('Transaction failed.');
            return;
        }

        const txStatus = await sorobanServer.getTransaction(txResponse.hash);
        if (!txStatus?.resultMetaXdr) {
            console.log('No meta in response.');
            return;
        }

        const resultValue = txStatus.returnValue;

        if (resultValue.value().value()) {
            const contractId = StrKey.encodeContract(resultValue.value().value());
            console.log('Deploy successful!');
            console.log(`Deployed address: ${contractId}`);
        } else {
            console.log('No result returned by the contract.');
        }
    } catch (err) {
        console.error('Transaction error:', err.response?.data || err.message);
    }
}

main();


```

{% endtab %}
{% endtabs %}
