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
nonceintegerYesPositive integer, incrementing nonce
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 UpdateLeverage type
  const domain = {
    name: "Synthetix",
    version: "1",
    chainId: 1,
    verifyingContract: "0x0000000000000000000000000000000000000000"
  };
 
  const types = {
    UpdateLeverage: [
      { name: "subAccountId", type: "uint256" },
      { name: "symbol", type: "string" },
      { name: "leverage", type: "string" },
      { name: "nonce", type: "uint256" },
      { name: "expiresAfter", type: "uint256" }
    ]
  };
 
  const message = {
    subAccountId: BigInt(subAccountId),
    symbol,
    leverage: leverage.toString(),
    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 any positive integer as nonce
  • Each nonce must be greater than the previous one (incrementing)
  • Date.now() is a convenient option, not a requirement
  • If nonce conflicts occur, increment by 1 and retry

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

Error CodeDescriptionRetryable
UNAUTHORIZEDEIP-712 signature validation failedNo
VALIDATION_ERRORRequest validation failedNo
MISSING_REQUIRED_FIELDRequired field is missingNo
INVALID_FORMATField format is invalidNo
INVALID_VALUEInvalid parameter valueNo
RATE_LIMIT_EXCEEDEDToo many requests in time windowYes
INSUFFICIENT_MARGINNot enough margin for tradeNo
ORDER_NOT_FOUNDOrder does not existNo
OPERATION_TIMEOUTOperation timed outYes

Next Steps