Files
ritmex-bot/docs/nado/developer-resources/api/order-appendix.md

8.9 KiB
Raw Permalink Blame History

Order Appendix

The Order Appendix is a 128-bit integer that encodes extra order parameters like execution type, isolated margin, and trigger configurations.

Bit Layout

| value   | reserved | trigger | reduce only | order type | isolated | version |
| 64 bits | 50 bits  | 2 bits  | 1 bit       | 2 bits     | 1 bit    | 8 bits  |
| 127..64 | 63..14   | 13..12  | 11          | 10..9      | 8        | 7..0    |

Fields (from LSB to MSB)

Version

8-bits (0-7). Protocol version identifier. Currently 1. May increment when encoding structure updates.

Isolated

1-bit (8). Indicates whether the order uses isolated margin. Isolated positions have dedicated margin for a specific product, creating a separate isolated subaccount. The original account becomes the "parent subaccount" that can manage the isolated position.

Key Properties:

  • Creates isolated subaccount with dedicated margin
  • Only quote transfers allowed between isolated and parent subaccounts
  • Parent account can sign orders for isolated subaccount
  • Cannot be combined with TWAP orders

Example:

from nado_protocol.utils.appendix import build_appendix
from nado_protocol.utils.math import to_x6

# Create isolated order with 1000 USDT0 margin
appendix = build_appendix(
    order_type=OrderType.DEFAULT,
    isolated=True,
    isolated_margin=to_x6(1000)  # 1000 USDT0 (x6 precision)
)

Order Type

2-bits (9-10). Execution behavior for the order.

Values:

  • 0 - DEFAULT: Standard limit order behavior.
  • 1 - IOC (Immediate or Cancel): Execute immediately, cancel unfilled portion.
  • 2 - FOK (Fill or Kill): Execute completely or cancel entire order.
  • 3 - POST_ONLY: Only add liquidity, reject if would take liquidity.

Example:

from nado_protocol.utils.appendix import build_appendix

# Post-only order that only provides liquidity
appendix = build_appendix(
    order_type=OrderType.POST_ONLY
)

Reduce Only

1-bit (11). Restricts order to only decrease existing positions. Prevent accidentally increasing position size. Order will be rejected if it would increase the position in the same direction.

Use Cases:

  • Risk management when closing positions.
  • Taking profits without adding exposure.
  • Automated position reduction strategies.

Example:

from nado_protocol.utils.appendix import build_appendix

# Reduce-only order to close part of existing position
appendix = build_appendix(
    order_type=OrderType.DEFAULT,
    reduce_only=True
)

Trigger Type

2-bits (12-13). Conditional execution behavior.

Values:

  • 0 - NONE: Execute immediately (regular order).
  • 1 - PRICE: Price-based conditional order.
  • 2 - TWAP: Time-Weighted Average Price execution.
  • 3 - TWAP_CUSTOM_AMOUNTS: TWAP with randomized amounts.

Example:

from nado_protocol.utils.appendix import build_appendix

# TWAP order executing 5 times with 0.5% max slippage
appendix = build_appendix(
    order_type=OrderType.DEFAULT,
    trigger_type=OrderAppendixTriggerType.TWAP,
    twap_times=5,
    twap_slippage_frac=0.005  # 0.5%
)

Reserved

50-bits (14-63). Reserved for future protocol extensions. Must be set to 0.

Value

64-bits (64-127). Context-dependent data based on other flags.

TWAP Configuration (when trigger = 2 or 3)

Encodes TWAP execution parameters in the 64-bit value field:

| times  | slippage_x6 |
| 32 bits|   32 bits   |

Fields:

  • times: Number of TWAP executions.
  • slippage_x6: Maximum slippage × 1_000_000 (6 decimal precision).

Example:

from nado_protocol.utils.appendix import build_appendix, order_twap_data

# TWAP: 10 executions, 1% max slippage
appendix = build_appendix(
    order_type=OrderType.DEFAULT,
    trigger_type=OrderAppendixTriggerType.TWAP,
    twap_times=10,
    twap_slippage_frac=0.01  # 1%
)

# Extract TWAP data
times, slippage = order_twap_data(appendix)
# times = 10, slippage = 0.01

Isolated Margin (when isolated = 1)

Amount of quote (margin_x6) to transfer to isolated subaccount on first fill, stored in the 64-bit value field.

{% hint style="warning" %} Important: Isolated margin is stored in x6 precision (6 decimals) in the appendix value field.

  • Stored as margin_x6 (6 decimal places)
  • Takes up 64 bits (bits 64-127 of the appendix) {% endhint %}

Example:

from nado_protocol.utils.appendix import build_appendix, order_isolated_margin
from nado_protocol.utils.math import to_x6

# Isolated order with 500 USDT0 margin
appendix = build_appendix(
    order_type=OrderType.DEFAULT,
    isolated=True,
    isolated_margin=to_x6(500)  # 500 USDT0 (x6 precision)
)

# Extract isolated margin
margin = order_isolated_margin(appendix)
# Returns: 500000000 (500 * 10^6 in x6 precision)

Constraints

  • Isolated + TWAP: Cannot combine isolated orders with TWAP (trigger types 2 or 3).
  • TWAP Requirements: TWAP orders must specify both twap_times and twap_slippage_frac .
  • Isolated Margin: Can only set isolated_margin when isolated=True .

Migration from Legacy Format

Before (deprecated):

  • Order type encoded in expiration field.
  • Reduce-only flag encoded in nonce field.
  • Limited trigger functionality.

After (current):

  • All flags consolidated in 128-bit appendix .
  • expiration is pure timestamp.
  • nonce encodes recv_time only.
  • Enhanced trigger and isolated margin support.

Building Appendix Values

from nado_protocol.utils.expiration import OrderType
from nado_protocol.utils.appendix import build_appendix, OrderAppendixTriggerType

# Simple market order
appendix = build_appendix(order_type=OrderType.DEFAULT)

# Post-only reduce order
appendix = build_appendix(
    order_type=OrderType.POST_ONLY,
    reduce_only=True
)

# Isolated order with margin
appendix = build_appendix(
    order_type=OrderType.DEFAULT,
    isolated=True,
    isolated_margin=to_x6(1000)  # 1000 USDT0 (x6 precision)
)

# TWAP order
appendix = build_appendix(
    order_type=OrderType.DEFAULT,
    trigger_type=OrderAppendixTriggerType.TWAP,
    twap_times=5,
    twap_slippage_frac=0.01  # 1%
)

Manual Bit Manipulation (Advanced)

{% hint style="info" %} Refer to nado_protocol.utils.order for a detailed implementation. {% endhint %}

# Build appendix manually
def build_manual_appendix(order_type=0, isolated=False, reduce_only=False,
                         trigger_type=0, value=0):
    appendix = 0

    # Version (bits 0-7)
    appendix |= 1  # Version 1

    # Isolated (bit 8)
    if isolated:
        appendix |= 1 << 8

    # Order type (bits 9-10)
    appendix |= (order_type & 0b11) << 9

    # Reduce only (bit 11)
    if reduce_only:
        appendix |= 1 << 11

    # Trigger type (bits 12-13)
    appendix |= (trigger_type & 0b11) << 12

    # Reserved bits 14-63 (set to 0)

    # Value (bits 64-127)
    # Note: Value is stored in x6 precision for isolated margin
    appendix |= (value & ((1 << 64) - 1)) << 64

    return appendix

# Example: Post-only reduce order
appendix = build_manual_appendix(
    order_type=3,  # POST_ONLY
    reduce_only=True
)

Utility Functions

# Check order properties
is_reduce_only = order_reduce_only(appendix)
is_trigger = order_is_trigger_order(appendix)
is_isolated = order_is_isolated(appendix)
version = order_version(appendix)
order_type = order_execution_type(appendix)
trigger_type = order_trigger_type(appendix)

# Extract context data
twap_data = order_twap_data(appendix)  # Returns (times, slippage) or None
isolated_margin = order_isolated_margin(appendix)  # Returns margin or None