# 工具函数

`@arcblock/did-connect-react` 库导出了一系列工具函数，旨在简化与身份验证流程、数据处理和 API 通信相关的常见任务。虽然核心组件和钩子处理了大多数用例，但这些工具为高级集成或自定义实现提供了精细的控制。

## API 客户端

### createAxios

该函数是一个用于创建预配置 `axios` 实例的工厂。它会自动包含必要的头信息，如 `x-did-connect-version` 和 `x-blocklet-visitor-id`，以确保与基于 Blocklet 的服务正常通信。这是在你的应用程序中创建 API 客户端的推荐方法。

**参数**

<x-field-group>
  <x-field data-name="options" data-type="object" data-required="false" data-desc="标准的 Axios 配置对象。"></x-field>
  <x-field data-name="lazyOptions" data-type="object" data-required="false" data-desc="懒发送的配置。">
    <x-field data-name="lazy" data-type="boolean" data-default="false" data-desc="是否启用懒发送。"></x-field>
    <x-field data-name="lazyTime" data-type="number" data-default="300" data-desc="懒发送的防抖时间（毫秒）。"></x-field>
  </x-field>
</x-field-group>

**返回值**

<x-field data-name="axiosInstance" data-type="AxiosInstance" data-desc="一个已配置的 Axios 实例。"></x-field>

**示例**

```javascript apiClient.js icon=logos:javascript
import { createAxios } from '@arcblock/did-connect-react/lib/utils';

const apiClient = createAxios({
  baseURL: '/api',
});

export default apiClient;
```

## URL 和弹窗处理

这些函数帮助管理在 DID Connect 身份验证过程中使用的 URL 和弹窗。

| 函数 | 描述 |
| :--- | :--- |
| `encodeConnectUrl(url)` | 对 URL 进行编码，以便安全地作为 `__connect_url__` 查询参数传递。 |
| `decodeConnectUrl(encoded)` | 解码由 `encodeConnectUrl` 编码的 URL。 |
| `parseTokenFromConnectUrl(connectUrl)` | 从 DID Connect URL 中提取会话令牌 (`_t_`)。 |
| `openPopup(url, options)` | 打开一个新的、居中的弹窗。它由 `DidConnect` 组件内部使用，以显示钱包连接界面。如果弹窗被阻止，则会抛出 `NotOpenError`。 |
| `runPopup(config)` | 一个基于 Promise 的包装器，用于管理由 `openPopup` 创建的弹窗的生命周期。它监听来自弹窗的 `message` 事件，处理超时，并在身份验证流程完成时解析。 |
| `decodeUrlParams()` | 从当前窗口的 URL 中解析自定义的 `__did-connect__` 参数。 |

**示例：自定义弹窗流程**

```javascript customAuthButton.js icon=logos:javascript
import { openPopup, runPopup } from '@arcblock/did-connect-react/lib/utils';

const handleCustomLogin = async () => {
  const authUrl = 'https://your-auth-service.com/connect';
  try {
    const popup = openPopup(authUrl);
    const result = await runPopup({ popup, timeoutInSeconds: 600 });
    console.log('Authentication successful:', result);
    // Handle successful login
  } catch (error) {
    console.error('Authentication failed:', error.message);
    // Handle popup closed or timeout
  }
};
```

## 会话和 Cookie 管理

这些辅助函数用于向 Cookie 读写用户连接信息，从而实现跨页面加载的会话持久性。

| 函数 | 描述 |
| :--- | :--- |
| `getConnectedInfo(data)` | 将连接请求的原始响应数据格式化为适合 Cookie 存储的标准化对象。 |
| `updateConnectedInfo(info, parsed)` | 在成功连接后设置必要的 Cookie (`connected_did`, `connected_pk`, `connected_app`)。这使得库可以优化后续的身份验证检查。 |
| `getVisitorId()` | 从 Cookie 中检索唯一访客 ID。 |
| `setVisitorId(id)` | 在 Cookie 中设置唯一访客 ID。 |

**示例**

```javascript sessionManager.js icon=logos:javascript
import { getConnectedInfo, updateConnectedInfo } from '@arcblock/did-connect-react/lib/utils';

// Assuming 'authResponse' is the object returned from your login API
function persistSession(authResponse) {
  const connectedInfo = getConnectedInfo(authResponse);
  updateConnectedInfo(connectedInfo, true);
  console.log('Session info saved to cookies.');
}
```

## 加密工具

对于需要客户端加密或解密的高级场景，该库公开了包装 `tweetnacl-sealedbox-js` 库的辅助函数。

| 函数 | 描述 |
| :--- | :--- |
| `encodeKey(key)` | 对密钥进行 Base64URL 编码以便传输。 |
| `decodeKey(str)` | 将 Base64URL 字符串解码为 `Uint8Array` 密钥。 |
| `encrypt(value, encryptKey)` | 使用公钥加密字符串值。 |
| `decrypt(value, encryptKey, decryptKey)` | 使用相应的公钥和私钥解密 base64 字符串。 |

## 错误处理

为了向用户提供更好的反馈，你可以使用这些函数将技术性错误对象解析为人类可读的消息。

| 函数 | 描述 |
| :--- | :--- |
| `getApiErrorMessage(err, defaultMessage)` | 从 `axios` 错误对象中提取用户友好的错误消息。 |
| `getWebAuthnErrorMessage(err, defaultMessage, t)` | 处理 WebAuthn/Passkey 特定错误（例如，用户取消、浏览器不支持），并返回本地化的、用户友好的消息。 |

**示例**

```javascript errorHandling.js icon=logos:javascript
import { getApiErrorMessage } from '@arcblock/did-connect-react/lib/utils';
import apiClient from './apiClient';

async function fetchData() {
  try {
    const response = await apiClient.get('/data');
    return response.data;
  } catch (error) {
    const message = getApiErrorMessage(error, 'Failed to fetch data.');
    alert(message);
  }
}
```

---

通过利用这些工具，你可以构建更复杂和定制化的身份验证体验。有关所有导出成员及其类型的完整列表，请参阅 [API 参考](./api-reference.md)。