8.9 KiB
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_timesandtwap_slippage_frac. - Isolated Margin: Can only set
isolated_marginwhenisolated=True.
Migration from Legacy Format
Before (deprecated):
- Order type encoded in
expirationfield. - Reduce-only flag encoded in
noncefield. - Limited trigger functionality.
After (current):
- All flags consolidated in 128-bit
appendix. expirationis pure timestamp.nonceencodesrecv_timeonly.- Enhanced trigger and isolated margin support.
Building Appendix Values
Using Python SDK (Recommended)
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