Skip to content

Update Leverage (WebSocket)

Adjust leverage settings for trading markets through the WebSocket connection for rapid risk management and position scaling.

Endpoint

ws.send() wss://api.synthetix.io/v1/ws/trade

Request

Request Format

{
  "id": "leverage-1",
  "method": "post",
  "params": {
    "action": "updateLeverage",
    "symbol": "BTC-USDT",
    "leverage": "20",
    "subAccountId": "1867542890123456789",
    "nonce": 1704067200000,
    "expiresAfter": 1704067300,
    "signature": {
      "v": 28,
      "r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
      "s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
    }
  }
}

Parameters

Request Parameters

ParameterTypeRequiredDescription
idstringYesClient-generated unique request identifier
methodstringYesMust be "post"
paramsobjectYesContains the trading request payload with all fields flattened

Params Object Fields

ParameterTypeRequiredDescription
actionstringYesMust be "updateLeverage"
symbolstringYesMarket symbol (e.g., "BTC-USDT")
leveragestringYesDesired leverage multiplier as string
subAccountIdstringYesSubaccount identifier
nonceintegerYesIncrementing nonce (Unix ms timestamp as number)
expiresAfterintegerNoOptional expiration timestamp in seconds (0 = no expiration)
signatureobjectYesEIP-712 signature

EIP-712 Type Definition

const UpdateLeverageTypes = {
  UpdateLeverage: [
    { name: "subAccountId", type: "uint256" },
    { name: "symbol", type: "string" },
    { name: "leverage", type: "string" },
    { name: "nonce", type: "uint256" },
    { name: "expiresAfter", type: "uint256" }
  ]
}

Response Format

Success Response

{
  "id": "leverage-1",
  "status": 200,
  "result": {
    "symbol": "BTC-USDT",
    "previousLeverage": "10",
    "newLeverage": "20"
  }
}
Response Fields:
FieldTypeDescription
symbolstringMarket symbol
previousLeveragestringPrevious leverage setting
newLeveragestringNew leverage setting

Error Response

{
  "id": "leverage-1",
  "status": 400,
  "result": null,
  "error": {
    "code": 400,
    "message": "Leverage exceeds maximum allowed"
  }
}

Implementation Example

import { ethers } from 'ethers';
 
async function updateLeverage(ws, signer, subAccountId, symbol, leverage) {
  const nonce = Date.now();
  const expiresAfter = Math.floor(Date.now() / 1000) + 30;
 
  // EIP-712 signature using SubAccountAction type
  const domain = {
    name: "Synthetix",
    version: "1",
    chainId: 1,
    verifyingContract: "0x0000000000000000000000000000000000000000"
  };
 
  const types = {
    SubAccountAction: [
      { name: "subAccountId", type: "uint256" },
      { name: "action", type: "string" },
      { name: "nonce", type: "uint256" },
      { name: "expiresAfter", type: "uint256" }
    ]
  };
 
  const message = {
    subAccountId: BigInt(subAccountId),
    action: "updateLeverage",
    nonce: BigInt(nonce),
    expiresAfter: BigInt(expiresAfter)
  };
 
  const sig = await signer.signTypedData(domain, types, message);
  const signature = ethers.Signature.from(sig);
 
  // Send request
  ws.send(JSON.stringify({
    id: `leverage-${Date.now()}`,
    method: "post",
    params: {
      action: "updateLeverage",
      symbol,
      leverage: leverage.toString(),
      subAccountId,
      nonce,
      expiresAfter,
      signature: { v: signature.v, r: signature.r, s: signature.s }
    }
  }));
}
 
// Usage: Set leverage to 20x for BTC-USDT
await updateLeverage(ws, signer, "1867542890123456789", "BTC-USDT", "20");
 
// Usage: Set conservative 5x leverage for ETH-USDT
await updateLeverage(ws, signer, "1867542890123456789", "ETH-USDT", "5");

Important Behavior

How Leverage Settings Work

When you update leverage for a market:

  • The new leverage setting applies to all future positions you open in that market
  • Existing positions retain their original leverage - they are NOT affected
  • The setting persists until you explicitly change it again
Example:
1. You have an open BTC position at 10x leverage
2. You call updateLeverage(subAccountId, "BTC-USDT", "25")
3. Your existing position REMAINS at 10x
4. Any NEW BTC positions will open at 25x

Can You Change Leverage on Existing Positions?

No, you cannot directly change leverage on existing positions. However:

  • For Isolated Positions: Use updateIsolatedMargin (REST API only) to add/remove margin, which changes effective leverage
  • For Cross Margin Positions: Leverage is fixed at position entry

Error Handling

Common Errors

Error CodeMessageDescription
-32000Invalid leverageLeverage exceeds maximum allowed for symbol
-32001Position existsCannot change leverage with open positions
-32002Invalid symbolMarket symbol does not exist
-32003Margin insufficientNot enough margin for new leverage setting

Signing

All trading methods are signed using EIP-712. Each successful trading request will contain:

  • A piece of structured data that includes the sender address
  • A signature of the hash of that structured data, signed by the sender

For detailed information on EIP-712 signing, see EIP-712 Signing.

Nonce Management

The nonce system prevents replay attacks and ensures order uniqueness:

  • Use current timestamp in milliseconds as nonce
  • Each nonce must be greater than the previous one
  • Recommended: Use Date.now() or equivalent
  • If nonce conflicts occur, increment by 1 and retry

:::note SubAccountAction Exception SubAccountAction endpoints (getPositions, getOpenOrders, getOrdersHistory, getTrades, getFundingPayments, getSubAccount, getDelegatedSigners, getBalanceUpdates) do not require a nonce. Only the signature and optional expiresAfter parameters are needed. :::

ErrorDescription
Invalid signatureEIP-712 signature validation failed
Invalid market symbolMarket symbol not recognized
Nonce already usedNonce must be greater than previous value
Rate limit exceededToo many requests in time window
Request expiredexpiresAfter timestamp has passed

Next Steps