Skip to main content

Order Examples

This page shows how to create, edit, cancel, and track orders using GmxApiSdk. All examples assume Arbitrum (chainId: 42161).

Setup

import { GmxApiSdk, PrivateKeySigner } from "@gmx-io/sdk/v2";

const sdk = new GmxApiSdk({ chainId: 42161 });

// For signing orders — PrivateKeySigner wraps viem's privateKeyToAccount
const signer = new PrivateKeySigner("0xYOUR_PRIVATE_KEY");
const account = signer.address;

IAbstractSigner is the minimal interface the SDK needs. You can implement it with any wallet:

import type { IAbstractSigner } from "@gmx-io/sdk/v2";

const walletSigner: IAbstractSigner = {
address: "0x...",
async signTypedData(domain, types, value) {
return wallet.signTypedData({ domain, types, message: value });
},
async signMessage(message) {
return wallet.signMessage({ message });
},
// Optional - only needed for classic mode
async sendTransaction(tx) {
return wallet.sendTransaction(tx);
},
};

Discovering markets and prices

Before creating orders, you need to know which markets exist and what prices to use. The symbol field used in order requests (e.g. "ETH/USD [WETH-USDC]") comes from the market data.

List available markets

const markets = await sdk.fetchMarkets();

for (const m of markets) {
console.log(m.symbol); // "ETH/USD [WETH-USDC]"
console.log(m.marketTokenAddress); // "0x70d95587d40A2caf56bd97485aB3Eec10Bee6336"
console.log(m.isSpotOnly); // false (perp market) or true (spot only)
console.log(m.leverageTiers); // [{ maxLeverage, minCollateralFactor, maxPositionSize }]
console.log(m.minPositionSizeUsd); // Minimum position size (30 decimals)
console.log(m.minCollateralUsd); // Minimum collateral (30 decimals)
}

Get current prices and market data

// All markets
const tickers = await sdk.fetchMarketsTickers();

// Filter by symbol
const ethTickers = await sdk.fetchMarketsTickers({
symbols: ["ETH/USD [WETH-USDC]"],
});

// Filter by market address
const filtered = await sdk.fetchMarketsTickers({
addresses: ["0x70d95587d40A2caf56bd97485aB3Eec10Bee6336"],
});

const ticker = ethTickers[0];
console.log(ticker.symbol); // "ETH/USD [WETH-USDC]"
console.log(ticker.markPrice); // Current mark price (30 decimals)
console.log(ticker.maxPrice); // Max price
console.log(ticker.minPrice); // Min price
console.log(ticker.high24h); // 24h high
console.log(ticker.low24h); // 24h low
console.log(ticker.priceChangePercent24hBps); // 24h change in bps
console.log(ticker.longInterestUsd); // Open interest long (30 decimals)
console.log(ticker.shortInterestUsd); // Open interest short (30 decimals)
console.log(ticker.availableLiquidityLong);
console.log(ticker.availableLiquidityShort);
console.log(ticker.fundingRateLong); // Current funding rate
console.log(ticker.borrowingRateLong); // Current borrowing rate

Get token info

// Static token catalog (symbols, decimals, addresses)
const tokens = await sdk.fetchTokens();

// Token metadata with current prices
const tokensData = await sdk.fetchTokensData();

Read positions and orders

// Current positions for an account
const positions = await sdk.fetchPositionsInfo({ address: account });

for (const p of positions) {
console.log(p.indexName); // "ETH/USD"
console.log(p.isLong); // true or false
console.log(p.sizeInUsd); // Position size (30-decimal bigint)
console.log(p.collateralUsd); // Collateral value
console.log(p.marketAddress); // Market address
}

// Positions with their related TP/SL orders
const positionsWithOrders = await sdk.fetchPositionsInfo({
address: account,
includeRelatedOrders: true,
});

// Active orders
const orders = await sdk.fetchOrders({ address: account });

for (const o of orders) {
console.log(o.key); // Order key (used for edit/cancel)
console.log(o.isLong);
console.log(o.sizeDeltaUsd); // Size delta (30-decimal bigint)
console.log(o.triggerPrice); // Trigger price for limit/conditional orders
console.log(o.executionFee);
}

Check wallet balances and allowances

const balances = await sdk.fetchWalletBalances({ address: account });

const allowances = await sdk.fetchAllowances({
address: account,
spender: "router",
});

// Build an ERC-20 approval if needed
const approveTx = sdk.buildApproveTransaction({
tokenAddress: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // USDC on Arbitrum
spender: "router",
amount: 1_000_000_000n, // 1000 USDC
});
// approveTx.to, approveTx.data — send via your wallet

Express orders — three-step flow

Express orders use the API relay (Gelato). The flow is: preparesignsubmit.

1. Prepare

const prepared = await sdk.prepareOrder({
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: 10n * 10n ** 30n, // $10 (30 decimals)
collateralToken: "USDC",
collateralToPay: { amount: 1_000_000n, token: "USDC" }, // 1 USDC (6 decimals)
mode: "express",
from: account,
});

// prepared.payloadType === "typed-data"
// prepared.estimates contains fee and price impact data
console.log(prepared.estimates);
// {
// sizeDeltaUsd: 10000000000000000000000000000000n,
// executionFeeAmount: ...,
// positionFeeUsd: ...,
// acceptablePrice: ...,
// swapPriceImpactDeltaUsd: ...,
// positionPriceImpactDeltaUsd: ...,
// borrowingFeeUsd: ...,
// fundingFeeUsd: ...,
// }

2. Sign

const signature = await sdk.signOrder(prepared, signer);

3. Submit

const submitted = await sdk.submitOrder({
mode: prepared.mode,
requestId: prepared.requestId,
signature,
from: account,
idempotencyKey: prepared.idempotencyKey,
eip712Data: {
batchParams: prepared.payload.batchParams,
relayParams: prepared.payload.relayParams,
},
});

console.log(submitted.requestId); // Use this to track the order
console.log(submitted.status); // "relay_accepted", "relay_pending", etc.

Referral codes and UI fee receivers

Order prepare requests can include optional attribution fields:

const prepared = await sdk.prepareOrder({
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: 10n * 10n ** 30n,
collateralToken: "USDC",
collateralToPay: { amount: 1_000_000n, token: "USDC" },
mode: "express",
from: account,
referralCode: "YourReferralCode",
uiFeeReceiver: "0x1234567890123456789012345678901234567890",
});

referralCode may be either the human-readable registered referral code, such as "YourReferralCode", or an already encoded bytes32 value. Human-readable codes can contain letters, digits, and underscores, and can be up to 20 characters long. The GMX API encodes human-readable codes before building the order payload.

Use uiFeeReceiver for custom UI fee attribution. The receiver must be a valid address and should have its UI fee factor configured on-chain. For regular receiver addresses, the prepared Express order keeps the same receiver address; register and claim UI fees from that original receiver. TWAP orders create their own synthetic UI fee receiver and do not accept caller-supplied uiFeeReceiver.

Express orders — one-call convenience

executeExpressOrder runs prepare + sign + submit in a single call:

const result = await sdk.executeExpressOrder(
{
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: 10n * 10n ** 30n,
collateralToken: "USDC",
collateralToPay: { amount: 1_000_000n, token: "USDC" },
mode: "express",
from: account,
},
signer
);

console.log(result.requestId);

Tracking order status

Poll fetchOrderStatus with the requestId returned from submission:

const status = await sdk.fetchOrderStatus({
requestId: submitted.requestId,
});

console.log(status.status);
// Possible values:
// "prepared" | "relay_accepted" | "relay_pending" | "relay_submitted"
// | "created" | "executed" | "cancelled" | "relay_failed" | "relay_reverted"

// Terminal statuses: "executed", "cancelled", "relay_failed", "relay_reverted"

Polling loop example:

async function waitForExecution(sdk, requestId, timeoutMs = 60_000) {
const terminal = new Set(["executed", "cancelled", "relay_failed", "relay_reverted"]);
const start = Date.now();

while (Date.now() - start < timeoutMs) {
const status = await sdk.fetchOrderStatus({ requestId });
if (terminal.has(status.status)) return status;
await new Promise((r) => setTimeout(r, 2000));
}

throw new Error(`Order ${requestId} did not reach terminal status within ${timeoutMs}ms`);
}

const finalStatus = await waitForExecution(sdk, result.requestId);
// finalStatus.executionTxnHash — on-chain execution tx
// finalStatus.orderKeys — created order keys
// finalStatus.error — error details if failed

Market increase (open / add to position)

Long

await sdk.executeExpressOrder(
{
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: 100n * 10n ** 30n, // $100
collateralToken: "USDC",
collateralToPay: { amount: 10_000_000n, token: "USDC" }, // 10 USDC
mode: "express",
from: account,
},
signer
);

Short

await sdk.executeExpressOrder(
{
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "short",
orderType: "market",
size: 100n * 10n ** 30n,
collateralToken: "USDC",
collateralToPay: { amount: 10_000_000n, token: "USDC" },
mode: "express",
from: account,
},
signer
);

Limit increase

Set triggerPrice for the entry price. The order stays open until the price is reached.

const result = await sdk.executeExpressOrder(
{
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "limit",
size: 10n * 10n ** 30n,
triggerPrice: 2000n * 10n ** 30n, // $2,000 entry
collateralToken: "USDC",
collateralToPay: { amount: 1_000_000n, token: "USDC" },
mode: "express",
from: account,
},
signer
);

// The order is created on-chain; verify it appears in your orders list
const orders = await sdk.fetchOrders({ address: account });

Market decrease (close / reduce position)

Partial close

// Get current position size
const positions = await sdk.fetchPositionsInfo({ address: account });
const ethLong = positions.find((p) => p.isLong && p.indexName?.includes("ETH/USD"));
const currentSize = BigInt(ethLong.sizeInUsd);

await sdk.executeExpressOrder(
{
kind: "decrease",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: currentSize / 2n, // Close half
collateralToken: "USDC",
receiveToken: "USDC",
mode: "express",
from: account,
},
signer
);

Full close

await sdk.executeExpressOrder(
{
kind: "decrease",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: currentSize, // Close entire position
collateralToken: "USDC",
receiveToken: "USDC",
mode: "express",
from: account,
},
signer
);

keepLeverage

When decreasing, keepLeverage controls whether collateral is withdrawn proportionally:

// keepLeverage: true — removes collateral proportionally, preserving leverage ratio
await sdk.executeExpressOrder(
{
kind: "decrease",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: currentSize / 5n,
keepLeverage: true,
collateralToken: "USDC",
receiveToken: "USDC",
mode: "express",
from: account,
},
signer
);

// keepLeverage: false — keeps collateral, reducing leverage

receiveToken

Choose which token to receive when closing:

await sdk.executeExpressOrder(
{
kind: "decrease",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: currentSize,
collateralToken: "USDC",
receiveToken: "ETH", // Receive ETH instead of USDC
mode: "express",
from: account,
},
signer
);

Conditional decrease (stop-loss / take-profit)

Stop-loss

const result = await sdk.executeExpressOrder(
{
kind: "decrease",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "stop-loss",
size: 10n * 10n ** 30n,
triggerPrice: 1800n * 10n ** 30n, // Trigger at $1,800
collateralToken: "USDC",
receiveToken: "USDC",
mode: "express",
from: account,
},
signer
);

Take-profit

const result = await sdk.executeExpressOrder(
{
kind: "decrease",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "take-profit",
size: 10n * 10n ** 30n,
triggerPrice: 5000n * 10n ** 30n, // Trigger at $5,000
collateralToken: "USDC",
receiveToken: "USDC",
mode: "express",
from: account,
},
signer
);

TP/SL with position entry

Attach take-profit and stop-loss orders when opening a position using tpsl:

// Get current mark price for TP/SL calculation
const tickers = await sdk.fetchMarketsTickers({ symbols: ["ETH/USD [WETH-USDC]"] });
const markPrice = BigInt(tickers[0].maxPrice);

await sdk.executeExpressOrder(
{
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: 10n * 10n ** 30n,
collateralToken: "USDC",
collateralToPay: { amount: 1_000_000n, token: "USDC" },
mode: "express",
from: account,
tpsl: [
{ type: "take-profit", triggerPrice: markPrice * 105n / 100n, size: 10n * 10n ** 30n },
{ type: "stop-loss", triggerPrice: markPrice * 95n / 100n, size: 10n * 10n ** 30n },
],
},
signer
);

tpsl supports partial-size TP/SL — omit size to use the full position size. tpsl is only valid on increase orders with market or limit order types. It cannot be used with twap, decrease, or swap orders.

Swap orders

await sdk.executeExpressOrder(
{
kind: "swap",
symbol: "ETH/USD [WETH-USDC]",
orderType: "market",
size: 1_000_000n, // 1 USDC (token decimals)
collateralToPay: { amount: 1_000_000n, token: "USDC" },
receiveToken: "ETH",
mode: "express",
from: account,
},
signer
);

TWAP orders

Split a large order into multiple parts executed over time:

await sdk.executeExpressOrder(
{
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "twap",
size: 20n * 10n ** 30n, // $20 total
collateralToken: "USDC",
collateralToPay: { amount: 3_000_000n, token: "USDC" },
twapConfig: { duration: 600, parts: 2 }, // 2 parts over 10 minutes
mode: "express",
from: account,
},
signer
);

twapConfig.parts must be between 2 and 30 inclusive. twapConfig.duration must be greater than 0. TWAP cannot be combined with tpsl.

Edit orders

Change the trigger price (or size) of an existing limit/conditional order:

const orders = await sdk.fetchOrders({ address: account });
const orderId = orders[0].key;

const prepared = await sdk.prepareEditOrder({
orderIds: [orderId],
newTriggerPrice: 2500n * 10n ** 30n, // New trigger: $2,500
mode: "express",
from: account,
});

const signature = await sdk.signOrder(prepared, signer);

const submitted = await sdk.submitOrder({
mode: prepared.mode,
requestId: prepared.requestId,
signature,
from: account,
idempotencyKey: prepared.idempotencyKey,
eip712Data: {
batchParams: prepared.payload.batchParams,
relayParams: prepared.payload.relayParams,
},
});

prepareEditOrder accepts newSize, newTriggerPrice, newAcceptablePrice, newAutoCancel, and executionFeeTopUp.

Cancel orders

Cancel specific orders

const orders = await sdk.fetchOrders({ address: account });
const orderId = orders[0].key;

const prepared = await sdk.prepareCancelOrder({
orderIds: [orderId],
mode: "express",
from: account,
});

const signature = await sdk.signOrder(prepared, signer);

await sdk.submitOrder({
mode: prepared.mode,
requestId: prepared.requestId,
signature,
from: account,
idempotencyKey: prepared.idempotencyKey,
eip712Data: {
batchParams: prepared.payload.batchParams,
relayParams: prepared.payload.relayParams,
},
});

Cancel all orders

const prepared = await sdk.prepareCancelOrder({
all: true,
mode: "express",
from: account,
});

const signature = await sdk.signOrder(prepared, signer);

await sdk.submitOrder({
mode: prepared.mode,
requestId: prepared.requestId,
signature,
from: account,
idempotencyKey: prepared.idempotencyKey,
eip712Data: {
batchParams: prepared.payload.batchParams,
relayParams: prepared.payload.relayParams,
},
});

Classic mode (on-chain transactions)

Classic mode returns raw transaction calldata instead of typed data. You sign and broadcast the transaction yourself — no relay is involved.

const prepared = await sdk.prepareOrder({
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: 10n * 10n ** 30n,
collateralToken: "USDC",
collateralToPay: { amount: 1_000_000n, token: "USDC" },
mode: "classic",
from: account,
});

// prepared.payloadType === "transaction"
// prepared.payload.to — contract address
// prepared.payload.data — calldata
// prepared.payload.value — ETH value (execution fee)

// Send with your wallet / viem / ethers:
const txHash = await signer.sendTransaction({
to: prepared.payload.to,
data: prepared.payload.data,
value: BigInt(prepared.payload.value ?? 0),
});

PrivateKeySigner.sendTransaction requires rpcUrl in the constructor:

import { getViemChain } from "@gmx-io/sdk/configs/chains";

const signer = new PrivateKeySigner("0xYOUR_PRIVATE_KEY", {
rpcUrl: "https://arb1.arbitrum.io/rpc",
chain: getViemChain(42161),
});

Slippage and execution fee buffer

Slippage

Controls the acceptable price deviation in basis points (default varies by order type). Higher slippage widens the acceptable price range without affecting size or fee estimates.

const prepared = await sdk.prepareOrder({
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: 10n * 10n ** 30n,
collateralToPay: { amount: 1_000_000n, token: "USDC" },
slippage: 30, // 0.3% (in basis points)
mode: "express",
from: account,
});

Execution fee buffer

Adds a buffer to the execution fee in basis points. Higher buffer reduces the chance of order failure due to gas spikes.

const prepared = await sdk.prepareOrder({
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: 10n * 10n ** 30n,
collateralToPay: { amount: 1_000_000n, token: "USDC" },
executionFeeBufferBps: 5000, // 50% buffer
mode: "express",
from: account,
});

One-click trading (subaccounts)

Subaccounts let you sign orders with a derived key, avoiding wallet popups for each trade. The main wallet signs setup messages and approval refreshes; order signatures are produced by the generated subaccount key.

Quick setup

// Generate a local subaccount signer, refresh its on-chain status, and sign
// a SubaccountApproval only if the current on-chain authorization is not enough.
const subaccountAddress = await sdk.activateSubaccount(signer, {
expiresInSeconds: 86400, // 24 hours
maxAllowedCount: 100, // Max 100 actions
});

console.log(sdk.subaccountAddress); // "0x..."
console.log(sdk.subaccountStatus?.remainingActions);
console.log(sdk.hasActiveSubaccount); // true
console.log(sdk.subaccountApprovalMessage?.signature);
// Non-empty signature: the next subaccount order will submit this approval.
// "0x": the subaccount is already active on-chain and no new owner approval is needed.

Submit orders with subaccount

Once activated, executeExpressOrder automatically attaches the current subaccount approval and uses the subaccount signer for the order:

const result = await sdk.executeExpressOrder(
{
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: 10n * 10n ** 30n,
collateralToken: "USDC",
collateralToPay: { amount: 1_000_000n, token: "USDC" },
mode: "express",
from: account, // Main account address
},
signer // Main signer identifies the account; SDK signs with subaccount internally
);

If the order submitted a fresh approval, wait until the order is created or executed, then refresh the subaccount state before preparing another subaccount order:

let status = await sdk.fetchOrderStatus({
requestId: result.requestId,
});

while (!["created", "executed", "cancelled", "relay_failed", "relay_reverted"].includes(status.status)) {
await new Promise((r) => setTimeout(r, 2000));
status = await sdk.fetchOrderStatus({ requestId: result.requestId });
}

if (status.status === "created" || status.status === "executed") {
await sdk.refreshSubaccountState(account);
}

console.log(sdk.subaccountApprovalMessage?.signature); // "0x" after the approval is usable on-chain

Manual subaccount flow

For more control, use the explicit prepare, sign, and submit flow. If the SDK has active subaccount state, prepareOrder() attaches the current subaccount address and approval, signOrder() uses the subaccount signer, and submitOrder() forwards the approval that belongs to the prepared request:

const prepared = await sdk.prepareOrder({
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: 10n * 10n ** 30n,
collateralToken: "USDC",
collateralToPay: { amount: 1_000_000n, token: "USDC" },
mode: "express",
from: account,
});

const signature = await sdk.signOrder(prepared, signer);

const submitted = await sdk.submitOrder({
mode: prepared.mode,
requestId: prepared.requestId,
signature,
from: account,
idempotencyKey: prepared.idempotencyKey,
eip712Data: {
batchParams: prepared.payload.batchParams,
relayParams: prepared.payload.relayParams,
},
});

If you manage subaccount approval yourself, you can pass subaccountAddress and subaccountApproval explicitly. The high-level signOrder() helper still needs the SDK-managed subaccount signer; if the subaccount key is external, sign the prepared typed data with that subaccount signer and submit the approval yourself.

const prepared = await sdk.prepareOrder({
kind: "increase",
symbol: "ETH/USD [WETH-USDC]",
direction: "long",
orderType: "market",
size: 10n * 10n ** 30n,
collateralToken: "USDC",
collateralToPay: { amount: 1_000_000n, token: "USDC" },
mode: "express",
from: account,
subaccountAddress: sdk.subaccountAddress,
subaccountApproval: sdk.subaccountApprovalMessage,
});

Step-by-step setup

// 1. Generate subaccount (deterministic from main signer)
const subAddr = await sdk.generateSubaccount(signer);

// 2. Refresh SDK-managed on-chain status
const status = await sdk.refreshSubaccountState(signer.address);

// 3. Activate with custom limits
await sdk.activateSubaccount(signer, {
expiresInSeconds: 86400,
maxAllowedCount: (status?.currentActionsCount ?? 0n) + 50n,
});

// 4. Refresh after an approval-bearing order is created or executed
await sdk.refreshSubaccountState(signer.address);

// 5. Clear when done or when the connected wallet account changes
sdk.clearSubaccount();

Collateral management

Deposit or withdraw collateral on an existing position using prepareCollateral:

const prepared = await sdk.prepareCollateral({
operation: "deposit", // or "withdraw"
positionKey: "0x...", // Position key from fetchPositionsInfo
amount: 5_000_000n, // 5 USDC (token decimals)
mode: "express",
from: account,
});

const signature = await sdk.signOrder(prepared, signer);

await sdk.submitOrder({
mode: prepared.mode,
requestId: prepared.requestId,
signature,
from: account,
idempotencyKey: prepared.idempotencyKey,
eip712Data: {
batchParams: prepared.payload.batchParams,
relayParams: prepared.payload.relayParams,
},
});

prepareCollateral also accepts optional slippage, executionFeeBufferBps, and gasPaymentToken parameters.

GMX Account operations

GMX Account helpers are available in @gmx-io/sdk/v2. Same-chain operations return or submit wallet transactions on the settlement chain. Cross-chain deposits prepare source-chain transactions. Cross-chain withdrawals prepare typed data and submit through the relayer API.

Setup

import { GmxApiSdk, PrivateKeySigner } from "@gmx-io/sdk/v2";
import { ARBITRUM, SOURCE_BASE_MAINNET, getViemChain } from "@gmx-io/sdk/configs/chains";
import { getMultichainTokenGroups, resolveStargatePool } from "@gmx-io/sdk/configs/multichainTokens";

const sdk = new GmxApiSdk({ chainId: ARBITRUM });

const signer = new PrivateKeySigner(process.env.PRIVATE_KEY as `0x${string}`, {
rpcUrl: process.env.ARBITRUM_RPC_URL,
chain: getViemChain(ARBITRUM),
});

const sourceSigner = new PrivateKeySigner(process.env.PRIVATE_KEY as `0x${string}`, {
rpcUrl: process.env.BASE_RPC_URL,
chain: getViemChain(SOURCE_BASE_MAINNET),
});

const account = signer.address;
const tokenGroups = getMultichainTokenGroups();
const arbitrumUsdc = resolveStargatePool(tokenGroups, { chainId: ARBITRUM, tokenSymbol: "USDC" });
const baseUsdc = resolveStargatePool(tokenGroups, { chainId: SOURCE_BASE_MAINNET, tokenSymbol: "USDC" });

if (!arbitrumUsdc || !baseUsdc) {
throw new Error("USDC is not configured for the selected chains");
}

Same-chain deposit and withdrawal

const depositTxHash = await sdk.executeSameChainDeposit(signer, {
tokenAddress: arbitrumUsdc.address,
amount: 1_000_000n,
account,
});

const bridgeOutParams = sdk.buildSameChainWithdrawBridgeOutParams({
tokenAddress: arbitrumUsdc.address,
amount: 500_000n,
});

const withdrawTxHash = await sdk.executeSameChainWithdraw(signer, {
bridgeOutParams,
});

Cross-chain deposit

await sdk.executeErc20Approve(sourceSigner, {
tokenAddress: baseUsdc.address,
spender: baseUsdc.stargate,
amount: 1_000_000n,
});

const deposit = await sdk.executeCrossChainDeposit(sourceSigner, {
srcChainId: SOURCE_BASE_MAINNET,
account,
tokenSymbol: baseUsdc.symbol,
amount: 1_000_000n,
});

Cross-chain withdrawal

const bridgeOutParams = sdk.buildCrossChainWithdrawBridgeOutParams({
tokenAddress: arbitrumUsdc.address,
amount: 500_000n,
dstChainId: SOURCE_BASE_MAINNET,
stargateAddress: arbitrumUsdc.stargate,
slippageBps: 5,
});

const submitted = await sdk.executeCrossChainWithdraw(signer, {
srcChainId: SOURCE_BASE_MAINNET,
account,
bridgeOutParams,
});

const status = await sdk.getCrossChainWithdrawStatus(submitted.requestId);

Manual cross-chain withdrawal

const prepared = await sdk.prepareCrossChainWithdraw({
srcChainId: SOURCE_BASE_MAINNET,
account,
bridgeOutParams,
});

const signature = await sdk.signCrossChainWithdraw(prepared, signer);

const submitted = await sdk.submitCrossChainWithdraw({
srcChainId: SOURCE_BASE_MAINNET,
account,
signature,
bridgeOutParams,
relayParamsPayload: prepared.payload.relayParams,
relayerFeeTokenAddress: prepared.payload.gasPaymentParams.relayerFeeTokenAddress,
relayerFeeAmount: prepared.payload.gasPaymentParams.relayerFeeAmount,
requestId: prepared.requestId,
});

Type reference

Use these tables as a compact reference for the public transaction types used by the examples above.

PrepareOrderRequest

FieldTypeRequiredNotes
kind"increase" | "decrease" | "swap"Yes
symbolstringYesMarket symbol, e.g. "ETH/USD [WETH-USDC]"
direction"long" | "short"For increase/decrease
orderType"market" | "limit" | "stop-market" | "take-profit" | "stop-loss" | "twap"Yes
sizebigintYesUSD value with 30 decimals for positions; token decimals for swaps
triggerPricebigintFor limit/conditional30 decimals
slippagenumberNoBasis points
collateralTokenstringNoToken symbol for position collateral
collateralToPay{ amount: bigint, token: string }For increase/swapToken amount in native decimals
receiveTokenstringFor swap/decreaseToken symbol to receive
keepLeveragebooleanNoFor decrease — withdraw collateral proportionally
manualSwapPathstring[]NoOverride auto swap path with market addresses
acceptablePriceImpactBpsbigintNoAcceptable price impact in basis points
executionFeeBufferBpsnumberNoExecution fee buffer in basis points
twapConfig{ duration: number, parts: number, frequency?: number }For TWAPparts: 2–30, duration in seconds, optional frequency in seconds
tpslArray<{ type, triggerPrice, size? }>NoTP/SL sidecar orders (increase only)
gasPaymentTokenstringNoToken for gas payment
referralCodestringNoHuman-readable referral code or encoded bytes32; human-readable codes support letters, digits, and underscores, up to 20 characters
uiFeeReceiverstringNoCustom UI fee receiver address; not supported for TWAP orders
mode"express" | "classic"Yes
fromstringYesSender address
subaccountAddressstringNoFor 1CT
subaccountApprovalobjectNoFor 1CT

PrepareOrderResponse

FieldTypeDescription
requestIdstringRequest identifier used for signing, submission, and status polling
idempotencyKeystring?Idempotency key returned by the API, when available
payloadType"transaction" | "typed-data"Whether the prepared payload is a classic transaction or EIP-712 typed data
mode"express" | "classic"Transaction mode requested during preparation
payloadRecord<string, any>Prepared transaction or typed-data payload
estimatesOrderEstimates?Fee, impact, and acceptable-price estimates
expiresAtnumber?Unix timestamp when the prepared payload expires
warningsstring[]?Non-blocking API warnings for the prepared order
traceIdstring?API trace identifier for support and debugging

SubmitOrderResponse

FieldTypeDescription
requestIdstringRequest identifier
statusstringSee status values above
txHashstring?Relay transaction hash
taskIdstring?Gelato task identifier, when relay submission creates one
error{ code, message }?Error details
traceIdstring?API trace identifier for support and debugging

OrderEstimates

Returned in prepared.estimates:

FieldTypeDescription
sizeDeltaUsdbigintPosition size delta (30 decimals)
executionFeeAmountbigintExecution fee in gas token
positionFeeUsdbigintPosition fee (30 decimals)
acceptablePricebigintWorst acceptable execution price (30 decimals)
positionPriceImpactDeltaUsdbigintPosition price impact (30 decimals)
swapPriceImpactDeltaUsdbigintSwap price impact (30 decimals)
borrowingFeeUsdbigintBorrowing fee (30 decimals)
fundingFeeUsdbigintFunding fee (30 decimals)

OrderStatusResponse

FieldTypeDescription
requestIdstringRequest identifier
statusstringSee status values above
txHashstring?Relay transaction hash
createdTxnHashstring?On-chain order creation tx
executionTxnHashstring?On-chain execution tx
orderKeysstring[]?Created order keys
cancellationReasonstring?Why the order was cancelled
taskIdstring?Gelato task identifier, when available
error{ code, message }?Error details
createdAtstring?API creation timestamp
updatedAtstring?API update timestamp
traceIdstring?API trace identifier for support and debugging