Getting Started
The full SDK v1 client (GmxSdk) exposes these top-level modules:
markets— fetch market definitions, pricing, and daily volumestokens— fetch token metadata and balancespositions— read open positions for an accountorders— read active orders and submit new ones (long, short, swap, cancel)trades— fetch historical trade activityaccounts— read governance delegate dataoracle— read raw oracle markets, tokens, and tickers from the configured oracle URLutils— fee estimation, price impact, and other calculation helpers
Before you start
To use GmxSdk, you need the following:
- An RPC endpoint for your target chain
- A GMX oracle keeper URL — see Oracle Prices
- A Subsquid GraphQL URL — see GraphQL
- A viem
WalletClientfor write operations. For read-only use, you can omit the wallet client, but you still configure the RPC, oracle, and Subsquid URLs.
Initialization
The following example shows the minimum setup to initialize the SDK and fetch positions for an account on Arbitrum mainnet.
import { GmxSdk } from "@gmx-io/sdk";
// 1. Create the SDK instance
const sdk = new GmxSdk({
chainId: 42161, // Arbitrum
rpcUrl: "https://arb1.arbitrum.io/rpc",
oracleUrl: "https://arbitrum-api.gmxinfra.io",
subsquidUrl: "https://gmx.squids.live/gmx-synthetics-arbitrum:prod/api/graphql",
});
// 2. Set the account you want to query
sdk.setAccount("0x9f7198eb1b9Ccc0Eb7A07eD228d8FbC12963ea33");
// 3. Fetch market and token data (required for most queries)
const { marketsInfoData, tokensData } = await sdk.markets.getMarketsInfo();
// 4. Fetch open positions for the account
const { positionsData } = await sdk.positions.getPositions({
marketsData: marketsInfoData,
tokensData,
});
console.log(positionsData);
The SDK doesn't require a wallet client for read-only operations. To submit orders, pass a viem WalletClient:
import { GmxSdk } from "@gmx-io/sdk";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { arbitrum } from "viem/chains";
const account = privateKeyToAccount("0x...your-private-key");
const walletClient = createWalletClient({
account,
chain: arbitrum,
transport: http("https://arb1.arbitrum.io/rpc"),
});
const sdk = new GmxSdk({
chainId: 42161,
rpcUrl: "https://arb1.arbitrum.io/rpc",
oracleUrl: "https://arbitrum-api.gmxinfra.io",
subsquidUrl: "https://gmx.squids.live/gmx-synthetics-arbitrum:prod/api/graphql",
walletClient,
});
If you're using CommonJS, require the v1 client from the package root:
const { GmxSdk } = require("@gmx-io/sdk");
const sdk = new GmxSdk({
chainId: 42161,
rpcUrl: "https://arb1.arbitrum.io/rpc",
oracleUrl: "https://arbitrum-api.gmxinfra.io",
subsquidUrl: "https://gmx.squids.live/gmx-synthetics-arbitrum:prod/api/graphql",
});
If you're using wagmi in a React application, pass useWalletClient().data as the walletClient parameter after the wallet connects.
Common workflows
If you want exact "I want to do X" steps, start with the Integration guide:
- Read positions, active orders, and recent trades for one account
- Submit a
Market Increaseorder withorders.long() - Cancel active orders by on-chain order key
- Understand the SDK's simulation, retry, timeout, and eventual-consistency behavior
- Debug duplicate submits, missing receipts, stale reads, and cancel/replace races in Troubleshooting
API Reference
The SDK groups methods into modules, each accessed as a property on the GmxSdk instance. All methods are async.
Read methods
sdk.markets
| Method | Parameters | Returns | Notes |
|---|---|---|---|
getMarkets(offset?, limit?) | offset: bigint = 0n, limit: bigint = 300n | { marketsData?, marketsAddresses?, error? } | Builds the listed market set from oracle market configs plus on-chain reader data |
getMarketsInfo() | — | { marketsInfoData?, tokensData?, pricesUpdatedAt? } | Fetches full market details including token prices; use this for most workflows |
getDailyVolumes() | — | Record<string, bigint> | undefined | Returns a map of market address → daily volume in USD (30-decimal precision) |
sdk.tokens
| Method | Parameters | Returns | Notes |
|---|---|---|---|
getTokensData() | — | { tokensData, pricesUpdatedAt } | Fetches token metadata and current prices for all tokens on the configured chain |
sdk.positions
| Method | Parameters | Returns | Notes |
|---|---|---|---|
getPositions(p) | marketsData, tokensData, start?: number, end?: number | { positionsData? } | Requires an account set via sdk.setAccount(). start/end are pagination offsets (default 0/1000) |
sdk.orders
| Method | Parameters | Returns | Notes |
|---|---|---|---|
getOrders(p) | marketsInfoData, tokensData, account?, orderTypesFilter?, marketsDirectionsFilter? | { count, ordersInfoData } | Returns all active orders for the account; supports filtering by order type and market direction |
sdk.trades
| Method | Parameters | Returns | Notes |
|---|---|---|---|
getTradeHistory(p) | pageSize, pageIndex, marketsInfoData?, tokensData?, fromTxTimestamp?, toTxTimestamp?, marketsDirectionsFilter?, orderEventCombinations?, forAllAccounts? | Promise<TradeAction[]> | Fetches paginated trade history from the Subsquid indexer |
sdk.accounts
| Method | Parameters | Returns | Notes |
|---|---|---|---|
getGovTokenDelegates(account?) | account?: string | string[] | Returns the governance token delegates for the given account address; on chains without a configured GovToken it resolves to [] |
sdk.oracle
| Method | Parameters | Returns | Notes |
|---|---|---|---|
getMarkets() | — | Promise<MarketSdkConfig[]> | Fetches raw market configs from the configured oracle URL |
getTokens() | — | Promise<TokensResponse> | Fetches raw token configs from the configured oracle URL |
getTickers() | — | Promise<TickersResponse> | Fetches current oracle ticker data from /prices/tickers |
Write methods
Write methods submit transactions on-chain and require a walletClient and an account set via sdk.setAccount().
Quick order helpers (sdk.orders)
The quick helpers automatically calculate swap paths, amounts, and fees from the current market state. You don't need to pre-fetch marketsInfoData or tokensData — the helpers fetch what they need unless you pass them directly.
| Method | Key parameters | Notes |
|---|---|---|
long(p) | payAmount or sizeAmount, marketAddress, payTokenAddress, collateralTokenAddress, allowedSlippageBps?, leverage?, limitPrice? | Opens a long position; see Usage Examples |
short(p) | Same as long | Opens a short position |
swap(p) | fromAmount or toAmount, fromTokenAddress, toTokenAddress, allowedSlippageBps?, triggerPrice? | Executes a token swap; set triggerPrice for a Limit Swap |
Full order methods (sdk.orders)
Full methods require pre-computed amounts (use the utils module or the calculation helpers in @gmx-io/sdk/utils/trade).
| Method | Notes |
|---|---|
createIncreaseOrder(p) | Creates a Market Increase or Limit Increase order; see Usage Examples |
createDecreaseOrder(p) | Creates a Market Decrease, Stop-Loss, or Take-Profit order |
createSwapOrder(p) | Creates a Market Swap or Limit Swap order |
cancelOrders(orderKeys: string[]) | Cancels one or more orders by their on-chain keys |
Configuration Options
Pass a GmxSdkConfig object to the GmxSdk constructor. The full interface is:
interface GmxSdkConfig {
// Required
chainId: number; // 42161 (Arbitrum), 43114 (Avalanche), 3637 (Botanix), 43113 (Avalanche Fuji), or 421614 (Arbitrum Sepolia)
rpcUrl: string; // RPC endpoint for the chain
oracleUrl: string; // GMX oracle keeper URL
subsquidUrl: string; // GMX Subsquid GraphQL URL
// Optional — connection
account?: string; // Wallet address; can also be set via sdk.setAccount()
publicClient?: PublicClient; // Custom viem PublicClient; auto-created from rpcUrl if omitted
walletClient?: WalletClient; // Viem WalletClient; required for write operations
// Optional — overrides
tokens?: Record<string, Partial<Token>>; // Override token metadata by address
markets?: Record<string, Partial<MarketSdkConfig>>; // Override market config by address
// Optional — fees
settings?: {
uiFeeReceiverAccount?: string; // Address that receives UI fees on orders you submit
};
}
Network URLs
Use the following endpoints for each production network:
| Network | Oracle URL | Chain ID |
|---|---|---|
| Arbitrum | https://arbitrum-api.gmxinfra.io | 42161 |
| Avalanche | https://avalanche-api.gmxinfra.io | 43114 |
| Botanix | https://botanix-api.gmxinfra.io | 3637 |
For Subsquid GraphQL endpoints per network, see GraphQL. The Arbitrum endpoint is https://gmx.squids.live/gmx-synthetics-arbitrum:prod/api/graphql.
The table above lists production endpoints. Alpha-5 also accepts Arbitrum Sepolia (421614) and Avalanche Fuji (43113) in chainId where you provide matching RPC, oracle, and Subsquid endpoints for those environments.
For the underlying contract ABIs and parameters the SDK wraps, see Contracts.
The SDK source exports getOracleKeeperUrl(chainId) from @gmx-io/sdk/configs/oracleKeeper if you want to look up the URL programmatically.
Setting up custom viem clients
By default, the SDK creates its own viem PublicClient from rpcUrl. If you create your own client, include the batching configuration to optimize multicall performance:
import { createPublicClient, http } from "viem";
import { arbitrum } from "viem/chains";
import { BATCH_CONFIGS } from "@gmx-io/sdk/configs/batch";
const publicClient = createPublicClient({
chain: arbitrum,
transport: http("https://arb1.arbitrum.io/rpc", {
batch: BATCH_CONFIGS[42161].http,
}),
batch: BATCH_CONFIGS[42161].client,
});
const sdk = new GmxSdk({
chainId: 42161,
rpcUrl: "https://arb1.arbitrum.io/rpc",
oracleUrl: "https://arbitrum-api.gmxinfra.io",
subsquidUrl: "https://gmx.squids.live/gmx-synthetics-arbitrum:prod/api/graphql",
publicClient,
});
Customizing token data
To override default token properties, pass a tokens map keyed by token address:
const sdk = new GmxSdk({
chainId: 42161,
rpcUrl: "https://arb1.arbitrum.io/rpc",
oracleUrl: "https://arbitrum-api.gmxinfra.io",
subsquidUrl: "https://gmx.squids.live/gmx-synthetics-arbitrum:prod/api/graphql",
tokens: {
"0x912CE59144191C1204E64559FE8253a0e49E6548": {
name: "My Custom Name for ARB",
},
},
});
The name field for this token address uses your custom value throughout the SDK.
Customizing market availability
To hide specific markets from the SDK, set isListed: false in the markets override map:
const sdk = new GmxSdk({
chainId: 42161,
rpcUrl: "https://arb1.arbitrum.io/rpc",
oracleUrl: "https://arbitrum-api.gmxinfra.io",
subsquidUrl: "https://gmx.squids.live/gmx-synthetics-arbitrum:prod/api/graphql",
markets: {
"0x47c031236e19d024b42f8AE6780E44A573170703": {
isListed: false,
},
},
});
Usage Examples
These examples show the most common integration workflows. All examples assume you've initialized sdk and called sdk.setAccount() as shown in Initialization.
Quick order helpers
For most use cases, use the quick helper methods. They automatically calculate swap paths, amounts, and execution fees from the current market state. You can optionally pass marketsInfoData and tokensData yourself to reduce API calls if you've already fetched them.
Open a long position on ETH/USD (WETH-USDC) using WETH as collateral:
await sdk.orders.long({
payAmount: 100031302n, // Raw pay-token amount in the token's native decimals
marketAddress: "0x70d95587d40A2caf56bd97485aB3Eec10Bee6336", // ETH/USD [WETH-USDC]
payTokenAddress: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", // WETH
collateralTokenAddress: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // USDC
allowedSlippageBps: 125, // 1.25% slippage tolerance
leverage: 50000n, // 5x leverage (basis points, 10000 = 1x)
});
Swap ARB to LINK:
await sdk.orders.swap({
fromAmount: 1000n,
fromTokenAddress: "0x912CE59144191C1204E64559FE8253a0e49E6548", // ARB
toTokenAddress: "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4", // LINK
allowedSlippageBps: 125,
});
Pass payAmount to specify your input amount. Pass sizeAmount instead to target a specific position size. The helper calculates the other value automatically.
Synthetic token addresses
The payTokenAddress is the token you're depositing. The collateralTokenAddress is the token held as margin. Some markets use synthetic index tokens — for example, the BTC/USD [WBTC-USDC] market's index token is a synthetic BTC, so you pass the WBTC address (0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f) as collateralTokenAddress, not the synthetic address.
Full order method
Use createIncreaseOrder when you need precise control over order amounts, for example in automated strategies where you compute increaseAmounts yourself using getIncreasePositionAmounts from @gmx-io/sdk/utils/trade.
import type { IncreasePositionAmounts } from "@gmx-io/sdk/types/trade";
const { marketsInfoData, tokensData } = await sdk.markets.getMarketsInfo();
if (!marketsInfoData || !tokensData) {
throw new Error("Failed to fetch market data");
}
// ETH/USD [WETH-USDC] on Arbitrum
const marketInfo = marketsInfoData["0x70d95587d40A2caf56bd97485aB3Eec10Bee6336"];
// USDC as collateral
const collateralToken = tokensData["0xaf88d065e77c8cC2239327C5EDb3A432268e5831"];
// Compute increaseAmounts with getIncreasePositionAmounts().
// That helper needs the full IncreasePositionParams input shown in:
// /docs/sdk/v1/exports/utils/trade/increase
const increaseAmounts: IncreasePositionAmounts = /* precomputed */;
await sdk.orders.createIncreaseOrder({
marketsInfoData,
tokensData,
isLimit: false,
isLong: true,
marketAddress: marketInfo.marketTokenAddress,
allowedSlippage: 50,
collateralToken,
collateralTokenAddress: collateralToken.address,
receiveTokenAddress: collateralToken.address,
fromToken: collateralToken,
marketInfo,
indexToken: marketInfo.indexToken,
increaseAmounts,
});
The increaseAmounts object has a complex structure including swapStrategy, price impact data, and fee components. Use getIncreasePositionAmounts from @gmx-io/sdk/utils/trade to compute it rather than constructing it manually. The complete low-level input shape is documented in trade/increase.
Operational notes
Keep these behaviors in mind when you integrate SDK v1 into a production app:
- Write methods return a transaction hash after submission. They do not wait for keeper execution or refetch the resulting order state for you.
- The default viem HTTP clients created by
GmxSdkdisable transport retries. Add your own retry and backoff policy around safe read paths. - The SDK does not provide idempotency keys or client order IDs. Prevent duplicate submits in your UI while a transaction is pending.
- Market increases and market swaps simulate before submit by default. Some non-market flows skip simulation in the current implementation. See the Integration guide for the exact behavior.
Next steps
- Start with the Integration guide for scenario-based walkthroughs
- See SDK Examples for more complete integration patterns
- See Exports for utility functions available in the SDK