> ## Documentation Index
> Fetch the complete documentation index at: https://docs.li.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# 概念

> 每一次修改类调用背后的创建、授权、执行模式，谁签署什么，以及交易场所凭证存放在哪里。

三个概念可以解释 SDK 的大部分行为：每个修改类操作都是一条三阶段流水线；授权在用户和 SDK 之间划分；每个交易场所的凭证都存放在一个可替换的存储适配器背后。

## 创建、授权、执行

订单、取消、设置和提款都运行相同的流水线。

<Steps>
  <Step title="创建" icon="file-pen">
    你发送交易场所、账户、操作类型及其参数。后端返回一个步骤数组。一次调用可能返回多个步骤：例如在下单前提高杠杆，会依次返回两个步骤。
  </Step>

  <Step title="授权" icon="key">
    每个步骤恰好携带一个授权载荷，具体由该步骤的签名方式决定：可以由用户的钱包签署，也可以由 SDK 用它为该账户持有的凭证签署。
  </Step>

  <Step title="执行" icon="paper-plane">
    已签名的步骤被送回，响应中每个步骤对应一条结果。成功时携带交易场所的标识符；失败时携带一个错误，通常还带有结构化的错误码。
  </Step>
</Steps>

各步骤类型的区别在于授权时需要产出什么：

| 步骤携带的内容   | 授权方式                   |
| --------- | ---------------------- |
| 类型化数据     | 一个 EIP-712 签名          |
| 一个签名 blob | 交易场所自身的签名方             |
| 交易参数      | 一笔钱包提交的交易              |
| 一个请求      | 针对确切请求字节计算出的签名         |
| 一个登录挑战    | 针对用户地址的个人签名挑战          |
| 一个会话请求    | 由交易场所插件在客户端直接完成，无需执行往返 |

最后一种是这个模式的例外。会话步骤永远不会进入执行阶段，因为插件会直接完成它。

<Warning>
  不要根据交易场所名称推断凭证类型。授权方式由 SDK 和已注册的插件决定，同一个交易场所针对不同操作也可能返回不同的步骤类型。请根据步骤本身分支处理，而不是根据交易场所。
</Warning>

## 谁来签名

每个操作都会声明由谁授权，答案只有两种。

**用户**授权任何授予某项能力或转出资金的操作：批准代理、存款、登录，以及部分交易场所上的提款。这些会调用钱包。

**SDK** 使用它为该账户在该交易场所持有的凭证来授权交易。这就是为什么下单流程不会弹出钱包——凭证是在设置阶段由用户的一次操作授予的。

有些操作会同时列出两者，因为协议需要双方各自贡献一部分。高层交易方法会自动处理由 SDK 签名的那一半，无需你手动请求；设置流程也是由单次调用端到端统一协调的，而不需要你为每个交易场所的方案分别编写脚本。

## 凭证存放在哪里

每个交易场所的插件通过一个存储适配器持久化各自的交易凭证，该适配器是可替换的。

默认实现面向浏览器。值在写入本地存储前会被加密，而用于加密的密钥则作为一个不可导出的句柄保存在浏览器自身的密钥库中，而不是页面可以读回的一个值。如果运行环境缺少这两种能力中的任意一种，会回退到一个不持久化的会话，而不是以明文写出凭证。

<Note>
  可以为某个交易场所的存储传入你自己的适配器，将凭证保存在别处。这是服务端或原生集成的推荐做法，此时浏览器的默认实现并不适用。
</Note>

实际影响是：清除了站点数据的用户需要重新完成设置。这是一个可以接受的结果，但你的界面应该识别并展示这一点，而不是将其当作交易错误呈现出来。

## 推送数据

行情和账户更新通过直接建立到交易场所本身（而非经过代理）的 WebSocket 连接送达。你为每个交易场所注册一个推送提供方，订阅会返回一个用于取消订阅的函数。

同一通道上的多个监听者共享同一条底层连接，因此各组件可以各自独立订阅，而不必每次都新开一条连接。每个交易场所底层都有自己的原生协议和速率限制，由插件将其映射到统一的通道名称上。

## 失败处理

结果按步骤逐一返回，这意味着一个多步骤操作可能部分成功。例如在下单前先调整杠杆，可能出现杠杆调整已生效但订单被拒绝的情况；如果把整次调用当作整体失败处理，就会误报这一结果。

应该以结构化错误码作为分支判断的依据。插件也可能在结果传递给你之前就先做出反应，这也是为什么一个已被交易场所停止接受的凭证会在本地被自动清除，而不是导致后续每一笔订单都以相同方式失败。

## 后续步骤

<CardGroup cols={2}>
  <Card title="交易场所" icon="building-columns" href="/perps/venues" horizontal>
    每个交易场所如何实现设置、签名和提款。
  </Card>

  <Card title="快速开始" icon="rocket" href="/perps/quickstart" horizontal>
    以上流水线对应的实际代码。
  </Card>

  <Card title="错误码" icon="triangle-exclamation" href="https://public-perps-docs.mintlify.app/error-codes" horizontal>
    完整的错误码列表及其含义。
  </Card>

  <Card title="方法参考" icon="book" href="https://public-perps-docs.mintlify.app/" horizontal>
    每个方法的参数和返回结构。
  </Card>
</CardGroup>
