Docs

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 structure

get_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 context
  • params: CreatePerpParams:
    • starting_price: float -- Initial mark price
    • beacon: str -- Oracle beacon address
    • fees: str | None -- Optional fees module override
    • margin_ratios: str | None -- Optional margin ratios module
    • lockup_period: str | None -- Optional lockup period module
    • sqrt_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 -- True for long, False for short
  • margin: float -- Margin in USDC
  • leverage: float -- Leverage multiplier
  • unspecified_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

FunctionReturnsDescription
get_position_pnl(data)floatUnrealized PnL in USD
get_position_funding_payment(data)floatCumulative funding payment
get_position_effective_margin(data)floatCurrent effective margin
get_position_is_liquidatable(data)boolWhether position can be liquidated
get_position_live_details(data)LiveDetailsFull live details object

Calculation Functions

FunctionDescription
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

FunctionReturnsDescription
get_perp_mark(perp_data)floatCurrent mark price
get_perp_beacon(perp_data)strOracle beacon address
get_perp_bounds(perp_data)BoundsMargin and leverage bounds
get_perp_fees(perp_data)FeesFee structure
get_perp_tick_spacing(perp_data)intAMM tick spacing

User Functions

FunctionReturnsDescription
get_user_usdc_balance(user_data)floatUSDC balance
get_user_open_positions(user_data)list[OpenPositionData]Open positions
get_user_wallet_address(user_data)strWallet address

Utility Functions

FunctionDescription
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: MarginRatios

Parameter 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 = None

Error 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 ClassDescription
PerpCityErrorBase exception for all SDK errors
ContractErrorSmart contract revert (includes error_name and debug info)
TransactionRejectedErrorUser rejected transaction signing
InsufficientFundsErrorWallet has insufficient funds
RPCErrorRPC connectivity or response error
ValidationErrorInput validation failure