Skip to main content

Getting Started

The full SDK v1 client (GmxSdk) exposes these top-level modules:

  • markets — fetch market definitions, pricing, and daily volumes
  • tokens — fetch token metadata and balances
  • positions — read open positions for an account
  • orders — read active orders and submit new ones (long, short, swap, cancel)
  • trades — fetch historical trade activity
  • accounts — read governance delegate data
  • oracle — read raw oracle markets, tokens, and tickers from the configured oracle URL
  • utils — 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 WalletClient for 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",
});
tip

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 Increase order with orders.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

MethodParametersReturnsNotes
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> | undefinedReturns a map of market address → daily volume in USD (30-decimal precision)

sdk.tokens

MethodParametersReturnsNotes
getTokensData(){ tokensData, pricesUpdatedAt }Fetches token metadata and current prices for all tokens on the configured chain

sdk.positions

MethodParametersReturnsNotes
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

MethodParametersReturnsNotes
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

MethodParametersReturnsNotes
getTradeHistory(p)pageSize, pageIndex, marketsInfoData?, tokensData?, fromTxTimestamp?, toTxTimestamp?, marketsDirectionsFilter?, orderEventCombinations?, forAllAccounts?Promise<TradeAction[]>Fetches paginated trade history from the Subsquid indexer

sdk.accounts

MethodParametersReturnsNotes
getGovTokenDelegates(account?)account?: stringstring[]Returns the governance token delegates for the given account address; on chains without a configured GovToken it resolves to []

sdk.oracle

MethodParametersReturnsNotes
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.

MethodKey parametersNotes
long(p)payAmount or sizeAmount, marketAddress, payTokenAddress, collateralTokenAddress, allowedSlippageBps?, leverage?, limitPrice?Opens a long position; see Usage Examples
short(p)Same as longOpens 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).

MethodNotes
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:

NetworkOracle URLChain ID
Arbitrumhttps://arbitrum-api.gmxinfra.io42161
Avalanchehttps://avalanche-api.gmxinfra.io43114
Botanixhttps://botanix-api.gmxinfra.io3637

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.

tip

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,
});
tip

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,
});
note

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 GmxSdk disable 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