Skip to content

Pathfinder

Pathfinding is available in the Rust SDK today (read-only). Compute flow matrices and contract params; execution is runner-dependent.

Local pathfinding (crate)

use circles_pathfinder::{prepare_flow_for_contract, FindPathParams};
use alloy_primitives::U256;
 
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let params = FindPathParams {
        from: "0x1234567890123456789012345678901234567890".parse()?,
        to: "0x0987654321098765432109876543210987654321".parse()?,
        target_flow: U256::from(1_000_000_000_000_000_000u64), // 1 token
        use_wrapped_balances: Some(true),
        from_tokens: None,
        to_tokens: None,
        exclude_from_tokens: None,
        exclude_to_tokens: None,
        simulated_balances: None,
        max_transfers: Some(6),
    };
 
    let flow = prepare_flow_for_contract("https://rpc.aboutcircles.com/", params).await?;
    let (vertices, edges, streams, coordinates) = flow.into_contract_params();
    println!("vertices: {}, edges: {}", vertices.len(), edges.len());
 
    // Runner-dependent: submit to contracts when runner is available.
    // runner.transfer_flow(vertices, edges, streams, coordinates).await?;
    Ok(())
}

RPC pathfinding (circles-rpc)

use circles_rpc::{PathfinderMethods, RpcClient};
use circles_types::FindPathParams;
use alloy_primitives::U256;
use reqwest::Url;
 
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = RpcClient::http(Url::parse("https://rpc.aboutcircles.com/")?);
    let pathfinder = PathfinderMethods::new(client);
 
    let params = FindPathParams {
        from: "0x1234567890123456789012345678901234567890".parse()?,
        to: "0x0987654321098765432109876543210987654321".parse()?,
        target_flow: U256::from(1_000_000_000_000_000_000u64),
        use_wrapped_balances: Some(true),
        from_tokens: None,
        to_tokens: None,
        exclude_from_tokens: None,
        exclude_to_tokens: None,
        simulated_balances: None,
        max_transfers: Some(6),
    };
 
    let result = pathfinder.find_path(params).await?;
    println!("max flow: {}", result.max_flow);
    Ok(())
}

Use find_max_flow to get the ceiling when you don’t know the target amount.

Parameters (FindPathParams)

  • from, to (Address): endpoints.
  • target_flow (U256): required for find_path.
  • use_wrapped_balances (bool): include wrapped tokens in routing (set true if you hold wrappers).
  • from_tokens / to_tokens: pin allowed token owners at ends.
  • exclude_from_tokens / exclude_to_tokens: ban specific token owners.
  • simulated_balances: preview flows with hypothetical balances.
  • max_transfers: hop cap; lower = faster but may reduce flow.

From path to execution

  • prepare_flow_for_contract returns contract-ready (vertices, edges, streams, coordinates).
  • Hold params until runner exists; then call Hub transfer (operateFlowMatrix equivalent).

Tips

  • If max_flow is 0, check mutual trust or unwrap static/demurraged balances.
  • Always enable use_wrapped_balances when wrappers are involved.
  • Hop limits trade off performance vs. achievable flow.