> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kimia.live/llms.txt
> Use this file to discover all available pages before exploring further.

# Trade a Perpetual

> Open and close a leveraged SOL-PERP position on Kimia.

This guide walks through opening a 2× long on SOL-PERP from a clean wallet
state, using the Codama-generated TS client.

## Prerequisites

* Wallet funded on devnet (`solana airdrop 2`)
* USDC (devnet) in the wallet, mint is on the program constants page
* Perp market initialized (it is, on devnet, at `market_index = 0`)

## 1. Create a user account

```ts theme={null}
import { getInitializeUserAccountInstruction, findUserAccountPda } from
  '@/app/generated/perp/instructions';

const [userAccount] = await findUserAccountPda({ authority: wallet.address });

const ix = getInitializeUserAccountInstruction({
  authority: wallet,
  payer: wallet,
  userAccount,
});

await sendTransaction(ix);
```

## 2. Deposit USDC collateral

```ts theme={null}
import { getDepositCollateralInstruction } from '@/app/generated/perp/instructions';

const ix = getDepositCollateralInstruction({
  signer: wallet,
  userAccount,
  market: marketPda,
  userTokenAccount: userUsdcAta,
  collateralVault: market.collateralVault,
  amount: 1_000_000_000n,   // 1,000 USDC (6 decimals)
});
```

## 3. Post the oracle update

```ts theme={null}
import { PythSolanaReceiver } from '@pythnetwork/pyth-solana-receiver';
const hermes = await fetch(
  `https://hermes.pyth.network/v2/updates/price/latest?ids[]=${SOL_USD_FEED_ID}`
).then((r) => r.json());

const postIxs = await receiver.buildPostPriceUpdateInstructions(
  hermes.binary.data[0],
);
```

## 4. Place a market long

```ts theme={null}
import { getPlaceOrderInstruction } from '@/app/generated/perp/instructions';

const ix = getPlaceOrderInstruction({
  signer: wallet,
  userAccount,
  market: marketPda,
  oracle: priceUpdateAccount,   // from step 3
  orderbook: orderbookPda,
  collateralVault: market.collateralVault,
  feeVault: market.feeVault,
  // remainingAccounts: counterparty user accounts for up to 4 fills
  params: {
    price: 0n,                       // ignored for market orders
    baseAmount: 2_000_000_000n,      // 2 SOL (9 decimals) → ≈2× leverage on 1k USDC
    direction: { __kind: 'Long' },
    postOnly: false,
    isMarket: true,
    maxSlippageBps: 100,
  },
});

await sendTransaction([...postIxs, ix]);
```

## 5. Close the position

A closing order is a market order in the opposite direction:

```ts theme={null}
const closeIx = getPlaceOrderInstruction({
  ...commonAccounts,
  params: {
    ...,
    baseAmount: 2_000_000_000n,
    direction: { __kind: 'Short' },  // closes a long
    isMarket: true,
    maxSlippageBps: 100,
  },
});
```

Realized PnL flows into `user_account.collateral` automatically. Withdraw with
`getWithdrawCollateralInstruction` (authority only, delegates cannot withdraw).

## Things to watch

<Warning>
  If the oracle post instruction is not prepended, `place_order` will revert with
  `InvalidOraclePrice` or `StaleOracle`. The price must land on-chain **in the
  same transaction** as the trade.
</Warning>

<Tip>
  The matching loop processes up to 4 fills per tx. For larger fills, issue
  multiple `place_order` transactions, the remaining size will walk the book on
  each call.
</Tip>
