API Reference
Complete reference documentation for the PerpCity Python SDK.
Complete reference documentation for all PerpCity Python SDK functions and types.
Core Class
PerpCityContext
The main context class for all SDK operations.
from perpcity_sdk import PerpCityContext
context = PerpCityContext(
rpc_url="https://your-rpc-endpoint.example/v2/YOUR_KEY",
private_key="0xYOUR_PRIVATE_KEY",
perp_manager_address="0xPERP_MANAGER",
usdc_address="0xUSDC",
chain_id=84532, # optional, defaults to Base Sepolia
)Methods
get_perp_data(perp_id: str) -> PerpData
Fetches comprehensive perp market data including mark price, bounds, and fees.
perp_data = context.get_perp_data(perp_id)
print(perp_data.mark) # Current mark price
print(perp_data.beacon) # Oracle address
print(perp_data.bounds) # Market bounds
print(perp_data.fees) # Fee structureget_perp_config(perp_id: str) -> PerpConfig
Retrieves and caches perp configuration including module addresses.
get_user_data(user_address: str, positions: list[dict]) -> UserData
Fetches user data with live details for all positions.
get_open_position_data(perp_id: str, position_id: int, is_long: bool, is_maker: bool) -> OpenPositionData
Fetches live details for a single position.
get_position_raw_data(position_id: int) -> PositionRawData
Retrieves raw on-chain position data for calculations.
validate_chain_id() -> None
Validates the RPC endpoint matches the expected chain ID. Raises PerpCityError on mismatch.
deployments() -> PerpCityDeployments
Returns deployment addresses for the protocol.
execute_transaction(contract_fn, gas: int | None = None) -> dict
Builds, signs, and broadcasts a transaction. Returns the transaction receipt.
Trading Functions
create_perp
Creates a new perpetual market.
from perpcity_sdk import create_perp, CreatePerpParams
perp_id = create_perp(context, CreatePerpParams(
starting_price=3000.0,
beacon="0x...",
))Parameters:
context: PerpCityContext-- SDK contextparams: CreatePerpParams:starting_price: float-- Initial mark pricebeacon: str-- Oracle beacon addressfees: str | None-- Optional fees module overridemargin_ratios: str | None-- Optional margin ratios modulelockup_period: str | None-- Optional lockup period modulesqrt_price_impact_limit: str | None-- Optional price impact module
Returns: str -- The new perp ID (hex string)
open_taker_position
Opens a taker (long/short) position. Automatically approves USDC.
from perpcity_sdk import open_taker_position, OpenTakerPositionParams
position = open_taker_position(context, perp_id, OpenTakerPositionParams(
is_long=True,
margin=1000,
leverage=5,
unspecified_amount_limit=0,
))Parameters (OpenTakerPositionParams):
is_long: bool--Truefor long,Falsefor shortmargin: float-- Margin in USDCleverage: float-- Leverage multiplierunspecified_amount_limit: int-- Slippage tolerance
Returns: OpenPosition -- Position object with position_id, tx_hash, and methods
open_maker_position
Opens a maker (liquidity provider) position. Automatically approves USDC and aligns price range to tick spacing.
from perpcity_sdk import open_maker_position, OpenMakerPositionParams
position = open_maker_position(context, perp_id, OpenMakerPositionParams(
margin=10000,
price_lower=2900,
price_upper=3100,
liquidity=1000000,
max_amt0_in=1000000,
max_amt1_in=1000000,
))Returns: OpenPosition -- Position object
Position Management
OpenPosition
Returned by open_taker_position and open_maker_position.
# Close the position
result = position.close_position(ClosePositionParams(
min_amt0_out=0,
min_amt1_out=0,
max_amt1_in=1000000,
))
# Check live details
details = position.live_details()
print(details.pnl)
print(details.effective_margin)
print(details.is_liquidatable)close_position (functional)
from perpcity_sdk import close_position, ClosePositionParams
result = close_position(context, perp_id, position_id, ClosePositionParams(
min_amt0_out=0,
min_amt1_out=0,
max_amt1_in=1000000,
))Position Query Functions
| Function | Returns | Description |
|---|---|---|
get_position_pnl(data) | float | Unrealized PnL in USD |
get_position_funding_payment(data) | float | Cumulative funding payment |
get_position_effective_margin(data) | float | Current effective margin |
get_position_is_liquidatable(data) | bool | Whether position can be liquidated |
get_position_live_details(data) | LiveDetails | Full live details object |
Calculation Functions
| Function | Description |
|---|---|
calculate_entry_price(raw_data) | Entry price from raw position deltas |
calculate_position_size(raw_data) | Position size in base asset units |
calculate_position_value(raw_data, mark_price) | Notional value at mark price |
calculate_leverage(position_value, effective_margin) | Current leverage ratio |
calculate_liquidation_price(raw_data, is_long) | Liquidation price (float | None) |
Perp Data Functions
| Function | Returns | Description |
|---|---|---|
get_perp_mark(perp_data) | float | Current mark price |
get_perp_beacon(perp_data) | str | Oracle beacon address |
get_perp_bounds(perp_data) | Bounds | Margin and leverage bounds |
get_perp_fees(perp_data) | Fees | Fee structure |
get_perp_tick_spacing(perp_data) | int | AMM tick spacing |
User Functions
| Function | Returns | Description |
|---|---|---|
get_user_usdc_balance(user_data) | float | USDC balance |
get_user_open_positions(user_data) | list[OpenPositionData] | Open positions |
get_user_wallet_address(user_data) | str | Wallet address |
Utility Functions
| Function | Description |
|---|---|
price_to_sqrt_price_x96(price) | Price to Uniswap V4 sqrtPriceX96 |
sqrt_price_x96_to_price(sqrt_price_x96) | sqrtPriceX96 to price |
price_to_tick(price, round_down) | Price to Uniswap tick |
tick_to_price(tick) | Tick to price (1.0001^tick) |
scale_6_decimals(amount) | Scale to 6-decimal USDC format |
scale_from_6_decimals(value) | Scale from 6-decimal format |
estimate_liquidity(tick_lower, tick_upper, usd_scaled) | Estimate liquidity for a tick range |
Types
Data Types
@dataclass(frozen=True)
class PerpData:
id: str
tick_spacing: int
mark: float
beacon: str
bounds: Bounds
fees: Fees
@dataclass(frozen=True)
class Bounds:
min_margin: float
min_taker_leverage: float
max_taker_leverage: float
liquidation_taker_ratio: float
@dataclass(frozen=True)
class Fees:
creator_fee: float
insurance_fee: float
lp_fee: float
liquidation_fee: float
@dataclass(frozen=True)
class LiveDetails:
pnl: float
funding_payment: float
effective_margin: float
is_liquidatable: bool
@dataclass(frozen=True)
class OpenPositionData:
perp_id: str
position_id: int
live_details: LiveDetails
is_long: bool | None = None
is_maker: bool | None = None
@dataclass(frozen=True)
class UserData:
wallet_address: str
usdc_balance: float
open_positions: list[OpenPositionData]
@dataclass(frozen=True)
class PositionRawData:
perp_id: str
position_id: int
margin: float
entry_perp_delta: int
entry_usd_delta: int
margin_ratios: MarginRatiosParameter Types
@dataclass
class OpenTakerPositionParams:
is_long: bool
margin: float
leverage: float
unspecified_amount_limit: int
@dataclass
class OpenMakerPositionParams:
margin: float
price_lower: float
price_upper: float
liquidity: int
max_amt0_in: int
max_amt1_in: int
@dataclass
class ClosePositionParams:
min_amt0_out: float
min_amt1_out: float
max_amt1_in: float
@dataclass
class CreatePerpParams:
starting_price: float
beacon: str
fees: str | None = None
margin_ratios: str | None = None
lockup_period: str | None = None
sqrt_price_impact_limit: str | None = NoneError Handling
All errors inherit from PerpCityError:
from perpcity_sdk import PerpCityError
try:
position = open_taker_position(context, perp_id, params)
except PerpCityError as e:
print(f"Error: {e}")| Error Class | Description |
|---|---|
PerpCityError | Base exception for all SDK errors |
ContractError | Smart contract revert (includes error_name and debug info) |
TransactionRejectedError | User rejected transaction signing |
InsufficientFundsError | Wallet has insufficient funds |
RPCError | RPC connectivity or response error |
ValidationError | Input validation failure |