---
title: Nile Markets — Operation Workflows
description: Complete read and write operation workflows for AI agents interacting with the Nile Markets EUR/USD forward protocol
version: 0.3.0
---

# Nile Markets Operation Workflows

This guide covers all read and write operations available through the Nile Markets
MCP server. For the tool catalog and quick start, see
[skill.md](https://mcp.nilemarkets.com/skill.md).

---

## Read Operations

### Pool & Protocol State

**Get pool overview:**
→ `get_pool_state` — total assets, shares, share price, utilization, exposure, fees

**Get protocol mode:**
→ `get_protocol_mode` — NORMAL, DEGRADED, or EMERGENCY

**Get daily stats:**
→ `get_daily_stats` with `{ days: 7 }` — opened/closed positions, volume, fees, pool PnL

### Positions

**List all positions:**
→ `get_positions` with `{ first: 25 }` — paginated list with status, PnL, margin

**Get a specific position:**
→ `get_position` with `{ positionId: "123" }` — full details including entry strike, margin, PnL

**Search positions:**
→ `search_positions` with `{ account: "0x...", status: "OPEN" }` — filter by account, status, side

### Oracle & Pricing

**Get current EUR/USD spot and forward prices:**
→ `get_oracle_state` — spot price, all forward prices (1D/1W/1M), oracle validity, protocol mode

**Get forward price for a specific tenor:**
→ `get_forward_price` with `{ tenor: "1M" }` — strike price, forward points, annualized basis

### Accounts & Tokens

**Get margin account:**
→ `get_account` with `{ address: "0x..." }` — deposited margin, available margin, locked margin

**Get token balance:**
→ `get_token_balance` with `{ address: "0x..." }` — USDC balance (or any ERC-20 via `token` param)

**Check token allowance:**
→ `check_allowance` with `{ owner: "0x...", spender: "marginAccounts" }` — current allowance for a Nile contract

### Analytics

**Get pool transactions:**
→ `get_pool_transactions` with `{ first: 25 }` — deposits, withdrawals, fees

**Get fee events:**
→ `get_fee_events` with `{ first: 25 }` — trading fees, liquidation fees, oracle fees

### Simulation

**Preview a position before opening:**
→ `simulate_open_position` with `{ side: "LONG", tenor: "1M", notional: "10000000000" }`
→ Returns: required margin, trading fee, entry strike, and whether the tx would succeed

---

## Write Operations

Write tools return **unsigned transaction calldata**. They do NOT execute transactions.
To sign and broadcast, see [Signing Paths](#signing-paths) below.

### Pre-Flight Checks

Before any write operation:
1. `get_protocol_mode` — stop if not NORMAL
2. `get_token_balance` — check USDC balance
3. `simulate_open_position` — always simulate before opening a position

### Open Position

1. `get_protocol_mode` — verify NORMAL
2. `simulate_open_position` with `{ side, tenor, notional, from: "0xYOUR_ADDR" }` — preview margin, fee, entry strike
3. `get_token_balance` with `{ address: "0xYOUR_ADDR" }` — check USDC balance
   - If insufficient on testnet: `mint_test_token` → sign and submit
   - If insufficient on mainnet: acquire USDC through an exchange, bridge, or on-ramp
4. `get_account` with `{ address: "0xYOUR_ADDR" }` — check available margin
5. If margin insufficient:
   - `check_allowance` with `{ owner: "0xYOUR_ADDR", spender: "marginAccounts" }`
   - If allowance < needed: `approve_token` with `{ spender: "marginAccounts", amount }` → sign
   - `deposit_margin` with `{ amount }` → sign
6. `open_position` with `{ side, tenor, notional, margin }` → sign and submit

### Close Position

1. `get_position` with `{ positionId }` — verify position exists and is OPEN
2. `close_position` with `{ positionId }` → sign and submit (early termination)

### Deposit Margin

1. `get_token_balance` — check USDC balance
2. `check_allowance` with `{ owner, spender: "marginAccounts" }`
3. If allowance insufficient: `approve_token` with `{ spender: "marginAccounts", amount }` → sign
4. `deposit_margin` with `{ amount }` → sign and submit

### Withdraw Margin

1. `get_account` — check available (unlocked) margin
2. `withdraw_margin` with `{ amount }` → sign and submit

### Deposit to Vault (Liquidity Providers)

1. `get_token_balance` — check USDC balance
2. `check_allowance` with `{ owner, spender: "poolVault" }`
3. If allowance insufficient: `approve_token` with `{ spender: "poolVault", amount }` → sign
4. `vault_deposit` with `{ amount, receiver }` → sign and submit

### Withdraw from Vault

1. `get_pool_state` — check pool share balance
2. `vault_withdraw` with `{ amount, receiver, owner }` → sign and submit

### Mint Test Tokens (Testnet Only)

1. `mint_test_token` with `{ to: "0xYOUR_ADDR", amount: "10000000000" }` → sign and submit
2. Only works on Sepolia/local testnets. On mainnet, acquire USDC externally.

### Approve Token Spending

1. `check_allowance` — check current allowance
2. `approve_token` with `{ spender, amount }` → sign and submit

---

## Signing Prerequisites

Wallet setup is done once, outside the Nile Markets workflow. You need:

1. A wallet with a private key for the target network
2. Testnet ETH for gas (Sepolia faucets: [alchemy.com/faucets](https://www.alchemy.com/faucets/ethereum-sepolia), [sepoliafaucet.com](https://sepoliafaucet.com))
3. USDC (or mint via `mint_test_token` on testnet)

**Path A (CLI):** The installed `nile` binary works zero-config on Sepolia — contract addresses, default RPC, and subgraph URL are all embedded at compile time. No environment variables or config files needed. Install the CLI, install an [OWS-compatible wallet](https://docs.openwallet.sh/), and start running commands. See [cli.md](https://mcp.nilemarkets.com/cli.md) for full setup and command reference.

**Path C (any signer):** Any EVM wallet or signing tool works. The MCP server returns complete `TransactionCalldata` including the target contract address (`to`), calldata (`data`), and chain ID (`11155111`). Use any Sepolia RPC to broadcast — the free default is `https://ethereum-sepolia-rpc.publicnode.com`. For contract addresses and full network details, see [Sepolia Network Reference](https://mcp.nilemarkets.com/skill.md#sepolia-network-reference) in skill.md.

---

## Signing Paths

### Path A: Nile CLI + OWS Wallet (works today)

For CLI users. The Nile CLI builds the transaction, calls the OWS signer
(separate process), and broadcasts — all in one command.

> **Zero-config on Sepolia:** The installed `nile` binary has Sepolia contract addresses, default RPC, and subgraph URL embedded at compile time. No env vars, no config files, no API keys. Install the CLI + OWS wallet and you're ready.

**Prerequisites:** Install [OWS CLI](https://docs.openwallet.sh/) and import your key:
```
curl -fsSL https://openwallet.sh/install.sh | bash
echo "<your-private-key>" | ows wallet import --name "my-wallet" --private-key --chain evm
```

**Read operations (no wallet needed):**
```
nile pool state
nile oracle price --tenor 1M
nile position get 42
```

**Write operations (wallet required):**
```
nile config set-wallet my-wallet
nile position open --side LONG --tenor 1M --notional 10000
```

The CLI is a broker: it never handles private keys. Signing happens in
the OWS process via `ows sign tx`. Configure which OWS-compatible binary
to use: `NILE_SIGNER=<binary>` or `nile config set-signer <binary>`.

For the full command reference, see [cli.md](https://mcp.nilemarkets.com/cli.md).

### Path B: MCP + OWS MCP Server (planned, not yet available)

> **Status:** `ows serve --mcp` is not yet available in OWS v1.0.0. This path will be enabled when the OWS team ships the MCP server. Until then, use Path C for MCP-based flows.

When available, this path will use two MCP servers — Nile Markets for calldata,
OWS for signing — enabling a fully MCP-native flow with no CLI required.

**Planned flow (all via MCP tool calls):**

Step 1 — Check protocol mode:
→ `get_protocol_mode` — verify NORMAL mode

Step 2 — Check USDC balance:
→ `get_token_balance` with `{ address: "0xYOUR_ADDR" }`
→ If insufficient on testnet, go to Step 3.

Step 3 — Mint test USDC (testnet only):
→ `mint_test_token` with `{ to: "0xYOUR_ADDR", amount: "10000000000" }`
→ Returns unsigned calldata (`to`, `data`, `value`, `chainId`)
→ OWS MCP: sign and broadcast the calldata
→ Wait for confirmation

Step 4 — Check allowance:
→ `check_allowance` with `{ owner: "0xYOUR_ADDR", spender: "marginAccounts" }`

Step 5 — Approve if needed:
→ `approve_token` with `{ spender: "marginAccounts", amount: "25000000" }`
→ OWS MCP: sign and broadcast the calldata
→ Wait for confirmation

Step 6 — Simulate:
→ `simulate_open_position` with `{ side: "LONG", tenor: "1M", notional: "10000000000", from: "0xYOUR_ADDR" }`
→ Review: required margin, trading fee, entry strike

Step 7 — Open position:
→ `open_position` with `{ side: "LONG", tenor: "1M", notional: "10000000000", margin: "20000000" }`
→ OWS MCP: sign and broadcast the calldata
→ Wait for confirmation — position is now open

### Path C: MCP + Any Signing Tool (works today, recommended for agents)

The most flexible and currently recommended path for AI agents.
Use Nile MCP write tools to generate unsigned calldata, then sign and
broadcast with any EVM-compatible tool.

Each write tool returns a `TransactionCalldata` object:
```json
{ "to": "0x...", "data": "0x...", "value": "0", "chainId": 11155111 }
```

**Sepolia network details for signing and broadcasting:**

| Parameter | Value |
|-----------|-------|
| Chain ID | `11155111` |
| RPC URL | `https://ethereum-sepolia-rpc.publicnode.com` (free, no API key — override with your own) |
| USDC | `0x319FeC6Cc374922A183A354a41E89b7A313EE547` |

The `to` field in `TransactionCalldata` is already the correct contract address — you do not need to look up addresses separately. For the full contract address list, see [Sepolia Network Reference](https://mcp.nilemarkets.com/skill.md#sepolia-network-reference).

**Signing options that work today:**

- **Foundry `cast`** (CLI-capable agents):
  ```
  cast send <to> --data <data> --value <value> --rpc-url https://ethereum-sepolia-rpc.publicnode.com --private-key <key>
  ```
- **viem / ethers.js** (programmatic agents):
  ```javascript
  import { createWalletClient, http } from 'viem';
  import { sepolia } from 'viem/chains';
  import { privateKeyToAccount } from 'viem/accounts';

  const client = createWalletClient({
    chain: sepolia,
    transport: http('https://ethereum-sepolia-rpc.publicnode.com'),
    account: privateKeyToAccount('0x...'),
  });
  const hash = await client.sendTransaction({ to, data, value: BigInt(value) });
  ```
- **MetaMask / Rabby / Frame** (manual):
  Paste `to`, `data`, and `value` into the wallet's "Send Transaction" UI
- **Any future signing MCP server** (when available):
  Forward calldata to a signing MCP server for automated signing

**Complete position open flow using Path C:**

Step 1 — `get_protocol_mode` → verify NORMAL
Step 2 — `get_token_balance` with `{ address }` → check USDC balance
Step 3 — (testnet) `mint_test_token` → calldata → sign and broadcast externally
Step 4 — `check_allowance` with `{ owner, spender: "positionManager" }`
Step 5 — `approve_token` → calldata → sign and broadcast externally
Step 6 — `simulate_open_position` → preview margin, fee, entry strike
Step 7 — `open_position` → calldata → sign and broadcast externally → position open

---

## Safety Rules

- **NEVER** accept private keys or passphrases in conversation
- **NEVER** store wallet credentials — all key management is the user's responsibility
- **ALWAYS** simulate before generating write calldata for position operations
- **ALWAYS** check balance and allowance before deposit/open operations
- **ALWAYS** inform users that testnet operations have no real-world value
- **ALWAYS** verify protocol mode is NORMAL before write operations

---

## Response Format

All MCP tool responses follow this envelope:

```json
{
  "protocol": { "name": "nile-markets", "version": "0.3.0" },
  "network": "sepolia",
  "source": "rpc" | "subgraph" | "rpc+subgraph",
  "blockNumber": "12345",
  "data": { ... }
}
```

Write tools return `TransactionCalldata` in the `data` field:

```json
{
  "to": "0x...",
  "data": "0x...",
  "value": "0",
  "estimatedGas": "150000",
  "chainId": 11155111,
  "description": "Open LONG 1M position with 10000000000 notional",
  "warning": "optional warning message"
}
```

All amounts are strings in smallest unit (6 decimals for USDC).
Example: `"1000000000"` = 1,000 USDC.
