PropAMM Rust SDK
SDK for interacting with the PropAMMRouter contract over JSON-RPC, built
entirely on rex /
ethrex: EthClient transport,
signing, eth_call overrides, and ABI encoding/decoding via ethrex's
calldata codec (signature strings; selectors are regression-tested against
forge inspect PropAMMRouter methodIdentifiers). Mirrors the TypeScript SDK
(../typescript): same surface, snake_case names, no on-chain V1 suffix.
rex's StateOverrideSet and BlockOverrideSet are re-exported, and all
eth_calls go through rex's call_with_overrides. rex flattens revert data
into its error string; the client recovers the payload from the
" (data: 0x…)" suffix so reverts still decode into named contract errors —
if rex ever exposes the data structurally, that parsing can go away.
Setup
Getting started
Quote and swap 1 ETH for USDC through the best venue:
use ;
use ;
use SwapParams;
use ;
let client = connect_with_signer?;
let me = client.signer_address.unwrap;
let router = new; // deployed router proxy
let amount_in = parse_ether?;
let quote = router.quote.await?;
let result = router
.swap_and_wait
.await?;
println!;
A runnable version lives in examples/getting_started.rs:
It defaults to a local anvil mainnet fork with anvil's funded account and the
mainnet router deployment; override with RPC_URL / PRIVATE_KEY /
ROUTER_ADDRESS / SLIPPAGE_BPS.
State overrides
The pAMM venues price off-chain liquidity that on-chain state does not
reflect, so a plain eth_call quote sees stale prices. Titan publishes fresh
state overrides, and quotes apply them automatically: the simulation carries
the overrides plus their block number/timestamp so venues price their pushed
state instead of the chain's.
Two sources implement the OverridesSource trait; both need no authentication:
OverridesWsSource— streamswss://rpc.titanbuilder.xyz/ws/pamm_quote_stream, caching per-pAMM entries across frames and reconnecting with backoff. This is the default: a router built withPropAmmRouter::newcreates one (connecting lazily on the first quote). The connection auto-closes after an idle window without quotes (idle_timeout, default 30s) and reconnects transparently, so no teardown is needed.OverridesRpcSource— callstitan_getPammStateOverridesover HTTP on each quote. No connection to manage.
use Arc;
use ;
use ;
// default: streaming WS source created automatically
let router = new;
// or attach a source explicitly
let router = with_overrides;
// per-call control
let opts = QuoteOptions ;
let stale = router.quote_with.await?;
When a snapshot has no Bebop entry, a default slot override zeroes Bebop's
price so a stale on-chain quote can't win venue selection (disable with
skip_bebop_default). The Uniswap V3 fallback quoter only reads live pool
state, so pAMM overrides never affect it (pin it via
venues: Some(vec![router.fallback_swap_router().await?]) if needed).
Custom state diffs go through ContractClient::call with CallOverrides
directly.
Admin functions (addVenue, pause, setPairFee, ...) have no typed
methods, but their signatures are in the ABI module — encode and send them
through the generic client:
use ;
use encode_calldata;
let calldata = encode_calldata?;
let hash = client.send.await?;
Layout
src/client.rs— rex/ethrex-based contract client (callwith state/block overrides,send,wait_for_transaction).src/router/mod.rs—PropAmmRouterbindings (quote/quote_with,swap/swap_with,swap_and_wait(_with),wait_for_swap,approve/allowance, views) plusMAX_FEE_BPS.src/router/abi.rs— hand-rolledPropAMMRouterABI: signature constants (selector-tested), return/event decoding, and the custom-error table.src/overrides/mod.rs— pAMM state-override sources (OverridesWsSource,OverridesRpcSource), payload parsing, andto_state_override.src/common/tokens.rs—ETH_SENTINELand mainnet token addresses.src/common/pamms.rs— pAMM venue addresses.src/common/helpers.rs—apply_slippage,deadline_in,parse_address, and unit conversion (parse_ether,parse_units,format_ether,format_units).
The on-chain quote functions are nonpayable (not view), so the bindings call
them through eth_call simulation (ContractClient::call) rather than a
plain read.