Docs
SDK

How to Open Positions

This guide shows you how to open taker positions (long or short) using the PerpCity SDK.

Basic Long Position

Open a long position:

import { openTakerPosition } from '@strobelabs/perpcity-sdk'

await openTakerPosition(
  context,
  '0x...', // perpId (Hex address)
  {
    isLong: true,           // Long position
    margin: 1000,           // 1,000 USDC margin
    leverage: 5,            // 5x leverage
    unspecifiedAmountLimit: 0      // Slippage limit
  }
)

This opens a position worth 5,000 USDC (1,000 margin × 5x leverage).

Basic Short Position

Open a short position:

import { openTakerPosition } from '@strobelabs/perpcity-sdk'

await openTakerPosition(
  context,
  '0x...', // perpId (Hex address)
  {
    isLong: false,          // Short position
    margin: 2000,           // 2,000 USDC margin
    leverage: 3,            // 3x leverage
    unspecifiedAmountLimit: 0
  }
)

Understanding Parameters

perpId

The ID of the perp market you want to trade. You get this from:

  • Perp creation (if you created it)
  • Your tracking system (see Core Concepts)
  • The protocol's UI or API

isLong

Boolean flag:

  • true = Long (profit when price increases)
  • false = Short (profit when price decreases)

margin

The amount of USDC to use as collateral, in human units:

// Pass the dollar amount directly
const margin = 100  // $100 USDC
const margin = 500  // $500 USDC
const margin = 1000 // $1,000 USDC

The SDK internally scales to 6-decimal format for the smart contract.

leverage

The leverage multiplier as a simple number:

const leverage = 2   // 2x
const leverage = 5   // 5x
const leverage = 7.5 // 7.5x

Position Size Calculation

Your position's notional value is:

Position Size = Margin × Leverage

Complete Example

import { PerpCityContext, openTakerPosition } from '@strobelabs/perpcity-sdk'
import { createWalletClient, http } from 'viem'
import { base } from 'viem/chains'
import { privateKeyToAccount } from 'viem/accounts'

async function openPosition() {
  // Setup wallet
  const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)
  const walletClient = createWalletClient({
    account,
    chain: base,
    transport: http(process.env.RPC_URL)
  })

  // Initialize context
  const context = new PerpCityContext({
    walletClient,
    rpcUrl: process.env.RPC_URL!,
    deployments: {
      perpManager: process.env.PERP_MANAGER_ADDRESS as `0x${string}`,
      usdc: process.env.USDC_ADDRESS as `0x${string}`
    }
  })

  // Open long position
  console.log('Opening 5x long position with 1000 USDC margin...')

  await openTakerPosition(
    context,
    '0x...', // perpId
    {
      isLong: true,
      margin: 1000,     // 1,000 USDC
      leverage: 5,      // 5x
      unspecifiedAmountLimit: 0
    }
  )

  console.log('Position opened successfully!')
}

openPosition()

Position Tracking

The openTakerPosition function returns an OpenPosition object that includes the position ID:

const position = await openTakerPosition(context, perpId, {
  isLong: true,
  margin: 1000,
  leverage: 5,
  unspecifiedAmountLimit: 0
})

console.log('Position ID:', position.positionId)
console.log('Transaction Hash:', position.txHash)

// You can also get live details directly from the returned object
const liveDetails = await position.liveDetails()
console.log('PnL:', liveDetails.pnl)

Leverage Limits

Each perp market may have maximum leverage limits. Check the perp configuration:

const config = await context.getPerpConfig('0x...')
console.log('Margin ratios module:', config.marginRatios)
// Use the config to determine leverage limits for this perp

Margin Requirements

Before opening a position, ensure you have sufficient margin:

import { getUserUsdcBalance } from '@strobelabs/perpcity-sdk'

// Fetch user data
const userData = await context.getUserData(
  walletClient.account.address,
  [] // No existing positions needed for balance check
)

// Extract balance
const balance = getUserUsdcBalance(userData)
const requiredMargin = 1000 // Your desired margin (1000 USDC)

if (balance < requiredMargin) {
  throw new Error('Insufficient USDC balance')
}

// Check perp config for additional requirements
const config = await context.getPerpConfig('0x...')

Common Errors

Insufficient Balance

Error: Insufficient USDC balance

Solution: Deposit more USDC to your wallet or reduce margin/leverage.

Leverage Too High

Error: Leverage exceeds maximum

Solution: Reduce leverage to within the perp's maximum limit.

Margin Too Low

Error: Margin below initial margin requirement

Solution: Increase margin or reduce leverage.

Market Closed or Paused

Error: Market not active

Solution: Check if the perp market is active and not paused.

Next Steps