For the complete documentation index, see llms.txt. This page is also available as Markdown.

Builder Code

Builder Code lets a registered Builder place orders for a Trader after the Trader explicitly authorizes that Builder's agent wallet. The Builder never receives the Trader's private key.

Integration flow:

  1. The Builder master wallet calls registerBuilder once.

  2. Each Trader master wallet calls approveAgentToBuilder with the Builder agent address and fee cap.

  3. The Builder agent calls placeBuilderOrder or placeBuilderBracketOrder for that Trader.

  4. The Trader master wallet calls revokeAgentToBuilder to end the authorization.

Start here: Python full lifecycle example · JavaScript full lifecycle example.

Use the SDKs unless you need a raw REST integration. The SDKs create protobuf bytes and EIP-712 signatures for you.

Register Builder

post
/exchange/registerBuilder

Register the Builder master wallet once. Submit action.type=registerBuilder to POST /api/v1/exchange.

Signer: Builder master wallet · EIP-712 primary type: RegisterBuilder

Runnable examples: Python register Builder · JavaScript register Builder

Raw signing. EIP-712 is a wallet typed-data signature, not a signature of the JSON request string. Sign this exact typed-data payload with the Builder master wallet. Use chainId 421614 for Testnet or 42161 for Mainnet; when expiryAfter is omitted in the request, sign it as 0.

{
  "types": {
    "EIP712Domain": [
      { "name": "name", "type": "string" },
      { "name": "version", "type": "string" },
      { "name": "chainId", "type": "uint256" },
      { "name": "verifyingContract", "type": "address" }
    ],
    "RegisterBuilder": [
      { "name": "dexChain", "type": "string" },
      { "name": "name", "type": "string" },
      { "name": "nonce", "type": "uint64" },
      { "name": "expiryAfter", "type": "uint64" }
    ]
  },
  "primaryType": "RegisterBuilder",
  "domain": {
    "name": "SignTransaction",
    "version": "1",
    "chainId": 421614,
    "verifyingContract": "0x0100000000000000000000000000000000000001"
  },
  "message": {
    "dexChain": "Testnet",
    "name": "example-builder",
    "nonce": 1763023626904,
    "expiryAfter": 1763023926904
  }
}
Body
nonceinteger · int64Required
expiryAfterinteger · int64 · nullableOptional

Sign 0 when omitted or null.

Responses
200

Transaction submitted

application/json
codeintegerOptional

0 = success. See Error Codes section for non-zero values.

Example: 0
messagestringOptional
post/exchange/registerBuilder
result = client.exchange.register_builder("example-builder")
# See the linked runnable example above.
200

Transaction submitted

{
  "code": 0,
  "message": "success",
  "data": {
    "txHash": "0xabc...",
    "txCode": 0,
    "txMsg": ""
  }
}

Authorize Builder Agent

post
/exchange/approveAgentToBuilder

Submit action.type=approveAgentToBuilder to POST /api/v1/exchange. The Trader master wallet authorizes the Builder agent address, not the Trader's own agent. maxFeeRate is a positive decimal string and must not exceed the environment-configured Builder fee cap.

Signer: Trader master wallet · EIP-712 primary type: ApproveAgentToBuilder

Runnable examples: Python full lifecycle · JavaScript approve Builder agent

Raw signing. Sign the following EIP-712 typed-data payload with the Trader master wallet. agentAddress is the Builder's agent address, builderAddress is the Builder's master address, and expiryAfter must be signed as 0 when omitted.

{
  "types": {
    "ApproveAgentToBuilder": [
      { "name": "dexChain", "type": "string" },
      { "name": "agentAddress", "type": "address" },
      { "name": "builderAddress", "type": "address" },
      { "name": "maxFeeRate", "type": "string" },
      { "name": "validitySeconds", "type": "uint64" },
      { "name": "nonce", "type": "uint64" },
      { "name": "expiryAfter", "type": "uint64" }
    ]
  },
  "primaryType": "ApproveAgentToBuilder",
  "domain": { "name": "SignTransaction", "version": "1", "chainId": 421614, "verifyingContract": "0x0100000000000000000000000000000000000001" },
  "message": {
    "dexChain": "Testnet",
    "agentAddress": "0x<builder-agent-address>",
    "builderAddress": "0x<builder-master-address>",
    "maxFeeRate": "0.0002",
    "validitySeconds": 3600,
    "nonce": 1763023626904,
    "expiryAfter": 1763023926904
  }
}
Body
nonceinteger · int64Required
expiryAfterinteger · int64 · nullableOptional

Sign 0 when omitted or null.

Responses
200

Transaction submitted

application/json
codeintegerOptional

0 = success. See Error Codes section for non-zero values.

Example: 0
messagestringOptional
post/exchange/approveAgentToBuilder
trader.exchange.approve_agent_to_builder(
    builder.wallet.master_address, "0.0002", 3600,
    agent_address=builder.wallet.agent_address,
)
# See the linked runnable example above.
200

Transaction submitted

{
  "code": 0,
  "message": "success",
  "data": {
    "txHash": "0xabc...",
    "txCode": 0,
    "txMsg": ""
  }
}

Revoke Builder Agent Authorization

post
/exchange/revokeAgentToBuilder

Submit action.type=revokeAgentToBuilder to POST /api/v1/exchange. The authorization is resolved from the Trader master signature; no Builder or agent address is included in the action.

Signer: Trader master wallet · EIP-712 primary type: RevokeAgentToBuilder

Runnable examples: Python revoke Builder authorization · JavaScript revoke Builder authorization

Raw signing. Sign this EIP-712 typed-data payload with the Trader master wallet. The server resolves the Builder and agent from the Trader's active authorization; do not add those addresses to the action.

{
  "types": {
    "RevokeAgentToBuilder": [
      { "name": "dexChain", "type": "string" },
      { "name": "nonce", "type": "uint64" },
      { "name": "expiryAfter", "type": "uint64" }
    ]
  },
  "primaryType": "RevokeAgentToBuilder",
  "domain": { "name": "SignTransaction", "version": "1", "chainId": 421614, "verifyingContract": "0x0100000000000000000000000000000000000001" },
  "message": {
    "dexChain": "Testnet",
    "nonce": 1763023626904,
    "expiryAfter": 1763023926904
  }
}
Body
nonceinteger · int64Required
expiryAfterinteger · int64 · nullableOptional

Sign 0 when omitted or null.

Responses
200

Transaction submitted

application/json
codeintegerOptional

0 = success. See Error Codes section for non-zero values.

Example: 0
messagestringOptional
post/exchange/revokeAgentToBuilder
result = trader.exchange.revoke_agent_to_builder()
# See the linked runnable example above.
200

Transaction submitted

{
  "code": 0,
  "message": "success",
  "data": {
    "txHash": "0xabc...",
    "txCode": 0,
    "txMsg": ""
  }
}

Place Builder Order

post
/exchange/placeBuilderOrder

Submit action.type=placeBuilderOrder to POST /api/v1/exchange after the Trader authorizes the Builder agent. builderFeeRate must be a non-negative decimal string and must not exceed the Trader authorization's maxFeeRate.

Signer: Builder agent · Protobuf: MsgPlaceBuilderOrder

Runnable examples: Python full lifecycle · JavaScript place Builder order

Raw signing. Serialize this message using proto3, then calculate connectionId = keccak256(proto_bytes + bytes(vaultAddress) + little_endian_uint64(nonce) + little_endian_uint64(expiryAfter)). Use empty bytes for an omitted vaultAddress and 0 for an omitted expiryAfter. The Builder agent then signs this EIP-712 typed-data payload. Use source "b" on Testnet or "a" on Mainnet.

{
  "types": {
    "Agent": [
      { "name": "source", "type": "string" },
      { "name": "connectionId", "type": "bytes32" }
    ]
  },
  "primaryType": "Agent",
  "domain": { "name": "Exchange", "version": "1", "chainId": 421614, "verifyingContract": "0x0100000000000000000000000000000000000001" },
  "message": { "source": "b", "connectionId": "0x<keccak256-result>" }
}
message MsgPlaceBuilderOrder {
  int64 cl_ord_id = 1;
  int64 symbol_code = 2;
  string ord_px = 3;
  string ord_qty = 4;
  string trigger_px = 5;
  OrdType ord_type = 6;
  OrdSide ord_side = 7;
  OrdTIF time_in_force = 8;
  ReduceOnlyOption reduce_only_option = 9;
  int64 parent_ord_id = 10;
  ConditionalOrdTriggerType tpsl_trigger_type = 11;
  string slippage_pct = 12;
  string builder_addr = 13;
  string builder_fee_rate = 14;
}
Body
nonceinteger · int64Required
expiryAfterinteger · int64 · nullableOptional

Use 0 in the L1 connection ID when omitted or null.

vaultAddressstring · nullableOptional
Responses
200

Transaction submitted

application/json
codeintegerOptional

0 = success. See Error Codes section for non-zero values.

Example: 0
messagestringOptional
post/exchange/placeBuilderOrder
result = builder.exchange.place_builder_order(
    symbol_code=1, px="65000", qty="0.001",
    builder=builder.wallet.master_address, builder_fee_rate="0.0002",
)
# See the linked runnable example above.
200

Transaction submitted

{
  "code": 0,
  "message": "success",
  "data": {
    "txHash": "0xabc...",
    "txCode": 0,
    "txMsg": ""
  }
}

Place Builder Bracket Order

post
/exchange/placeBuilderBracketOrder

Submit 2 or 3 orders with action.type=placeBuilderBracketOrder to POST /api/v1/exchange. The first order is the main order; remaining orders must be TP (TP_FROM_POSITION) or SL (SL_FROM_POSITION).

Signer: Builder agent · Protobuf: MsgPlaceBuilderBracketOrder

Runnable examples: Python full lifecycle · JavaScript full lifecycle

Raw signing. Each child order is a MsgPlaceBuilderOrder with the builder_addr = 13 and builder_fee_rate = 14 fields shown above. Serialize the wrapper below and use the same Builder-agent Agent EIP-712 signing process as placeBuilderOrder.

message MsgPlaceBuilderBracketOrder {
  MsgPlaceBuilderOrder main_order = 1;
  MsgPlaceBuilderOrder take_profit_order = 2;
  MsgPlaceBuilderOrder stop_loss_order = 3;
}
Body
nonceinteger · int64Required
expiryAfterinteger · int64 · nullableOptional

Use 0 in the L1 connection ID when omitted or null.

vaultAddressstring · nullableOptional
Responses
200

Transaction submitted

application/json
codeintegerOptional

0 = success. See Error Codes section for non-zero values.

Example: 0
messagestringOptional
post/exchange/placeBuilderBracketOrder
result = builder.exchange.place_builder_bracket_order(
    [main_order, take_profit_order, stop_loss_order],
    builder.wallet.master_address, "0.0002",
)
# See the linked runnable example above.
200

Transaction submitted

{
  "code": 0,
  "message": "success",
  "data": {
    "txHash": "0xabc...",
    "txCode": 0,
    "txMsg": ""
  }
}

Last updated