Add Support for Specifying Margin Type (Cross/Isolated) in Order Placement #313

Hello dYdX Team,

I noticed that the v4-chain repository does not appear to have a feature for specifying the margin type (Cross or Isolated) during order placement via the clob module.

Adding this capability as a parameter in the place-order command would greatly improve flexibility for traders managing their margin strategies.

Currently, I am using the following code to place an order. By default, it places orders with Cross Margin, but there is no option to switch to Isolated Margin:

import asyncio
import random

from dydx_v4_client import MAX_CLIENT_ID, NodeClient, OrderFlags, Wallet
from dydx_v4_client.indexer.rest.constants import OrderType
from dydx_v4_client.indexer.rest.indexer_client import IndexerClient
from dydx_v4_client.network import TESTNET
from dydx_v4_client.node.market import Market
from v4_proto.dydxprotocol.clob.order_pb2 import Order

MARKET_ID = "ETH-USD"
TEST_ADDRESS = ''
DYDX_TEST_MNEMONIC = (
)

async def place_market_order(size: float):
    try:
        node = await NodeClient.connect(TESTNET.node)
        indexer = IndexerClient(TESTNET.rest_indexer)

        market_data = await indexer.markets.get_perpetual_markets(MARKET_ID)
        market = Market(market_data["markets"][MARKET_ID])

        wallet = await Wallet.from_mnemonic(node, DYDX_TEST_MNEMONIC, TEST_ADDRESS)

        account_info = await node.get_account(TEST_ADDRESS)
        wallet.sequence = account_info.sequence

        order_id = market.order_id(
            TEST_ADDRESS, 0, random.randint(0, MAX_CLIENT_ID), OrderFlags.SHORT_TERM
        )

        current_block = await node.latest_block_height()

        new_order = market.order(
            order_id=order_id,
            order_type=OrderType.LIMIT,
            side=Order.Side.SIDE_SELL,
            size=size,
            price=0,
            time_in_force=Order.TimeInForce.TIME_IN_FORCE_UNSPECIFIED,
            reduce_only=False,
            good_til_block=current_block + 10,
        )

        transaction = await node.place_order(
            wallet=wallet,
            order=new_order,
        )

        print(f"Transaction successful: {transaction}")
        wallet.sequence += 1

    except Exception as e:
        print(f"An error occurred: {e}")

asyncio.run(place_market_order(1.053))

As you can see, this code places orders with Cross Margin by default, and there is no option to switch to Isolated Margin.

Could you clarify whether this functionality is currently supported or if there are plans to include it in future updates?

Thank you for your time and consideration.

Best regards,

1 Like

Hi Soheil,

The margin type can be set using the designated subaccounts. If the order is placed on subaccount 0 to 127 then the order would be placed on cross-margin. From subaccount 128 or greater, the order will be placed using isolated margin. You can find further information in this link: How to integrate APIs with FE isolated positions · dYdX · v4

Hope that helps! Thank you.

Could you please provide an example code?

1 Like

Here are a couple of examples with typescript:

3 Likes
async def place_market_order(size: float):
    try:
        node = await NodeClient.connect(TESTNET.node)
        indexer = IndexerClient(TESTNET.rest_indexer)
        market_data = await indexer.markets.get_perpetual_markets(MARKET_ID)
        market = Market(market_data["markets"][MARKET_ID])

        wallet = await Wallet.from_mnemonic(node, DYDX_TEST_MNEMONIC, TEST_ADDRESS)

        account_info = await node.get_account(TEST_ADDRESS)
        wallet.sequence = account_info.sequence

        order_id = market.order_id(
            TEST_ADDRESS, 128 # subaccount number
            , random.randint(0, MAX_CLIENT_ID), OrderFlags.SHORT_TERM
        )

        current_block = await node.latest_block_height()

        new_order = market.order(
            order_id=order_id,
            order_type=OrderType.LIMIT,
            side=Order.Side.SIDE_SELL,
            size=size,
            price=0,
            time_in_force=Order.TimeInForce.TIME_IN_FORCE_UNSPECIFIED,
            reduce_only=False,
            good_til_block=current_block + 10,
        )

        transaction = await node.place_order(
            wallet=wallet,
            order=new_order,
        )

        print(f"Transaction successful: {transaction}")
        wallet.sequence += 1

    except Exception as e:
        print(f"An error occurred: {e}")

Why does the code stop working when I set the subaccount number to 128? How can I fix this issue?

My output:

Transaction successful: tx_response {
  txhash: "5C3F056821C5E748A37B78619E7DC01F3B9F02213C4471E4E6655BD4521F3E33"
  raw_log: "[]"
}

This is my output, which says “successful,” but it’s not actually successful. That means no order is registered on the website, and…
Can you guide me on how to fix this?

You can also see that my transaction doesn’t exist on this website:
https://testnet.dydx.explorers.guru/transaction/5C3F056821C5E748A37B78619E7DC01F3B9F02213C4471E4E6655BD4521F3E33.

2 Likes

Hi Soheil,
Did you deposit to subaccount 128 before placing the order?
If not, you can see how to do it here: How to transfer tokens between accounts · dYdX · v4

I tested what you mentioned, but it didn’t work. That’s why I created a new topic and asked my question.

My topic link: Issue Running transfer_example_subaccount_transfer.py from dydxprotocol v4 Clients

1 Like

I see, I would suggest to open a ticket on dydx.trade or ask on #developer channel on Discord, someone from the support team will be able to help.

1 Like

Hi @soheil_khaledabadi,

As @septiandara suggested, I strongly recommend raising this issue in the official dYdX Discord or opening a ticket here: dYdX Support.

The forum is not intended for technical support or front-end issues. It is dedicated to fostering governance and development discussions within the dYdX Community. Please refer to the community guidelines for more details.

I’ll now close this topic. Thank you for your understanding.

Cheers,