Skip to main content
This guide walks you through setting up a connection to the Nile Markets protocol on Sepolia, minting test USDC, and reading onchain state. By the end, you will be able to query pool state, read positions, and check oracle prices programmatically.

Prerequisites

Before starting, make sure you have:
  • A wallet with a Sepolia address (MetaMask, Rabby, or any EVM wallet)
  • Node.js 18+ and a package manager (pnpm, npm, or yarn)
  • A Sepolia RPC URL (from Alchemy, Infura, or any public Sepolia endpoint)

Steps

1

Get Sepolia ETH

You need Sepolia ETH to pay gas fees for transactions. Use any Sepolia faucet to get testnet ETH:
Most faucets require a small amount of mainnet ETH or account verification. If you are having trouble, try multiple faucets — availability varies.
Verify your balance:
cast balance YOUR_ADDRESS --rpc-url $SEPOLIA_RPC
2

Get Test USDC

The protocol uses MockUSDC on Sepolia, which has a public mint function anyone can call. Mint 1,000 USDC (1,000,000,000 raw units with 6 decimals) to your address:
cast send 0x319FeC6Cc374922A183A354a41E89b7A313EE547 \
  "mint(address,uint256)" \
  YOUR_ADDRESS 1000000000 \
  --rpc-url $SEPOLIA_RPC \
  --private-key $PRIVATE_KEY
Verify your MockUSDC balance:
cast call 0x319FeC6Cc374922A183A354a41E89b7A313EE547 \
  "balanceOf(address)(uint256)" YOUR_ADDRESS \
  --rpc-url $SEPOLIA_RPC
3

Install the SDK

The @nile-markets/sdk package provides type-safe ABIs, enum constants, and pair IDs for all protocol contracts.
pnpm add @nile-markets/sdk viem
The SDK has zero runtime dependencies. viem is listed as a peer dependency for type compatibility but is not imported by the SDK itself. You need viem (or ethers) separately to interact with the chain.
4

Read Pool State

Query the PoolVault to see total assets (USDC deposited by LPs) and total share supply:
import { createPublicClient, http } from "viem";
import { sepolia } from "viem/chains";
import { poolVaultAbi } from "@nile-markets/sdk";

const client = createPublicClient({
  chain: sepolia,
  transport: http("YOUR_RPC_URL"),
});

const POOL_VAULT = "0x61208f0337eE40278b0cbc55daEE7A37Fa180618";

const totalAssets = await client.readContract({
  address: POOL_VAULT,
  abi: poolVaultAbi,
  functionName: "totalAssets",
});

const totalSupply = await client.readContract({
  address: POOL_VAULT,
  abi: poolVaultAbi,
  functionName: "totalSupply",
});

console.log(`Pool: ${Number(totalAssets) / 1e6} USDC`);
console.log(`Shares: ${Number(totalSupply) / 1e6} outstanding`);
console.log(`Share price: ${Number(totalAssets) / Number(totalSupply)}`);
totalAssets() returns the pool’s USDC balance in raw 6-decimal units. totalSupply() returns the total share tokens outstanding (also 6 decimals). Share price is the ratio of the two.
5

Query Positions via Subgraph

The protocol’s subgraph indexes all onchain events into a queryable GraphQL API. Use it to fetch historical positions, account data, and pool statistics.
{
  positions(
    first: 5
    orderBy: openTimestamp
    orderDirection: desc
  ) {
    id
    account {
      id
    }
    side
    notional
    entryStrike
    status
    closeReason
    openTimestamp
    closeTimestamp
  }
}
const SUBGRAPH_URL = "https://api.studio.thegraph.com/query/YOUR_SUBGRAPH_ID";

const query = `{
  positions(first: 5, orderBy: openTimestamp, orderDirection: desc) {
    id
    account { id }
    side
    notional
    entryStrike
    status
    closeReason
  }
}`;

const response = await fetch(SUBGRAPH_URL, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ query }),
});

const { data } = await response.json();
console.log("Recent positions:", data.positions);
6

Check Oracle State

Read the current EUR/USD spot price and forward prices from the OracleModule:
import { oracleModuleAbi, PAIR_IDS } from "@nile-markets/sdk";

const ORACLE_MODULE = "0x1f78995b606CCF768E0a532Be8A1AB6eDf3Cd4D5";

// Read the latest spot price
const spot = await client.readContract({
  address: ORACLE_MODULE,
  abi: oracleModuleAbi,
  functionName: "getSpot",
  args: [PAIR_IDS.EUR_USD],
});

console.log(`EUR/USD spot: ${Number(spot.price) / 1e18}`);
console.log(`Valid: ${spot.isValid}`);
console.log(`Timestamp: ${new Date(Number(spot.timestamp) * 1000).toISOString()}`);
All prices are stored as 18-decimal fixed-point integers. Divide by 1e18 to get the human-readable exchange rate. For example, 1,080,000,000,000,000,000 represents EUR/USD = 1.08000.
7

Next Steps

You now have the tools to read protocol state on Sepolia. Here are some paths to explore next:

Open a Position

Walk through opening your first LONG or SHORT position with the SDK.

LP Deposit Tutorial

Deposit USDC into the vault and earn fees as a liquidity provider.

Monitor Positions

Build a real-time position monitor using the subgraph and RPC reads.

Core Concepts

Understand synthetic forwards, margin, and the protocol’s risk framework.

Contract Addresses Reference

For quick reference, here are the key contract addresses on Sepolia. See the full list on the Contract Addresses page.
ContractAddress
PositionManager0x8d81E9f1D0F0d1BdAAc0a91AFc2976522429A0cd
PoolVault0x61208f0337eE40278b0cbc55daEE7A37Fa180618
MarginAccounts0x12c310A5A5B5771459ff96979931CddE75A6D935
OracleModule0x1f78995b606CCF768E0a532Be8A1AB6eDf3Cd4D5
MockUSDC0x319FeC6Cc374922A183A354a41E89b7A313EE547

Troubleshooting

You need MockUSDC in your wallet. Go back to Step 2 and mint test USDC. Make sure you also have Sepolia ETH for gas fees.
The oracle may be stale if the publisher has not submitted a recent price update. On testnet, the publisher runs periodically and there may be gaps. Wait a few minutes and try again.
Verify you are using the correct subgraph URL. The subgraph may also take a few minutes to index new blocks after events are emitted. If the deployment is fresh, there may be no positions yet.
Public Sepolia RPC endpoints have rate limits. If you are hitting limits, switch to a dedicated provider like Alchemy or Infura (both have free tiers that support Sepolia).