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 CCEG2NHI3RO545HEMV4HQLIEPNXIBDOVXXD3DLOK727CMVBVNPOQJUFB

  • Function: deploy_swap_fee_contract(operator: Address, fee_destination: Address, max_swap_fee_fraction: u32) -> Address

  • Returns: Address of the newly deployed ProviderSwapFeeCollector.

Parameters explained:

  • operator- an address that will be able to claim fees

  • fee_destination - an address that will be able to receive the claimed fees.

  • max_swap_fee_fraction - maximum value of a swap fee that a given fee collector instance can accept.

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 you can set a dynamic fee but not exceeding the max_swap_fee_fraction parameter.

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 (e.g. 100 bps = 1% fee)
    max_swap_fee_bps = 100

    # 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, swap_fee_bps: 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)
            ]
        )
        .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()

Last updated