> For the complete documentation index, see [llms.txt](https://docs.nexus.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nexus.xyz/api-reference/zh-cn/guides/networks.md).

# 网络

每个 Nexus Exchange 接口如何选择网络：测试网、主网、本地，或由您自行描述的自定义目标。

每个 Nexus Exchange 接口都只与一个**网络**通信，该网络在构造客户端时选定。网络不是发布渠道，它决定的是谁的资金面临风险。**测试网**使用合成的模拟资金，**主网**将使用真实资金，**本地**用于开发。选择一个网络，就会把它们之间所有不同的部分打包在一起：REST 和 WebSocket 目标、是否提供水龙头，以及您的请求所限定的签名域。您选择的是网络，而不是自己拼接 URL。当前的基础 URL 请参见 [API 与速率限制](https://docs.nexus.xyz/exchange/apis-and-rates)。

以上三个是已发布的网络。您自行运行的部署属于 [`Custom` 网络](#the-custom-network)。它包含同样的一组配置，只是由您来描述，而不是由客户端解析。

### 三个已发布的网络

| 网络        | 资金                     | 水龙头 | 可用性                         |
| --------- | ---------------------- | --- | --------------------------- |
| `testnet` | 合成 USDX，没有现实价值         | 有   | 现已上线。所有接口的默认网络。             |
| `mainnet` | 真实资金，即从以太坊主网跨链而来的 USDX | 无   | 将随真实资金交易所一同上线。目前尚无法访问，详见下文。 |
| `local`   | 合成资金，连接您自行运行的索引器       | 有   | 用于本地开发。不是公共网络。              |

测试网在所有地方都是默认网络，这是有意为之，因为默认使用真实资金并不安全。

**主网目前尚无法访问**。它的公共主机尚未上线，因此没有任何接口会替您解析主网目标。为了避免把您的请求发到一个看似合理却错误的地方，每个接口都会以故障关闭的方式处理。Python 和 TypeScript 客户端在构造时抛出异常，MCP 服务器拒绝启动。Rust 客户端（以及基于它的 CLI）可以正常构建，但会在本地拒绝每一个请求，不会有任何字节离开进程。唯一的办法是由您自己指定目标。Python、TypeScript 和 MCP 服务器在提供显式基础 URL 时接受 `mainnet`（参见[指向主机但不描述它](#pointing-at-a-host-without-describing-it)），这就是在持久主机上线之前访问真实资金部署的方式。在 Rust 中，覆盖方式是一个完全不带网络的独立构造函数，因此它指向的是一个 URL 而不是主网。没有任何接口会替您猜测真实资金目标，因为这种失败无法预演。主网上线时，本页和各接口的发布说明都会予以说明。

### 选择网络

| 接口         | 选择网络                                                           | 默认值       |
| ---------- | -------------------------------------------------------------- | --------- |
| Python     | `Client(network=Network.TESTNET)`                              | `testnet` |
| TypeScript | `new Client({ network: Network.Testnet })`                     | `testnet` |
| Rust       | `Config::new(Network::Testnet)`                                | `testnet` |
| CLI        | `--network <mainnet\|testnet\|local\|LABEL>`，或 `NEXUS_NETWORK` | `testnet` |
| MCP 服务器    | `NEXUS_EXCHANGE_NETWORK`                                       | `testnet` |

CLI 的 `--network` 还接受在其配置文件中声明的自定义目标的标签，MCP 服务器则接受 `NEXUS_EXCHANGE_NETWORK=custom` 加上一组描述好的配置。参见[描述自定义目标](#describing-a-custom-target)。

无法识别的网络名称始终会报错。没有任何接口会回退到默认值，也没有任何接口会回退到 `local`。在得到证实之前，接口会把未知标识符当作真实资金处理，因此您必须纠正它。已停用的发布渠道名称会被拒绝，并提示其替代名称。`stable` 指的是一个提供测试网服务的主机，因此 `testnet` 是它的直接对应。

### 示例

```python
from nexus_exchange import Client, Network

client = Client(network=Network.TESTNET, api_key=..., api_secret=...)
```

```typescript
import { Client, Network } from "@nexus-xyz/exchange-ts";

const client = new Client({ network: Network.Testnet, apiKey: "…", apiSecret: "…" });
```

```rust
use nexus_exchange::{Config, Network};

let config = Config::new(Network::Testnet);
```

```bash
nexus --network local markets
```

### `Custom` 网络

上面三个是已发布的网络。您自行运行的部署，例如私有预发布环境、预览环境，或运行在您自己基础设施上的索引器，属于 **`Custom` 网络**。它是由您描述的第四类目标，而不是附加在三个网络之一上的 URL。

它之所以是一个网络而不是一个地址，是因为私有部署同样需要命名网络所打包的一切，而 URL 一样也提供不了。`Custom` 包含同样的一组配置，由您提供：

| 配置组成部分                | 由谁提供                                                                                                                |
| --------------------- | ------------------------------------------------------------------------------------------------------------------- |
| **REST 基础地址**         | 您。必填。                                                                                                               |
| **直连 `/api/v1` 基础地址** | 当部署将其与 REST 基础地址分开时，由您提供。默认为 REST 基础地址，单主机部署就是在那里提供该服务。                                                             |
| **WebSocket 源**       | 在允许部署将其单独拆分的接口中，由您提供。Rust SDK 和 CLI 从不推导它，因为推导会把一个流令牌与并非签发它的源配对。参见[字段集说明](#the-two-field-sets-differ-deliberately)。 |
| **资金**                | 您。必填，没有默认值。详见下文。                                                                                                    |
| **水龙头**               | 您。在声明之前视为**不存在**，这样注资调用就不会被路由到并不存在的水龙头。                                                                             |
| **签名域**               | 从该部署的 `GET /metadata` 读取，或由您提供。从不猜测。                                                                                |
| **标签**                | 您。必填，因为它是凭证命名空间。                                                                                                    |

#### 资金是必填的三态值

`funds` 取值为 `real`、`play` 或 `unknown`，并且**没有默认值**。两个布尔答案都不能安全地假定。真实资金交易所的预发布部署表现得就像真实资金，而背后接着生产数据的预览环境，也不会仅仅因为它不是已发布的主机就成了模拟资金。只有运营方才知道。

`unknown` 以**故障关闭**方式处理。这是一个合理的答案，因为您可能确实不知道，如实说明总比猜测好。接口随后会拒绝那些以真实资金为防护条件的操作，而不是放行。如果某个会转移价值的命令或工具在自定义目标上被拒绝，首先要检查的就是 `funds` 是否未声明。

#### 标签是必填的，并且是凭证命名空间

每个 `Custom` 目标都带有一个由调用方选择的标签，限定为 `[A-Za-z0-9._-]`，最多64个字符。`.` 和 `..` 会被直接拒绝。内置网络已经使用的名称（`mainnet`、`testnet`、`local`，以及 `custom` 本身）也会被拒绝：它们在该字符集下是合法的，但以这些名称命名会指向另一个目标的凭证。

标签是您存储的凭证所在命名空间的键，因此在会持久化配置的客户端中，它会进入文件系统。未经校验、包含 `/` 或 `..` 的标签就是路径遍历，它所指向的凭证属于另一个目标。字符集和长度上限在所有接口中都一致，并且每个接口都自行强制执行，而不是继承。MCP 服务器并非基于 Rust SDK 构建，它自带一份该规则。保留名称是唯一尚未统一的部分：Rust SDK 和 CLI 会拒绝内置网络的名称，而 MCP 服务器不会。请选择一个不与其中任何名称冲突的标签，而不要依赖拒绝机制来发现冲突。

标签由您在自己的配置中选择。`dev`、`preview` 和 `example` 都可以。

#### 签名域从不猜测

`Custom` 目标不会从任何地方继承签名域。客户端从该部署自己的 `GET /metadata` 读取 EIP-712 链 ID，或者使用您提供的值。如果两者都没有，它会**拒绝签名**，而不是复用另一个网络的值。

请在遇到之前就理解这条规则，因为相反的失败是静默的。在错误域下生成的签名可能*在另一个网络上有效*。拒绝是唯一安全的做法。

### 指向主机但不描述它

每个接口仍然接受一个裸基础 URL：

| 接口         | 裸基础 URL                                                  |
| ---------- | -------------------------------------------------------- |
| Python     | `base_url=`，直连基础地址另加 `direct_base_url=`                  |
| TypeScript | `baseUrl`                                                |
| Rust       | `Config::with_base_url(…)`，另加 `.with_direct_base_url(…)` |
| CLI        | `--base-url <URL>`，或 `NEXUS_BASE_URL`                    |
| MCP 服务器    | `NEXUS_EXCHANGE_API_URL`                                 |

这是捷径，而不是文档推荐的路径。在 MCP 服务器中，它已被正式弃用：仍可照常使用，但会打印一条指向配置组的提示。裸 URL 会构建一个**资金未声明**且**没有签名域**的 `Custom` 目标，因此以真实资金为防护条件的操作会被拒绝，客户端也不会签名。这足以让您只读地查看某个主机，而且有意设计为不足以在其上交易。

如果不只是读取，请描述目标，而不是只给出地址。

### 描述自定义目标

有两个接口从配置而不是构造函数参数中读取完整的配置组。

**MCP 服务器**。设置 `NEXUS_EXCHANGE_NETWORK=custom`，然后：

| 变量                             | 含义                                         |
| ------------------------------ | ------------------------------------------ |
| `NEXUS_EXCHANGE_API_URL`       | REST 基础地址。必填。                              |
| `NEXUS_EXCHANGE_NETWORK_LABEL` | 标签。必填。                                     |
| `NEXUS_EXCHANGE_FUNDS`         | `real`、`play` 或 `unknown`。必填。              |
| `NEXUS_EXCHANGE_FAUCET`        | 此处是否存在水龙头。不设置表示没有。                         |
| `NEXUS_EXCHANGE_GATEWAY_PATH`  | 网关路径在源下的位置：`/api/exchange`（默认）或 `/`（裸索引器）。 |

在**没有** `NEXUS_EXCHANGE_NETWORK=custom` 的情况下设置其中任何一个都会报错，而不是静默地不起作用。悄悄应用半组配置，会让您误以为自己配置了一项实际并未生效的安全属性。

**CLI**。在其配置文件（`$XDG_CONFIG_HOME/nexus/config.json`，找不到时回退到 `~/.config/nexus/config.json`）的 `custom_networks` 下声明目标，并通过标签选择它：

```json
{
  "custom_networks": {
    "dev": {
      "base_url": "https://exchange.example.com/api/exchange",
      "direct_base_url": "https://api.example.com",
      "funds": "play",
      "ws_url": "wss://stream.example.com",
      "faucet": true
    }
  }
}
```

```bash
nexus --network dev markets
```

一旦您从该部署自己的 `GET /metadata` 读取了 `chain_id`，它也应该写进这个条目。示例有意省略了它，而不是放一个占位值。没有任何哨兵值表示*未知*。CLI 会把您写入的任何数字都当作 EIP-712 域，所以编造的数字会在错误的域下生成签名，而省略它则会得到拒绝。

未声明的标签会报错。CLI 在您选择某个已声明的标签时才校验它，而不是在读取文件时校验，因此一个您没有使用的预发布环境中的错误不会导致其他所有命令都无法运行。

#### 两套字段集有意不同

两个列表互不为子集。共有三处差异：

* **`chain_id` 仅限 CLI。** MCP 服务器从不生成 EIP-712 签名（它使用 HMAC 认证），因此用不到签名域；带上签名域只会多一个可能过时的地方。
* **`gateway_path` 仅限 MCP。** 它与 CLI 的 `direct_base_url` 是同一项设置，只是从另一侧入手。MCP 服务器接受路径并推导出直连基础地址，CLI 则接受直连基础地址，无需路径。
* **`ws_url` 仅限 CLI。** MCP 服务器从网关基础地址推导出 WebSocket 源，API 契约支持这样做，因为流路径不带单独的主机。CLI 接受显式的 WebSocket 源，因为部署可能把流放在不同的主机上。所以，您可以向 CLI 描述一个带有独立 WebSocket 源的自定义目标，但目前还不能向 MCP 服务器这样描述。

### 网络包含哪些内容

选择一个网络会同时解析以下所有内容，这就是为什么它是一个选择而不是多个：

* **REST 基础地址**，用于交易和账户端点。
* **WebSocket 基础地址**，用于公共市场数据和经过认证的流（前提是该接口支持流）。Python SDK 不附带 WebSocket 客户端。在已发布的流主机上线之前，Rust SDK 拒绝在测试网上连接，而不是把流令牌与并非签发它的源配对，因此请在那里提供一个显式的 WebSocket URL。
* **是否存在水龙头**。在已发布的网络中，合成注资仅限测试网和本地，主网没有。自定义目标自行声明是否有水龙头，在声明之前视为没有。
* **余额是否为真实资金**。这是在执行任何不可逆操作之前用于分支判断的单一标志，而不是靠匹配主机名。
* **EIP-712 签名域**，它将代理注册限定在该网络内。服务器是其链 ID 的权威来源，因此请从您所连接网络的 `GET /metadata` 中读取。无法获取链 ID 的客户端会拒绝签名，而不是复用其他地方的值。

### 凭证与网络隔离

会话令牌、HMAC API 密钥和代理注册都是**按网络**签发的，在其他任何网络上都无效。为某个网络配置的密钥无法在另一个网络上通过认证，因此在测试网上泄露的凭证无法为真实资金签名。

客户端在其整个生命周期内都绑定于其网络，并且没有 setter。切换网络意味着使用该网络自己的凭证构造一个新客户端，并且绝不跨网络沿用签名、nonce 或代理注册。

CLI **按网络**存储凭证，以网络名称为键。对于自定义目标，它以标签而非 URL 为键，因此同一主机上的两个预发布环境各自保留独立的凭证。因此，`--network` 会同时选择目标*和*凭证集。它无法签发凭证。切换到一个您尚未设置的网络后，您不会有该网络的已存储密钥，所以请为该网络运行 `nexus setup`，或在命令行上随 `--network` 一起传入其凭证。

#### 是什么把密钥绑定到网络

**签发密钥时所针对的主机**。创建密钥没有网络参数。`POST /keys` 会记录处理该请求的实例所属的网络，此后该密钥只在那里有效。所以，创建密钥时您所指向的基础 URL *就是*绑定决定。没有什么需要设置，也没有什么需要确认。

请围绕以下两个后果做好规划：

* 在指向一个网络时创建密钥，然后在另一个网络上交易，无论之后如何配置客户端，都不可能成功。
* 您打算使用的每个网络都需要一个单独的密钥，分别针对各个网络签发。

#### 网络错误的密钥是什么样子

它看起来和不存在的密钥一模一样：**HTTP 401 Unauthorized**，响应体如下：

```json
{
  "code": "unauthorized"
}
```

该响应与签名错误、未知的密钥 ID 或缺少请求头**刻意无法区分**。被拒绝的密钥不能被识别为“真实存在，但注册在别处”，否则就会让人得以确认一个猜测的密钥 ID 在另一个网络上有效。因此，API 除了“此请求未通过认证”之外不会告诉您任何信息。

**在您更改目标网络之后出现认证失败，原因是网络的可能性远大于密钥被撤销**。在认定密钥已被删除或密钥 secret 丢失之前，请先检查是哪个主机签发了该密钥。响应中没有任何内容会把您引向那里。

#### 按网络绑定之前签发的密钥

在网络绑定机制出现之前创建的密钥不属于任何网络。它们在测试网和本地上仍然可用，这两个网络会把这类密钥收归己有，并在其上记录网络。主网上线时将**不会**接受它们，因为未标记的密钥无法证明其来源。请针对主网签发一个新密钥，而不要指望现有密钥能够沿用。

完整的认证流程（从钱包登录到签名请求）请参见[快速入门](https://docs.nexus.xyz/exchange/trading/quickstart)。

### 相关内容

* [API 与速率限制](https://docs.nexus.xyz/exchange/apis-and-rates)：当前的基础 URL 和速率限制
* [接口概览](/api-reference/zh-cn/readme.md)
* [资产组合与账户状态](/api-reference/zh-cn/guides/portfolio.md)
* [快速入门](https://docs.nexus.xyz/exchange/trading/quickstart)

> **状态**：测试网上的开发预览版。主网尚未上线，目前也无法访问。网络选择器取代了早先的 `{stable, beta, local}` 发布渠道选择器。在生产环境中请固定到已发布的版本，并在升级前查看各接口的发布说明。测试网凭证和余额没有现实价值。


---

# 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, and the optional `goal` query parameter:

```
GET https://docs.nexus.xyz/api-reference/zh-cn/guides/networks.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
