Skip to main content

Sign

Overview

All DEX operations use standard Ethereum transactions with a specific structure:

  1. Standard Ethereum transaction sent to a fixed contract address
  2. To Address (FIXED): 0x00000000000000000000000000000000000000cc
  3. Input Data Format: [Command Byte] + [JSON Data]

Important Notes:

  1. Strict Schema: Only predefined fields are allowed in JSON data. Unknown fields will be rejected.
  2. Order ID: The order ID is the transaction hash (txHash) of the create order transaction
  3. Price and Quantity: All values in JSON contexts are already decimal-applied:
    • Price "2.3" means 2.3 USDT
    • Quantity "10.5" means 10.5 tokens
    • No conversion to smallest units (wei) is needed

Transaction Structure:

{
from: "0x...", // Your wallet address
to: "0x00000000000000000000000000000000000000cc", // FIXED contract address
data: "[CommandByte][JSON(Context)]", // Command byte + JSON payload
value: "0x0", // Always 0 for DEX operations
gasLimit: "0x30000", // Arbitrary large value (gas-free on L2)
gasPrice: "0x0", // Set to 0 (gas-free on L2)
nonce: "...", // Your account nonce (supports timeNonce: Unix timestamp in ms)
chainId: "..." // Kaia chain ID
}

Command Bytes

CommandByte ValueDescription
DexCommandSession0x01Session wallet operations
DexCommandTransfer0x02Kaia transfers
DexCommandTokenTransfer0x11Token-specific transfers
DexCommandOrder0x21Place new order
DexCommandCancel0x22Cancel specific order
DexCommandCancelAll0x23Cancel all orders
DexCommandModify0x24Modify existing order
DexCommandStopOrder0x25Place stop order

Enums for Order Context

Side

ValueDescription
0Buy order
1Sell order

Order Type

ValueDescription
0Limit order
1Market order

Order Mode

ValueDescription
0Base mode (default) - quantity in base token
1Quote mode - quantity in quote token (market orders only)

Note: Quote mode (orderMode=1) can only be used for market orders that execute at the best available price. It cannot be used for limit orders. This is particularly useful for market buy orders where you want to specify the amount in quote token (e.g., "buy with 1000 USDT").

Tick and Lot Size

Alpha Sec. enforces standardized price precision and minimum order sizes across all markets to ensure consistent execution, protect against dust orders, and maintain engine-level efficiency.

Price Precision

Prices support up to 5 significant digits and up to 8 decimal places. Depending on the price range, the allowed decimal places and the minimum order size change dynamically.

Decimal Rules by Price Range

The following table defines the allowed decimal precision and the minimum order size for each price tier. Lower priced assets allow deeper decimal precision but enforce larger minimum sizes to prevent excessively small orders.

Price RangeAllowed DecimalsMinimum Size
10,000 or higher00.00001
1,000 or higher10.0001
100 or higher20.001
10 or higher30.01
1 or higher40.1
0.1 or higher51
0.01 or higher61
0.001 or higher71
0.0001 or higher81
0.00001 or higher81
0.000001 or higher81
0.0000001 or higher81
0.00000001 or higher81

Valid Price and Size Conditions

An order is valid only if it satisfies the following conditions:

Price Rules:

  1. The price must be within 5 significant digits

    • Valid: 12345, 0.0012345
    • Invalid: 12345.6, 0.00123456
  2. The price cannot exceed the allowed decimal places for its price tier

    • Example: If the price is 120, allowed decimals = 2
      • Valid: 120.34
      • Invalid: 120.345

Size Rules:

  • The size must be equal to or greater than the minimum size defined for the current price tier
    • Example: At 50 dollars, minimum size is 0.01
      • Valid: 0.01
      • Invalid: 0.009

Note: Orders that do not meet these requirements will be rejected by the matching engine.

1. Session Wallet Operations (DexCommandSession - 0x01)

POST /api/v1/wallet/session

Manage session wallets for delegated trading. Session wallets allow trading without exposing the main wallet's private key.

Transaction Data Structure:

data = [0x01][JSON(SessionContext)]

SessionContext Structure:

{
"type": 1, // 1: create, 2: update, 3: delete
"publickey": "0xSessionWalletAddress",
"expiresAt": 1758005316, // Unix timestamp in seconds when session expires
"nonce": 0, // Session nonce for replay protection
"l1owner": "0x1234567890123456789012345678901234567890",
"l1signature": "0x..." // EIP-712 signature
}

SessionContext Fields:

FieldTypeMandatoryDescription
typeINTYESSession command: 1 (create), 2 (update), 3 (delete)
publickeySTRINGYESSession wallet address
expiresAtLONGYESUnix timestamp in seconds when session expires
nonceLONGYESNonce for replay protection
l1ownerSTRINGYESOwner wallet address (master wallet address)
l1signatureSTRINGYESEIP-712 signature from owner wallet

Session Command Types:

TypeValueDescription
SessionCreate1Create new session wallet
SessionUpdate2Update existing session
SessionDelete3Delete session wallet

EIP-712 Signature Structure

Session operations require an EIP-712 typed data signature:

const typedData = {
types: {
EIP712Domain: [
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "chainId", type: "uint256" },
{ name: "verifyingContract", type: "address" }
],
RegisterSessionWallet: [
{ name: "sessionWallet", type: "address" },
{ name: "expiry", type: "uint64" },
{ name: "nonce", type: "uint64" }
]
},
primaryType: "RegisterSessionWallet",
domain: {
name: "DEXSignTransaction",
version: "1",
chainId: 8217, // 8217 for Mainnet L1 Chain ID
verifyingContract: "0x0000000000000000000000000000000000000000"
},
message: {
sessionWallet: "0xSessionWalletAddress",
expiry: "1758005316", // Unix timestamp in seconds as string
nonce: "0" // Nonce as string
}
};

// Sign the typed data with the L1 owner's private key
const signature = await signer._signTypedData(
typedData.domain,
{ RegisterSessionWallet: typedData.types.RegisterSessionWallet },
typedData.message
);

// IMPORTANT: When building the transaction, use the same nonce
const nonce = "0"; // Or Date.now().toString() for timeNonce
const tx = {
from: l1owner,
to: "0x00000000000000000000000000000000000000cc",
data: commandByte + JSON.stringify({
type: 1, // SessionCreate
publickey: sessionWallet,
expiresAt: 1758005316,
nonce: parseInt(nonce), // MUST match the nonce in EIP-712 message
l1owner: l1owner,
l1signature: signature
}),
nonce: nonce, // Transaction nonce MUST match the nonce in SessionContext
gasPrice: '0x0',
gasLimit: '0x30000'
};

Request Body:

{
"tx": "0x02f8730183...{full signed transaction hex}"
}

Response:

{
"code": 200,
"errMsg": "OK",
"result": "0x4c9980c4fd003e9aae2e7a8a87812382c84a695614225e423aaf1676089dbbfe"
}

Notes:

  • Session wallets expire at the specified Unix timestamp (in milliseconds)
  • The nonce prevents replay attacks
  • Important: The nonce value in the EIP-712 message MUST match the nonce value in the actual transaction
  • Important: The chainId in the EIP-712 domain must be the L1 chain ID (e.g., 8217 for Kaia Mainnet), not the L2 chain ID
  • L1 signature must be an EIP-712 signature from the owner wallet
  • All session operations target the same fixed contract address: 0x00000000000000000000000000000000000000cc

2. Place Order (DexCommandOrder - 0x21)

POST /api/v1/order

Transaction Data Structure:

data = [0x21][JSON(OrderContext)]

OrderContext Structure:

{
"l1owner": "0x1234567890123456789012345678901234567890",
"baseToken": "1",
"quoteToken": "2",
"side": 0, // 0: buy, 1: sell
"price": "2.3", // Price
"quantity": "10.5", // Quantity
"orderType": 0, // 0: limit, 1: market
"orderMode": 0 // 0: base mode, 1: quote mode
}

OrderContext Fields:

FieldTypeMandatoryDescription
l1ownerSTRINGYESWallet address placing the order (master wallet address)
baseTokenSTRINGYESBase token ID (e.g., "1" for KAIA)
quoteTokenSTRINGYESQuote token ID (e.g., "2" for USDT)
sideINTYES0 for buy, 1 for sell
priceSTRINGYESLimit price (set to "0" for market orders)
quantitySTRINGYESOrder quantity
orderTypeINTYES0 for limit, 1 for market
orderModeINTYES0 for base mode, 1 for quote mode (quote mode only available for market orders)

Request Body:

{
"tx": "0x02f8730183...{full signed transaction hex}"
}

Response:

{
"code": 200,
"errMsg": "OK",
"result": "0x4c9980c4fd003e9aae2e7a8a87812382c84a695614225e423aaf1676089dbbfe"
}

2-1. Place TPSL Order (DexCommandOrder - 0x21)

POST /api/v1/order (with Take Profit/Stop Loss)

Transaction Data Structure:

data = [0x21][JSON(OrderContextWithTPSL)]

OrderContextWithTPSL Structure:

{
"l1owner": "0x1234567890123456789012345678901234567890",
"baseToken": "1",
"quoteToken": "2",
"side": 0, // 0: buy, 1: sell
"price": "2.3", // Main order price
"quantity": "10.5", // Quantity
"orderType": 0, // 0: limit, 1: market
"orderMode": 0, // 0: base mode, 1: quote mode
"tpsl": { // Take Profit/Stop Loss configuration
"tpLimit": "2.5", // Take profit limit price
"slTrigger": "2.1", // Stop loss trigger price
"slLimit": "2.09" // Optional: Stop loss limit price (if not set, SL is market)
}
}

OrderContextWithTPSL Fields:

FieldTypeMandatoryDescription
l1ownerSTRINGYESWallet address placing the order (master wallet address)
baseTokenSTRINGYESBase token ID
quoteTokenSTRINGYESQuote token ID
sideINTYES0 for buy, 1 for sell
priceSTRINGYESMain order limit price
quantitySTRINGYESOrder quantity
orderTypeINTYES0 for limit, 1 for market
orderModeINTYES0 for base mode, 1 for quote mode (quote mode only available for market orders)
tpslOBJECTYESTake profit and stop loss configuration
tpsl.tpLimitSTRINGYESTake profit limit price
tpsl.slTriggerSTRINGYESStop loss trigger price
tpsl.slLimitSTRINGNOStop loss limit price (omit for market SL)

Request Body:

{
"tx": "0x02f8730183...{full signed transaction hex}"
}

Response:

{
"code": 200,
"errMsg": "OK",
"result": "0x4c9980c4fd003e9aae2e7a8a87812382c84a695614225e423aaf1676089dbbfe"
}

TPSL Order ID Generation:

When placing a TPSL order, both TP and SL must be set together. The order IDs are systematically generated from the original order's transaction hash:

// Generated based on original order ID (txHash)
TPIncrement = 1 // TP order: txHash[31] + 1
SLIncrement = 2 // SL order: txHash[31] + 2

// Note: Only the last byte is rotated
// Example:
// Original: 0x011...00ff → TP ID: 0x011...0000, SL ID: 0x011...0001
  • Stop orders use the original txHash as-is (no increment)
  • Both TP and SL orders must be configured when using the tpsl field

3. Cancel Order (DexCommandCancel - 0x22)

POST /api/v1/order/cancel

Transaction Data Structure:

data = [0x22][JSON(CancelContext)]

CancelContext Structure:

{
"l1owner": "0x1234567890123456789012345678901234567890",
"orderId": "0x4c9980c4fd003e9aae2e7a8a87812382c84a695614225e423aaf1676089dbbfe"
}

CancelContext Fields:

FieldTypeMandatoryDescription
l1ownerSTRINGYESWallet address that owns the order (master wallet address)
orderIdSTRINGYESOrder ID to cancel (transaction hash)

Request Body:

{
"tx": "0x02f8730183...{full signed transaction hex}"
}

Response:

{
"code": 200,
"errMsg": "OK",
"result": "0x4c9980c4fd003e9aae2e7a8a87812382c84a695614225e423aaf1676089dbbfe"
}

4. Cancel All Orders (DexCommandCancelAll - 0x23)

POST /api/v1/order/cancel/all

Transaction Data Structure:

data = [0x23][JSON(CancelAllContext)]

CancelAllContext Structure:

{
"l1owner": "0x1234567890123456789012345678901234567890"
}

CancelAllContext Fields:

FieldTypeMandatoryDescription
l1ownerSTRINGYESWallet address whose orders to cancel (master wallet address)

Request Body:

{
"tx": "0x02f8730183...{full signed transaction hex}"
}

Response:

{
"code": 200,
"errMsg": "OK",
"result": "0x4c9980c4fd003e9aae2e7a8a87812382c84a695614225e423aaf1676089dbbfe"
}

5. Modify Order (DexCommandModify - 0x24)

POST /api/v1/order/modify

Important: Modify operates as a "cancel and replace" mechanism. The original order is canceled and a new order is created with the modified parameters. The new order ID will be the transaction hash of the modify transaction.

Transaction Data Structure:

data = [0x24][JSON(ModifyContext)]

ModifyContext Structure:

{
"l1owner": "0x1234567890123456789012345678901234567890",
"orderId": "0x4bed76ae0c75b1d1d0b291873ad7fb58b0986955ae0d49ca642a0f8c48efbae5",
"newPrice": "2.35", // New price (null to keep current)
"newQty": "20.0" // New quantity (null to keep current)
}

ModifyContext Fields:

FieldTypeMandatoryDescription
l1ownerSTRINGYESWallet address that owns the order (master wallet address)
orderIdSTRINGYESOrder ID to modify (original transaction hash)
newPriceSTRINGNONew limit price (null to keep current)
newQtySTRINGNONew quantity (null to keep current)

Request Body:

{
"tx": "0x02f8730183...{full signed transaction hex}"
}

Response:

{
"code": 200,
"errMsg": "OK",
"result": "0x4c9980c4fd003e9aae2e7a8a87812382c84a695614225e423aaf1676089dbbfe"
}

6. Stop Order (DexCommandStopOrder - 0x25)

POST /api/v1/order/trigger

Transaction Data Structure:

data = [0x25][JSON(StopOrderContext)]

StopOrderContext Structure:

{
"l1owner": "0x1234567890123456789012345678901234567890",
"baseToken": "1",
"quoteToken": "2",
"stopPrice": "2.1", // Trigger price
"price": "2.09", // Limit price (0 for market order)
"quantity": "10.0", // Quantity
"side": 0, // 0: buy, 1: sell
"orderType": 0, // 0: limit, 1: market
"orderMode": 0 // 0: base mode, 1: quote mode
}

StopOrderContext Fields:

FieldTypeMandatoryDescription
l1ownerSTRINGYESWallet address placing the order (master wallet address)
baseTokenSTRINGYESBase token ID
quoteTokenSTRINGYESQuote token ID
stopPriceSTRINGYESPrice at which the stop order triggers
priceSTRINGYESLimit price after trigger ("0" for market)
quantitySTRINGYESOrder quantity
sideINTYES0 for buy, 1 for sell
orderTypeINTYES0 for limit, 1 for market
orderModeINTYES0 for base mode, 1 for quote mode (quote mode only available for market orders)

Request Body:

{
"tx": "0x02f8730183...{full signed transaction hex}"
}

Response:

{
"code": 200,
"errMsg": "OK",
"result": "0x4c9980c4fd003e9aae2e7a8a87812382c84a695614225e423aaf1676089dbbfe"
}

7. Transfer Assets (DexCommandTokenTransfer - 0x11)

POST /api/v1/wallet/transfer

Transaction Data Structure:

data = [0x11][JSON(TransferContext)]

TransferContext Structure:

{
"l1owner": "0x1234567890123456789012345678901234567890",
"to": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"token": "2",
"value": "1000.0", // Amount
}

TransferContext Fields:

FieldTypeMandatoryDescription
l1ownerSTRINGYESWallet address initiating the transfer (master wallet address)
toSTRINGYESDestination wallet address
tokenSTRINGYESToken ID to transfer
valueSTRINGYESAmount to transfer

Request Body:

{
"tx": "0x02f8730183...{full signed transaction hex}"
}

Response:

{
"code": 200,
"errMsg": "OK",
"result": "0x4c9980c4fd003e9aae2e7a8a87812382c84a695614225e423aaf1676089dbbfe"
}

Building and Signing Transactions

Fixed Contract Address

ALL transactions MUST be sent to:

0x00000000000000000000000000000000000000cc

Input Data Construction

The transaction's data field consists of:

  1. Command Byte (1 byte): Identifies the operation type
  2. JSON Data (remaining bytes): UTF-8 encoded JSON string with operation parameters

L2 Gas-Free Transactions

Important: The Kaia L2 DEX supports gas-free transactions, meaning:

  • Gas Price: Set to 0 (zero) for all transactions
  • Gas Limit: Use a sufficiently large arbitrary value (e.g., 0x30000 or 196608)
  • Value: Always 0x0 for DEX operations
  • Users don't need to hold native tokens for gas fees

Example: Building Order Transaction

// 1. Create OrderContext
const orderContext = {
l1owner: walletAddress,
baseToken: "1",
quoteToken: "2",
side: 0, // buy
price: "2.3",
quantity: "10.0",
orderType: 0, // limit
orderMode: 0 // base mode
};

// 2. Build transaction data
const commandByte = 0x21; // DexCommandOrder
const jsonData = JSON.stringify(orderContext);
const data = Buffer.concat([
Buffer.from([commandByte]),
Buffer.from(jsonData)
]);

// 3. Sign transaction (with gas-free parameters)
const tx = {
from: walletAddress,
to: MATCH_ENGINE_ADDRESS,
data: '0x' + data.toString('hex'),
value: '0x0', // Always 0 for DEX operations
gasLimit: '0x30000', // Arbitrary large value
gasPrice: '0x0', // Gas-free: set to 0
nonce: Date.now() // Can use timeNonce (Unix timestamp in ms) or sequential nonce
};

const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey);

// 4. Send to API
const response = await fetch('/api/v1/order', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tx: signedTx.rawTransaction })
});

Important Notes

  1. Transaction Target: All order transactions must be sent to the Match Engine contract address

  2. Order Mode:

    • Base mode (0): Quantity specified in base token
    • Quote mode (1): Quantity specified in quote token (only available for market orders, useful for market buy orders where you want to specify the amount in quote token)
  3. Gas Estimation: Recommended gas limit is 0x30000 (196,608) for most operations

  4. Nonce Management:

    • Standard sequential nonces are supported
    • TimeNonce Support: You can use Unix timestamp in milliseconds as the nonce value
    • TimeNonce allows parallel transaction submission without nonce conflicts
    • Example: Use Date.now() (returns milliseconds) as the nonce value
  5. TPSL Orders: Take Profit and Stop Loss can be attached to any limit order via the optional tpsl field

  6. Null Values: In modify operations, set fields to null to keep current values unchanged