> For the complete documentation index, see [llms.txt](https://docs.unix.market/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.unix.market/authentication/end-to-end-example.md).

# End To End Example

This page shows one complete example for each signing method.

|                  | Method A — ActionHash                                               | Method B — Typed Data Direct Sign      |
| ---------------- | ------------------------------------------------------------------- | -------------------------------------- |
| Example          | Place a limit order                                                 | Approve an Agent Key                   |
| Used by          | Trading, trading-related account settings, transfer, withdrawal     | Agent management, sub-account creation |
| Signing shape    | Business params -> canonical JSON -> `actionHash` -> `Agent` struct | Operation-specific typed struct        |
| `target_address` | Supported                                                           | Not used                               |

Both methods use the same EIP-712 Domain, nonce rules, expiration rules, and ECDSA signature shape.

## Shared Field Map

| HTTP field       | EIP-712 field   | Meaning                                                                                            |
| ---------------- | --------------- | -------------------------------------------------------------------------------------------------- |
| `signer_address` | `signerAddress` | Signer address. The node recovers the signer from `signature` and requires it to match this value. |
| `target_address` | `targetAddress` | Optional Method A target account. If omitted, the request targets `signer_address`.                |
| `nonce`          | `nonce`         | Millisecond timestamp used for replay protection.                                                  |
| `expires_after`  | `expiresAfter`  | Millisecond expiration timestamp.                                                                  |
| `signature`      | -               | ECDSA result `{ r, s, v }`; submitted for verification and not included as a signed field.         |

Shared EIP-712 Domain:

```json
{
  "name": "UniX",
  "version": "1",
  "chainId": 1,
  "verifyingContract": "0x0000000000000000000000000000000000000000"
}
```

## Method A — Place A Limit Order

**Scenario:** place a limit buy order.

**Endpoint:** `POST /v1/trade/orders`

**Action Tag:** `7`

{% stepper %}
{% step %}

## Business Parameters

```json
{
  "symbol_id": 100001,
  "is_buy": true,
  "order_type": "limit",
  "time_in_force": "gtc",
  "quantity": "1.0",
  "price": "67500.00",
  "position_side": "both",
  "margin_mode": "cross"
}
```

Only business parameters are used for canonical JSON. Public signing fields are added later.
{% endstep %}

{% step %}

## Compute `actionHash`

```python
import json
from web3 import Web3

action = {
    "symbol_id": 100001,
    "is_buy": True,
    "order_type": "limit",
    "time_in_force": "gtc",
    "quantity": "1.0",
    "price": "67500.00",
    "position_side": "both",
    "margin_mode": "cross",
}

canonical = json.dumps(action, sort_keys=True, separators=(",", ":")).encode()
action_hash = Web3.keccak(bytes([7]) + canonical)
```

Canonical JSON for this request:

```json
{"is_buy":true,"margin_mode":"cross","order_type":"limit","position_side":"both","price":"67500.00","quantity":"1.0","symbol_id":100001,"time_in_force":"gtc"}
```

{% endstep %}

{% step %}

## Sign The `Agent` Struct

This example does not use `target_address`, so it signs:

```
Agent(address signerAddress,bytes32 actionHash,uint64 nonce,uint64 expiresAfter)
```

```python
import time
from eth_account import Account
from eth_account.messages import encode_typed_data

nonce = int(time.time() * 1000)
expires_after = nonce + 600_000

domain = {
    "name": "UniX",
    "version": "1",
    "chainId": 1,
    "verifyingContract": "0x0000000000000000000000000000000000000000",
}
types = {"Agent": [
    {"name": "signerAddress", "type": "address"},
    {"name": "actionHash", "type": "bytes32"},
    {"name": "nonce", "type": "uint64"},
    {"name": "expiresAfter", "type": "uint64"},
]}
message = {
    "signerAddress": "0xYOUR_ADDRESS",
    "actionHash": action_hash,
    "nonce": nonce,
    "expiresAfter": expires_after,
}

signed = Account.sign_message(
    encode_typed_data(domain, types, "Agent", message),
    private_key="0xYOUR_PRIVATE_KEY",
)
```

{% endstep %}

{% step %}

## Submit The Request

```python
import requests

resp = requests.post("https://api.unixtrade.pro/v1/trade/orders", json={
    **action,
    "signer_address": "0xYOUR_ADDRESS",
    "nonce": nonce,
    "expires_after": expires_after,
    "signature": {"r": hex(signed.r), "s": hex(signed.s), "v": signed.v},
})
print(resp.json())
```

The node rejects the request unless `ecrecover(signing_hash, signature)` equals `signer_address`.
{% endstep %}

{% step %}

## Response Shape

```json
{
  "code": "0",
  "msg": "",
  "data": {
    "tx_hash": "0x9e581b06f35cb6c44f4b8e3f7e2d1c0b9a8f7e6d5c4b3a2918273645f6e5d4c3",
    "order_id": "144115188075855872",
    "client_order_id": null
  },
  "trace_code": ""
}
```

`tx_hash` is the same value as `signing_hash`.
{% endstep %}
{% endstepper %}

## Method B — Approve An Agent Key

**Scenario:** authorize a separate Agent Key for trading automation.

**Endpoint:** `POST /v1/account/approve-agent`

**Signer:** user private key. Agent Keys cannot sign Agent management requests.

{% stepper %}
{% step %}

## Business Parameters

```json
{
  "agent_address": "0xAGENT_ADDRESS",
  "authorized_address": "0xYOUR_ADDRESS",
  "valid_days": 30,
  "label": "mm-bot-prod"
}
```

When `authorized_address` is the signer's main account, the Agent can operate on the main account and its sub-accounts.
{% endstep %}

{% step %}

## Sign `ApproveAgent`

```
ApproveAgent(address signerAddress,address agentAddress,address authorizedAddress,uint32 validDays,string label,uint64 nonce,uint64 expiresAfter)
```

```python
import time
from eth_account import Account
from eth_account.messages import encode_typed_data

nonce = int(time.time() * 1000)
expires_after = nonce + 600_000

domain = {
    "name": "UniX",
    "version": "1",
    "chainId": 1,
    "verifyingContract": "0x0000000000000000000000000000000000000000",
}
types = {"ApproveAgent": [
    {"name": "signerAddress", "type": "address"},
    {"name": "agentAddress", "type": "address"},
    {"name": "authorizedAddress", "type": "address"},
    {"name": "validDays", "type": "uint32"},
    {"name": "label", "type": "string"},
    {"name": "nonce", "type": "uint64"},
    {"name": "expiresAfter", "type": "uint64"},
]}
message = {
    "signerAddress": "0xYOUR_ADDRESS",
    "agentAddress": "0xAGENT_ADDRESS",
    "authorizedAddress": "0xYOUR_ADDRESS",
    "validDays": 30,
    "label": "mm-bot-prod",
    "nonce": nonce,
    "expiresAfter": expires_after,
}

signed = Account.sign_message(
    encode_typed_data(domain, types, "ApproveAgent", message),
    private_key="0xYOUR_PRIVATE_KEY",
)
```

{% endstep %}

{% step %}

## Submit The Request

```python
import requests

resp = requests.post("https://api.unixtrade.pro/v1/account/approve-agent", json={
    "agent_address": "0xAGENT_ADDRESS",
    "authorized_address": "0xYOUR_ADDRESS",
    "valid_days": 30,
    "label": "mm-bot-prod",
    "signer_address": "0xYOUR_ADDRESS",
    "nonce": nonce,
    "expires_after": expires_after,
    "signature": {"r": hex(signed.r), "s": hex(signed.s), "v": signed.v},
})
print(resp.json())
```

{% endstep %}

{% step %}

## Response Shape

```json
{
  "code": "0",
  "msg": "",
  "data": {
    "tx_hash": "0x4f3c2b1a09f8e7d6c5b4a3928170655443322110ffeeddccbbaa99887766554",
    "agent_address": "0xAGENT_ADDRESS",
    "label": "mm-bot-prod",
    "authorized_address": "0xYOUR_ADDRESS",
    "valid_days": 30,
    "expires_at": 1722192000000,
    "replaced_agent_address": null
  },
  "trace_code": ""
}
```

`replaced_agent_address` is non-null only when the label already existed and the old Agent was replaced.
{% endstep %}
{% endstepper %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.unix.market/authentication/end-to-end-example.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
