Order Appendix
The Order Appendix is a powerful feature in the Nado Protocol that allows you to specify advanced order parameters through a compact bit-packed integer. This appendix encodes various order properties including execution types, isolated positions, TWAP parameters, and trigger types.
Overview
The appendix is a 128-bit integer with the following bit layout (from MSB to LSB):
| 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 (bits 0-7): Protocol version for future compatibility (currently version 1)
Isolated (bit 8): Whether the order is for an isolated position
Order Type (bits 9-10): Execution type (DEFAULT, IOC, FOK, POST_ONLY)
Reduce Only (bit 11): Whether the order can only reduce existing positions
Trigger Type (bits 12-13): Type of trigger order (NONE, PRICE, TWAP, TWAP_CUSTOM_AMOUNTS)
Reserved (bits 14-63): Reserved for future use
Value (bits 64-127): Additional data (isolated margin or TWAP parameters)
Building an Appendix
Use the build_appendix() function to create an appendix with the desired parameters:
from nado_protocol.utils.order import build_appendix
from nado_protocol.utils.expiration import OrderType
# Basic order with IOC execution type
appendix = build_appendix(order_type=OrderType.IOC)
# Reduce-only order
appendix = build_appendix(
order_type=OrderType.POST_ONLY,
reduce_only=True
)
Order Execution Types
The appendix supports four execution types:
- DEFAULT
Standard limit order behavior
- IOC (Immediate or Cancel)
Execute immediately, cancel any unfilled portion
- FOK (Fill or Kill)
Execute completely or cancel the entire order
- POST_ONLY
Only add liquidity to the order book, never take liquidity
Example:
from nado_protocol.utils.order import build_appendix
from nado_protocol.utils.expiration import OrderType
# Create different order types
ioc_appendix = build_appendix(order_type=OrderType.IOC)
fok_appendix = build_appendix(order_type=OrderType.FOK)
post_only_appendix = build_appendix(order_type=OrderType.POST_ONLY)
Isolated Positions
Isolated positions allow you to allocate specific margin to a trade, limiting your risk:
from nado_protocol.utils.order import build_appendix
from nado_protocol.utils.expiration import OrderType
from nado_protocol.utils.math import to_x6
# Create isolated position with 1000 USDC margin
# Note: isolated margin uses x6 precision and is limited to 64-bit values
isolated_appendix = build_appendix(
isolated=True,
isolated_margin=to_x6(1000),
order_type=OrderType.POST_ONLY
)
Note
Isolated positions and TWAP orders are mutually exclusive - you cannot have both in the same order.
TWAP Orders
Time-Weighted Average Price (TWAP) orders split large orders into smaller chunks executed over time:
from nado_protocol.utils.order import build_appendix, OrderAppendixTriggerType
# Create TWAP order with 10 child orders and 0.5% slippage tolerance
twap_appendix = build_appendix(
trigger_type=OrderAppendixTriggerType.TWAP,
twap_times=10,
twap_slippage_frac=0.005
)
# TWAP with custom amounts and reduce-only
twap_custom_appendix = build_appendix(
trigger_type=OrderAppendixTriggerType.TWAP_CUSTOM_AMOUNTS,
twap_times=5,
twap_slippage_frac=0.01,
reduce_only=True
)
Trigger Orders
Trigger orders can be configured with different trigger types:
from nado_protocol.utils.order import build_appendix, OrderAppendixTriggerType
from nado_protocol.utils.expiration import OrderType
# Price-based trigger order
price_trigger_appendix = build_appendix(
trigger_type=OrderAppendixTriggerType.PRICE,
order_type=OrderType.IOC,
reduce_only=True
)
Extracting Appendix Information
You can extract information from an existing appendix:
from nado_protocol.utils.order import (
order_version,
order_execution_type,
order_reduce_only,
order_is_isolated,
order_isolated_margin,
order_is_trigger_order,
order_trigger_type,
order_twap_data
)
from nado_protocol.utils.math import to_x6
appendix = build_appendix(
isolated=True,
isolated_margin=to_x6(500),
order_type=OrderType.IOC,
reduce_only=True
)
# Extract information
version = order_version(appendix)
execution_type = order_execution_type(appendix)
is_reduce_only = order_reduce_only(appendix)
is_isolated = order_is_isolated(appendix)
margin = order_isolated_margin(appendix)
is_trigger = order_is_trigger_order(appendix)
trigger_type = order_trigger_type(appendix)
print(f"Order Type: {execution_type.name}")
print(f"Reduce Only: {is_reduce_only}")
print(f"Isolated: {is_isolated}")
if margin:
print(f"Isolated Margin: {margin}")
Using Appendix with Orders
When placing orders, include the appendix in your order parameters:
from nado_protocol.engine_client.types import OrderParams, PlaceOrderParams
from nado_protocol.utils.order import build_appendix
from nado_protocol.utils.expiration import OrderType
from nado_protocol.utils.subaccount import SubaccountParams
import time
# Create appendix for a reduce-only IOC order
appendix = build_appendix(
order_type=OrderType.IOC,
reduce_only=True
)
# Create order with appendix
order = OrderParams(
sender=SubaccountParams(subaccount_owner="0x...", subaccount_name="default"),
priceX18=28898000000000000000000,
amount=-10000000000000000, # Sell to close position
expiration=int(time.time()) + 3600, # 1 hour from now
appendix=appendix
)
# Place the order
client.market.place_order(PlaceOrderParams(product_id=1, order=order))
Complex Trading Scenarios
Here are examples of complex trading scenarios using appendix:
Stop Loss Order
# Stop loss: reduce-only IOC order that executes immediately when triggered
stop_loss_appendix = build_appendix(
order_type=OrderType.IOC,
reduce_only=True,
trigger_type=OrderAppendixTriggerType.PRICE
)
Take Profit Order
# Take profit: reduce-only post-only order to avoid paying taker fees
take_profit_appendix = build_appendix(
order_type=OrderType.POST_ONLY,
reduce_only=True,
trigger_type=OrderAppendixTriggerType.PRICE
)
Breakout Strategy with Isolated Position
from nado_protocol.utils.math import to_x6
# Enter position on breakout with dedicated margin
# Note: isolated margin uses x6 precision and is limited to 64-bit values
breakout_appendix = build_appendix(
isolated=True,
isolated_margin=to_x6(5000), # 5000 USDC dedicated margin
order_type=OrderType.IOC
)
Large Order with TWAP
# Split large order into 20 smaller orders with 0.1% slippage tolerance
twap_appendix = build_appendix(
trigger_type=OrderAppendixTriggerType.TWAP,
twap_times=20,
twap_slippage_frac=0.001
)
Validation Rules
The appendix system enforces several validation rules:
Isolated + TWAP Exclusion: An order cannot be both isolated and a TWAP order
TWAP Parameters: TWAP orders require both twap_times and twap_slippage_frac
Isolated Margin: isolated_margin can only be set when isolated=True
Margin Limits: Isolated margin uses x6 precision and must be between 0 and 2^64 - 1
Error Handling
The appendix functions will raise ValueError for invalid configurations:
from nado_protocol.utils.math import to_x6
# This will raise ValueError: isolated_margin can only be set when isolated=True
try:
build_appendix(isolated=False, isolated_margin=to_x6(1000))
except ValueError as e:
print(f"Error: {e}")
# This will raise ValueError: TWAP parameters required
try:
build_appendix(trigger_type=OrderAppendixTriggerType.TWAP)
except ValueError as e:
print(f"Error: {e}")
# This will raise ValueError: Isolated and TWAP are mutually exclusive
try:
build_appendix(
isolated=True,
isolated_margin=to_x6(1000),
trigger_type=OrderAppendixTriggerType.TWAP,
twap_times=5,
twap_slippage_frac=0.01
)
except ValueError as e:
print(f"Error: {e}")
API Reference
For detailed API documentation, see:
nado_protocol.utils.order.build_appendix()nado_protocol.utils.order.order_version()nado_protocol.utils.order.order_execution_type()nado_protocol.utils.order.order_reduce_only()nado_protocol.utils.order.order_is_isolated()nado_protocol.utils.order.order_isolated_margin()nado_protocol.utils.order.order_is_trigger_order()nado_protocol.utils.order.order_trigger_type()nado_protocol.utils.order.order_twap_data()