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

# Trading with Exchange

> Use the Upside Python SDK Exchange client for signed writes — orders, cancels, margin and leverage, TP/SL, collateral transfers, and agent delegation.

The `Exchange` client performs every state-changing operation. Each call is
signed with your wallet key using EIP-712; the SDK builds the envelope, selects
the signing path, and manages the nonce for you.

```python theme={null}
from upside import Exchange
from upside.utils import constants

exchange = Exchange("0x<private-key>", base_url=constants.QA_API_URL)
```

`wallet` may be a private-key hex string or an `eth_account` LocalAccount.
Optional arguments: `account_id` (set it when signing with an agent key — see
[Agent delegation](#agent-api-wallet-delegation)) and a shared `nonce_manager`.

<Note>
  Prices and sizes are **raw integer strings**, scaled by the contract's
  `priceScale` / `qtyScale` from [`configs`](/info/configs). Order placement is
  **asynchronous** and HTTP 200 does not always mean success — see
  [key behaviors](/sdk/python/overview#key-behaviors).
</Note>

## Register an account

```python theme={null}
# QA requires an alpha test invitation code from the Upside team. On success a
# 10,000 USDC test airdrop lands within ~10s, and account_id is captured.
exchange.register_account(invite_code="<your-code>")
print(exchange.account_id)
```

## Orders

```python theme={null}
from upside import Cloid

exchange.order(asset=1, is_buy=True, size="10", price="50", cloid=Cloid.from_int(1001))
exchange.order(asset=1, is_buy=True, size="10", price="50", tif="Alo")   # Gtc | Ioc | Alo | Fok
exchange.market_order(asset=1, is_buy=False, size="5")
exchange.bulk_orders([...])                      # up to 10 orders, one signature
```

`order` builds a single-order `bulk_orders` call. For builder-fee sharing, pass
`builder_address` / `builder_fee`; in a batch only `orders[0]`'s builder fields
apply to the whole request. A **client order id** (`cloid`) is a positive int64;
wrap it with `Cloid.from_int(...)` so you can locate the order later with
`orders_by_cloids` or `cancel_by_cloid`.

### Cancel & modify

```python theme={null}
exchange.cancel(asset=1, oid=15)
exchange.cancel_by_cloid(asset=1, cloid=1001)
exchange.cancel_all(asset=1)                     # per-contract
exchange.bulk_cancel([...])                      # up to 10 cancels
exchange.modify(asset=1, oid=15, price="151", size="8")   # locate by oid (or cloid)
```

`modify` changes only price / size / TIF / cloid — provide just the fields you
want to change; side, asset, and reduce-only cannot change.

## Margin & leverage

```python theme={null}
exchange.update_leverage(asset=1, leverage=20)
exchange.update_margin_mode(asset=1, is_cross=False, is_hedge=True)   # isolated requires HEDGE
exchange.update_isolated_margin(asset=1, ntli=5000)   # ntli > 0 adds, < 0 removes
```

`update_margin_mode` requires no open position or orders on the contract. Omit
`is_hedge` to keep the current position mode; switching to isolated
(`is_cross=False`) requires HEDGE mode.

## Conditional orders (TP/SL)

```python theme={null}
exchange.tp_sl(asset=1, tp_price="90000", sl_price="80000")   # whole-position, market on trigger
exchange.cancel_tp_sl(asset=1)
exchange.cancel_conditional(oid=123)
```

At least one of `tp_price` / `sl_price` must be greater than `0`. A limit price
of `"0"` fires a market IOC on trigger; a value above `0` places a GTC limit. A
size of `"0"` closes the whole position. Trigger type selects the reference
price (`0` = mark, `1` = index, `2` = last).

## Collateral transfers

```python theme={null}
exchange.lock_collateral(market_deployer_id=1, coin_id=1, amount="1000")
exchange.unlock_collateral(market_deployer_id=1, coin_id=1, amount="1000")
exchange.transfer_between_deployers(1, 2, coin_id=1, amount="1000")
```

## Agent (API-wallet) delegation

Keep the master key offline and authorize a hot agent key to sign trades. The
server routes an agent-signed action to the master account from the recovered
signer, so the agent `Exchange` keeps `account_id` pointed at the master.

```python theme={null}
# Master authorizes an agent. With no address, a fresh key is generated and
# returned so you can build the agent client.
response, agent_key = master.approve_agent(agent_name="bot1")

agent = Exchange(agent_key, base_url=constants.QA_API_URL, account_id=master.account_id)
agent.order(asset=1, is_buy=True, size="10", price="50")

master.revoke_agent(agent.address)
```

`approve_agent` and `revoke_agent` are master-only. `valid_until` is a Unix-ms
expiry (`0` = permanent). See [API Wallets](/agents/api-wallets) for the
delegation model.
