Get Pools Info

# get_pools.py
import binascii
from typing import List

from stellar_sdk import Address, Keypair, scval, SorobanServer, xdr, TransactionBuilder, Server, StrKey
from stellar_sdk.xdr import UInt128Parts

# ==========================
# Configuration Variables
# ==========================

# Soroban and Horizon server RPC endpoints
SOROBAN_SERVER_RPC = 'https://soroban-testnet.stellar.org:443/'
HORIZON_SERVER = 'https://horizon-testnet.stellar.org'

# Distributor's secret key (ensure this is kept secure)
SECRET = 'SCJF..........KTXQ'

# Contract IDs for the router and tokens
ROUTER_CONTRACT_ID = 'CDMSJQ4TPCTAYDRYN46FVMYIWV2A4ZTHCWWIN2NW3QZIFPJWBBEGDKDY'
TOKEN_A_CONTRACT_ID = 'CAZRY5GSFBFXD7H6GAFBA5YGYQTDXU4QKWKMYFWBAZFUCURN3WKX6LF5'
TOKEN_B_CONTRACT_ID = 'CBL6KD2LFMLAUKFFWNNXWOXFN73GAXLEA4WMJRLQ5L76DMYTM3KWQVJN'

# Stellar network passphrase and known pool hash
NETWORK_PASSPHRASE = 'Test SDF Network ; September 2015'


# ==========================
# Utility Functions
# ==========================

def order_token_ids(tokens: List[xdr.SCVal]) -> List[xdr.SCVal]:
   """
   Orders token IDs based on their contract ID to maintain consistency.

   Args:
       tokens (List[xdr.SCVal]): List of token addresses as SCVal objects.

   Returns:
       List[xdr.SCVal]: Ordered list of token SCVal objects.
   """
   return sorted(tokens, key=lambda token: int(token.address.contract_id.hash.hex(), 16))


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


def get_pools(server, address, router_contract_id, tokens: list[str]) -> dict:
   tx_builder = TransactionBuilder(
       source_account=server.load_account(address),
       network_passphrase=NETWORK_PASSPHRASE,
       base_fee=1000000  # Set base fee; adjust as necessary
   ).set_timeout(3600)  # Set transaction timeout
   tx = (
       tx_builder
       .append_invoke_contract_function_op(
           contract_id=router_contract_id,
           function_name="get_pools",
           parameters=[
               scval.to_vec(order_token_ids([
                   Address(token).to_xdr_sc_val()
                   for token in tokens
               ])),
           ],
       )
       .build()
   )

   simulation = server.simulate_transaction(tx)
   tx_result = [xdr.SCVal.from_xdr(r.xdr) for r in simulation.results][0]
   if not tx_result:
       raise RuntimeError

   return {
       entry.key.bytes.sc_bytes.hex(): StrKey.encode_contract(binascii.unhexlify(entry.val.address.contract_id.hash.hex()))
       for entry in tx_result.map.sc_map
   }


def execute():
   server = SorobanServer(SOROBAN_SERVER_RPC)

   keypair = Keypair.from_secret(SECRET)

   # Order token IDs to ensure consistency
   token_a = scval.to_address(TOKEN_A_CONTRACT_ID)
   token_b = scval.to_address(TOKEN_B_CONTRACT_ID)
   pools = get_pools(
       server,
       keypair.public_key,
       ROUTER_CONTRACT_ID,
       [TOKEN_A_CONTRACT_ID, TOKEN_B_CONTRACT_ID],
   )

   for pool_hash, pool_id in pools.items():
       print(f"pool '{pool_hash}', '{pool_id}'")
       tx = (
           TransactionBuilder(
               source_account=server.load_account(keypair.public_key),
               network_passphrase=NETWORK_PASSPHRASE,
               base_fee=1000000
           ).set_timeout(3600)
           .append_invoke_contract_function_op(
               contract_id=ROUTER_CONTRACT_ID,
               function_name="get_info",
               parameters=[
                   scval.to_vec(order_token_ids([token_a, token_b])),
                   scval.to_bytes(bytes.fromhex(pool_hash)),  # Known pool hash as bytes
               ],
           )
           .build()
       )
       simulation = server.simulate_transaction(tx)
       tx_result = [xdr.SCVal.from_xdr(r.xdr) for r in simulation.results][0]
       if not tx_result:
           raise RuntimeError
       pool_info = {
           entry.key.sym.sc_symbol.decode(): entry.val
           for entry in tx_result.map.sc_map
       }
       pool_info['pool_type'] = pool_info['pool_type'].sym.sc_symbol.decode()
       pool_info['fee'] = "{0}%".format(str(int(pool_info['fee'].u32.uint32) / 10_000 * 100))
       if 'a' in pool_info:
           pool_info['a'] = u128_to_int(pool_info['a'].u128)
       if 'n_tokens' in pool_info:
           pool_info['n_tokens'] = int(pool_info['n_tokens'].u32.uint32)

       print('pool hash', pool_hash)
       for key, value in pool_info.items():
           print(key, value)
       print('-------')


if __name__ == "__main__":
   execute()

Last updated