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: prepare → sign → submit.
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
| Field | Type | Required | Notes |
|---|---|---|---|
kind | "increase" | "decrease" | "swap" | Yes | |
symbol | string | Yes | Market symbol, e.g. "ETH/USD [WETH-USDC]" |
direction | "long" | "short" | For increase/decrease | |
orderType | "market" | "limit" | "stop-market" | "take-profit" | "stop-loss" | "twap" | Yes | |
size | bigint | Yes | USD value with 30 decimals for positions; token decimals for swaps |
triggerPrice | bigint | For limit/conditional | 30 decimals |
slippage | number | No | Basis points |
collateralToken | string | No | Token symbol for position collateral |
collateralToPay | { amount: bigint, token: string } | For increase/swap | Token amount in native decimals |
receiveToken | string | For swap/decrease | Token symbol to receive |
keepLeverage | boolean | No | For decrease — withdraw collateral proportionally |
manualSwapPath | string[] | No | Override auto swap path with market addresses |
acceptablePriceImpactBps | bigint | No | Acceptable price impact in basis points |
executionFeeBufferBps | number | No | Execution fee buffer in basis points |
twapConfig | { duration: number, parts: number, frequency?: number } | For TWAP | parts: 2–30, duration in seconds, optional frequency in seconds |
tpsl | Array<{ type, triggerPrice, size? }> | No | TP/SL sidecar orders (increase only) |
gasPaymentToken | string | No | Token for gas payment |
referralCode | string | No | Human-readable referral code or encoded bytes32; human-readable codes support letters, digits, and underscores, up to 20 characters |
uiFeeReceiver | string | No | Custom UI fee receiver address; not supported for TWAP orders |
mode | "express" | "classic" | Yes | |
from | string | Yes | Sender address |
subaccountAddress | string | No | For 1CT |
subaccountApproval | object | No | For 1CT |
PrepareOrderResponse
| Field | Type | Description |
|---|---|---|
requestId | string | Request identifier used for signing, submission, and status polling |
idempotencyKey | string? | 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 |
payload | Record<string, any> | Prepared transaction or typed-data payload |
estimates | OrderEstimates? | Fee, impact, and acceptable-price estimates |
expiresAt | number? | Unix timestamp when the prepared payload expires |
warnings | string[]? | Non-blocking API warnings for the prepared order |
traceId | string? | API trace identifier for support and debugging |
SubmitOrderResponse
| Field | Type | Description |
|---|---|---|
requestId | string | Request identifier |
status | string | See status values above |
txHash | string? | Relay transaction hash |
taskId | string? | Gelato task identifier, when relay submission creates one |
error | { code, message }? | Error details |
traceId | string? | API trace identifier for support and debugging |
OrderEstimates
Returned in prepared.estimates:
| Field | Type | Description |
|---|---|---|
sizeDeltaUsd | bigint | Position size delta (30 decimals) |
executionFeeAmount | bigint | Execution fee in gas token |
positionFeeUsd | bigint | Position fee (30 decimals) |
acceptablePrice | bigint | Worst acceptable execution price (30 decimals) |
positionPriceImpactDeltaUsd | bigint | Position price impact (30 decimals) |
swapPriceImpactDeltaUsd | bigint | Swap price impact (30 decimals) |
borrowingFeeUsd | bigint | Borrowing fee (30 decimals) |
fundingFeeUsd | bigint | Funding fee (30 decimals) |
OrderStatusResponse
| Field | Type | Description |
|---|---|---|
requestId | string | Request identifier |
status | string | See status values above |
txHash | string? | Relay transaction hash |
createdTxnHash | string? | On-chain order creation tx |
executionTxnHash | string? | On-chain execution tx |
orderKeys | string[]? | Created order keys |
cancellationReason | string? | Why the order was cancelled |
taskId | string? | Gelato task identifier, when available |
error | { code, message }? | Error details |
createdAt | string? | API creation timestamp |
updatedAt | string? | API update timestamp |
traceId | string? | API trace identifier for support and debugging |