# @asentum/sdk 中文文档

规范地址：https://npmcn.com/package/%40asentum/sdk/

版本：0\.3\.1
npm 元数据更新时间：2026-11-07T14:31:04.953Z
中文译文更新时间：2026-11-07T23:55:25.609Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40asentum/sdk
原文对照：https://npmcn.com/package/%40asentum/sdk/?lang=original
项目主页：https://asentum.com/docs/reference/sdk
源码仓库：https://github.com/asentum-network/sdk

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：314 kB，7 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=18
- 运行依赖：3 个
- 首次发布：2026-05-16T13:33:13.549Z
- 最新版本发布：2026-11-07T14:31:04.764Z
- 近 30 天下载量：1972（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：4（近 12 个月 4 个）

## 中文简介

TypeScript SDK for Asentum:链读取,ase1地址,Dilithium3签名,与块和最后确认的交易,合同和事件. 在Node.js和浏览器中工作.

## 安装

```sh
npm install @asentum/sdk
```

也可以使用：`pnpm add @asentum/sdk`、`yarn add @asentum/sdk`、`bun add @asentum/sdk`

## README

# @ asentum/ sdk (英语)

Asentum 的 SDK 脚本类型 。 读取链条,用 Dilithium3(ML-DSA-65)签名, 发送交易, 跟随它们从“ 块中” 到“ 最终” 合同及其活动。 工作于Node.js 18+和现代浏览器.

以0.8.1为节点的当前.

```bash
npm install @asentum/sdk
```

## 快开始

```ts
import { AsentumClient, AsentumWallet, formatAse } from '@asentum/sdk';

const client = new AsentumClient('https://testnet.asentum.com');

// Reads need no keys
const { finalized, tip } = await client.getHeads();
const bal = await client.getBalance('ase1v0myp2de3dhj3crvkhxqlnjaw2mvp64a9efkpl');
console.log(formatAse(bal.balance), 'ASE at block', tip);

// A wallet signs locally; keys never leave your process
const wallet = AsentumWallet.fromSecretKey(client, SECRET_KEY_HEX, PUBLIC_KEY_HEX);
console.log(wallet.address); // ase1...

const tx = await wallet.sendTransfer({
  to: 'ase1wtc569gfwk87hplaawr46uj4suwsx2wndgf8ue',
  amountWei: 10n ** 18n, // 1 ASE
});
const receipt = await tx.wait();          // in a block, about 2.5 s
if (!receipt.success) throw new Error(receipt.error);
await tx.wait({ until: 'final' });        // final, a few blocks later
```

测试ASE来自空投仪表板(参见"Docs中的"Get Test ASE"). 节点的 `/dev/faucet` 每个公共节点都关闭了.

## 连锁店的事

-   **二头相.** 这个 _提示_ 是最佳链条上最新的块 这个 _定稿_ 高度跟踪了大约3个街区 却从未改变过. `getHeads()` 返回两者.
-   **不接受.** `POST /tx` 回复 `accepted: true` 仅限 意思是节点把交易放入了它的集合. 等着收据.
-   **收款使用情况 `success`**一个布尔人。 没有 `status` 报告 收讫. 交易失败 `success: false` 还有一个 `error` 理由,你觉得呢.
-   **收据默认读取提示.** 收据与 `finalized: false` 实值 很少输给兄弟和交易土地 又是在后面的一个街区。 仅 `finalized: true` 这是永久的.
-   **通讯地址.** SDK接受这个 `ase1...` 或者说 `0x...` 随地而回 ase1 对于它的每个地址表面, 也是节点用六进制回答的地方 (接收、参与、委员会、治理)。 与 小写十六进制, 因此 SDK 在内部转换 ase1 地址 在签署或取景前,合同论据为六分法。 哈什和生字节 保持0xxx(他们没有ase1形式),合同内地址也一样 返回值和事件数据:用 `toAse1` 显示前 他们.
-   **数额** 将 Wei (1 ASE = 10^18 Wei) 作为响应中的十进制字符串.
-   **利率限制.** 公共网关允许大约25个请求每秒 IP 并用 HTML 页面回答 429; 节点限制块并读取 到240分,然后4分一秒。 SDK重试429和5xx 在它抛出之前,先退后退 `RateLimitError`。 。 。 .

## 自动访问

```ts
const client = new AsentumClient(url?, {
  retries: 3,              // retries for 429 / 5xx / network errors
  requestTimeoutMs: 30000,
  fetch,                   // custom fetch, optional
  headers: {},             // e.g. Authorization for a private RPC
});
```

每个方法都采用可选的最后一个参数 `{ signal?: AbortSignal, retries?: number }`。 。 。 .

### 链与保健

| 方法 | 路线 | 回返 |
| --- | --- | --- |
| `getHeads()` | `GET /v3/heads` | `{ finalized: number, tip: number }` |
| `getTipNumber()` 编号 : `getFinalizedNumber()` | `GET /v3/heads` | `number` |
| `getBlockNumber()` | `GET /chain` | 最终高度, `number` |
| `getChainInfo()` | `GET /chain` | 链式 id、 最终高度、 集成池大小、 页眉 |
| `getChainId()` | `GET /chain` | `bigint` (被夹住) |
| `getMetadata()` | `GET /metadata` | EIP-3085 元数据 |
| `getApiInfo()` | `GET /api` | 节点身份 |
| `getGenesis()` | `GET /genesis` | 起源谱 |
| `isHealthy()` | `GET /health` | `boolean` |
| `isReady()` | `GET /ready` | `boolean` (在503上作假;注意节点0.8.1报告即使被搁置也准备就绪,所以请注意 `getHeads()`(中文(简体) ) |

### 账户

| 方法 | 路线 | 回返 |
| --- | --- | --- |
| `getBalance(addr)` | `GET /balance/<addr>` | `{ address, balance, nonce, pendingNonce }` |
| `getNonce(addr, { pending? })` | `GET /balance/<addr>` | `bigint`,默认待决 |
| `getAccount(addr)` | `GET /asentum/account/<addr>` | `{ exists, balance, nonce, codeHash, storageRoot, height }` |
| `getPublicKeyStatus(addr)` | `GET /public-key/<addr>` | `{ recorded, canOmitKey, ... }` |

### 块

| 方法 | 路线 | 回返 |
| --- | --- | --- |
| `getBlock(n, { tip? })` | `GET /block/<n>[?tip=1]` | `Block | null` (单位:千美元)`finalized`,以及 `confirmations`编号 :`auraHash` 在提示块上) |
| `getBlockReceipts(n, { tip? })` | `GET /block/<n>/receipts` | `{ receipts, finalized?, available }` |
| `getRawBlock(n)` | `GET /block-raw/<n>` | SSZ 六进制或 `null` |
| `getFinalizedStatus(h)` | `GET /v3/finalized?height=` | `{ finalized, auraHash? }` |

### 交易和收款

| 方法 | 路线 | 回返 |
| --- | --- | --- |
| `getReceipt(hash, { finalizedOnly? })` | `GET /receipts/<hash>[?tip=0]` | `Receipt | null` (单位:千美元)`success`, (中文(简体) ), `error?`, (中文(简体) ), `finalized`, (中文(简体) ), `confirmations`, (中文(简体) ), `blockHash`, (中文(简体) ), `auraHash?`(中文(简体) ) |
| `waitForReceipt(hash, opts)` | 民意调查 `GET /receipts` | `Receipt` (见下文) |
| `getTransaction(hash)` | `eth_getTransactionByHash` | `EthTransaction | null` |
| `submitRawTx(rawTx)` | `POST /tx` | `{ accepted, reason?, txHash? }` |
| `submitRawTxBatch(rawTxs)` | `POST /tx/batch` | `{ accepted, rejected, total, results }` |

### 合同

| 方法 | 路线 | 回返 |
| --- | --- | --- |
| `viewCall(contract, method, args, { blockTag? })` | `POST /view` | `{ ok, returnValue, reason?, blockNumber, finalized, ... }` |
| `view(contract, method, args, { blockTag? })` | `POST /view` | 返回值; 抛出 `ViewError` |
| `getCode(addr)` 编号 : `getContractSource(addr)` | `eth_getCode` | 十六进制/ 源文本 |
| `getStorageAt(addr, key)` | `eth_getStorageAt` | 存储的文本或 `null` |
| `getLogs({ address, event, fromBlock, toBlock })` | `eth_getLogs` | 已解码 `Log[]` (仅确定区块;10 000个区块以上的区域被分割) |

`blockTag` 实值 `'tip'` (默认; `'latest'` 财务报告和审定财务报表 `'pending'` 表示相同)或 `'finalized'` (单位:千美元)`'safe'`) (中文(简体) ). 没有历史状态读取.

### 验证人、共识、治理

| 方法 | 路线 |
| --- | --- |
| `getValidators()` | `GET /validators` (约260 KB) |
| `getParticipation({ lookback })` | `GET /participation` |
| `getCommittee({ epoch })` | `GET /v3/committee` |
| `getLiveness()` | `GET /consensus/liveness` |
| `getTombstones()` | `GET /slashing/tombstones` |
| `getProposals()` 编号 : `getProposal(id)` | `GET /governance/proposals`, (中文(简体) ), `/governance/proposal/<id>` |
| `getGovernanceLocked(addr)` 编号 : `getGovernanceWithdrawable(addr)` | `GET /governance/locked/<addr>`, (中文(简体) ), `/governance/withdrawable/<addr>` |
| `getGovernanceLibraries()` 编号 : `getGovernanceLibrary(name)` | `GET /governance/libraries`, (中文(简体) ), `/governance/library/<name>` |
| `jsonRpc(method, params)` | `POST /` (任何JSON-RPC方法) |

`faucet()` 已贬值: 它叫 `/dev/faucet`,它只对一个本地 打开它的德文网.

## 阿森通瓦尔特

```ts
const wallet = AsentumWallet.create(client);                    // random key
const wallet2 = AsentumWallet.fromSeed(client, seed32);         // deterministic
const wallet3 = AsentumWallet.fromSecretKey(client, skHex, pkHex);

wallet.address;      // ase1...
wallet.addressHex;   // 0x... lowercase, what contracts see as msg.sender
wallet.secretKeyHex; // back this up like a password
wallet.publicKeyHex;

await wallet.getBalance(); // bigint wei
await wallet.getNonce();   // bigint, the node's pendingNonce
```

### 发送

```ts
await wallet.sendTransfer({ to, amountWei: 10n ** 18n });
await wallet.sendCall({ to: contract, method: 'swap', args: [...], valueWei: 0n });
const c = await wallet.deploy(source); // c.address is known right away
await c.waitForDeploy();
```

每次发送返回 `{ hash, nonce, from, contractAddress?, wait() }` 一经 节点接受了,扔 `TxRejectedError` (与 `reason`当它 没有。 被拒绝的交易从未到达链.

**数量.** `amountWei` 编号 : `valueWei` 绝对是韦伊。 年长者 `amount` 编号 : `value` 字段经过 `parseAse`: 数字或小数字符串是 ASE (单位:千美元)`'1.5'` 表示 1.5 ASE , 表示比值为 Wei, 表示整数字符串超过 18 数字读作 wei. `sendTransferWei` 财务报告和审定财务报表 `sendCallWei` 仅取魏.

**诺斯.** 钱包询问节点 `pendingNonce` 手伸出来 相继的自来自来自出 钱包获取 n, n+1, n+2 。 拒绝之后,它又问节点 (单位:千美元)`wallet.resetNonce()` 用手做同样的事情。 过 `nonce` 以覆盖. 通过同一皇家警察部队提交和投票: `pendingNonce` 每个节点.

**蝙蝠侠.** 首先签名,然后在一个请求中提交:

```ts
const a = await wallet.signCall({ to, method: 'a' });
const b = await wallet.signCall({ to, method: 'b' });
const res = await wallet.sendBatch([a, b]);   // POST /tx/batch
res.results[0].accepted; res.results[0].wait();
```

**无密钥交易.** 一旦连锁店有账户的公用钥匙 记录,它的交易可以留下密钥 大约三分之一 小一点. `AsentumWallet.create(client, { keyless: 'auto' })` 切换到 尽快 `getPublicKeyStatus().canOmitKey` 这是真的。 默认是 `'off'`。 。 。 .

每个发送时其它覆盖 : `gasLimit` (违约:21 000美元用于转移, 200 000 000美元用于呼叫,至少200 000美元用于部署;合同呼叫需要 至少有50,000人, `maxFeePerGas` (违约1), `signal`。 。 。 .

## 名称 (@ 用户名)

从节点0.9.0和名称旗日(链条1423上的1 200 000块)a 账户可以拥有像 `@milkie`。地址上的名称点; 解析 当你建立交易 并在确认屏幕上显示.

```ts
if (await client.namesActive()) {
  const { address, name } = await client.resolveRecipient('@milkie'); // throws NameNotFoundError for a free name
  const primary = await client.lookupAddress(wallet.address);          // "milkie" or null
}
```

在旗日之前,在0.9.0年以上的节点上,每一次仰望都抛出 `NamesNotActiveError`。 。 。 .

### 登记、转让和记录(0.3.1)

每篇书信都是签名的调用NameRegistry系统合同 (单位:千美元)`NAME_REGISTRY_CONTRACT`, (中文(简体) ), `0x...0b`) (中文(简体) ). 钱包中每个都有一个方法:

```ts
await (await wallet.registerName('milkie')).wait();      // sends exactly nameFeeWei('milkie')
await wallet.transferName('milkie', 'ase1...');          // free; ase1 or 0x recipient
await wallet.setPrimaryName('milkie');                   // the name apps show for this address
await wallet.clearPrimaryName();
await wallet.setNameRecord('milkie', 'x', '@asentum');   // keys: avatar, url, x, description; '' clears
```

| 方法 | 合同电话 | 页:1 |
| --- | --- | --- |
| `registerName(name)` | `register(name)` + 费用 | 500 / 100 / 50 ASE为3 / 4 / 5个字符,10 ASE为6个或以上的字符. 一半被烧了 一半被烧了 钱包的第一个名字变成了它的首要名称。 每43 200个区块每个地址最多登记5个. |
| `transferName(name, to)` | `transfer(name, to)` | 只有主人,不收费。 名称停止为发件人的主机,其记录为新所有者清除. |
| `setPrimaryName(name)` | `setPrimary(name)` | 只拥有者. |
| `clearPrimaryName()` | `clearPrimary()` | 保持名称. |
| `setNameRecord(name, key, value)` | `setRecord(name, key, value)` | 只拥有者. `avatar` 财务报告和审定财务报表 `url` 从https://、http://或ipfs://开始; `x` 是一个 X 手柄. |

每种方法都采用通常的发送选项(`gasLimit`, (中文(简体) ), `nonce`, (中文(简体) ), `signal`, (...) (中文(简体) ) 返回 a `SentTx`; 调用 `.wait()` 为收据。 丢弃无效的名称 `InvalidNameError` 在签署之前.

读取: `client.getNameLookup(name)` (所有者、记录、主旗), `client.resolveName(name)`, (中文(简体) ), `client.lookupAddress(address)`,或视图调用 例如 `client.viewCall(NAME_REGISTRY_CONTRACT, 'isAvailable', ['milkie'])`。 。 。 .

### 建立地名市场

登记处 **无批准或操作方法**: 只有主人可以移动 a 名称。 合同可以拥有自己的名字,所以市场可以充当代管人. 在合同中,登记处视市场为 `msg.sender`,则 市场移动名称 交叉合同呼叫, `E(registry).transfer(name, buyer)`。 。 。 .

按此顺序列出,以便其他人不能在以下两者之间声称姓名:

1.  卖方打电话 `marketplace.prepare(name, price)`市场检查 `E(registry).get(name).owner === msg.sender` 并记录卖方.
2.  卖方打电话 `wallet.transferName(name, marketplaceAddress)`。 。 。 .
3.  `marketplace.activate(name)` 检查市场现在拥有这个名字.
4.  买家打电话 `marketplace.buy(name)` 与价格。 市场支付 卖方和电话 `E(registry).transfer(name, buyer)`。 。 。 .
5.  要取消,卖方打电话 `marketplace.cancel(name)` 并获得名称 通过同样的转移.

每次转帐都清空记录 所以买家从清扫开始 简介.

## 已签名的消息

```ts
const proof = wallet.signMessage(challenge); // { address, publicKey, signature }
verifyMessage({ ...proof, message: challenge }); // true
```

签名的字节是 `"Asentum Signed Message:\n" + byteLength(message) + "\n" + message` (ML-DSA-65),与(a) `window.asentum.signMessage` 编辑 电报钱包,所以服务器 检查每个钱包的方式相同.

## 契约

```ts
import { AsentumContract } from '@asentum/sdk';

const pool = new AsentumContract(client, 'ase1v0myp2de3dhj3crvkhxqlnjaw2mvp64a9efkpl');
await pool.view('getPool', ['3']);                          // reads the tip
await pool.view('getPool', ['3'], { blockTag: 'finalized' });
await pool.viewFull('getPool', ['3']);                      // value, gas, events, blockNumber
const tx = await pool.connect(wallet).send('swapExactIn', [...], { valueWei });
await pool.getEvents('Swap', { fromBlock: 570000, toBlock: 571000 });
await pool.getSource();
await pool.getAccount(); // codeHash = BLAKE3 of the source
```

## 快速确认

交易在发送后大约在一个街区内(大约2.5) 后几条街(大约为7至10秒), 显示 第一点成功,第二点成功.

```ts
import { TimeoutError } from '@asentum/sdk';

const tx = await contract.send('swapExactIn', args);
setStatus(tx.hash, 'pending');

try {
  await tx.wait({
    until: 'final',
    onIncluded: (r) => setStatus(tx.hash, r.success ? 'in-block' : 'failed'),
    onReorg: () => setStatus(tx.hash, 'pending'),   // its block lost; it will land again
    onFinal: (r) => setStatus(tx.hash, r.success ? 'final' : 'failed'),
    timeoutMs: 120_000,
    signal,                                          // AbortSignal, optional
  });
} catch (e) {
  if (e instanceof TimeoutError) setStatus(tx.hash, 'still-pending'); // not a failure
  else throw e;
}
```

`client.waitForReceipt(hash, options)` 任何大麻都一样。 选项 :

| 选项 | 默认 | 含义 |
| --- | --- | --- |
| `until` | `'included'` | `'included'`: 第一次收到时解决. `'final'`: 一次解决 `finalized: true`。 。 。 . |
| `timeoutMs` | 60 000人/120 000人 | 拒绝使用 `TimeoutError` (单位:千美元)`lastReceipt` 如果在区块内,则设置. |
| `pollIntervalMs` | 1 000个 | 区块相隔约2.5个;更快地买不到任何东西. |
| `onIncluded(r)` |  | 在一个街区。 如果重置器移动到另一个街区,则再次起火. |
| `onReorg(prev)` |  | 它被一个兄弟弄丢了. |
| `onFinal(r)` |  | 最终(与 `until: 'final'`) (中文(简体) ). |
| `throwOnFailure` | `false` | 拒绝方式 `TxFailedError` 打开 `success: false` 而不是解决. |
| `signal` |  | 别等了`AbortError`) (中文(简体) ). 交易不受影响. |
| `pauseWhenHidden` | `true` | 在浏览器中,标签被隐藏时没有投票. |

传粉者在429和5xx上退后(在发送后重复,否则) 双倍至10 s),并持续地通过网络blips.

`tx.wait()` 没有争论的行为像0.1.x:它首先解决 收据(以块形式),包括失败的收据. `tx.wait(ms)` 仍然需要一个 暂停 .

## 错误

SDK 故意所抛出的所有错误 `AsentumError` 并携带 稳定 `code`数字 :

| 类 | 何时 |
| --- | --- |
| `TxRejectedError` | `POST /tx` 已回复 `accepted: false` (单位:千美元)`reason`, (中文(简体) ), `isNonceError`(中文(简体) ) |
| `TxFailedError` | 收据有 `success: false` (与 `throwOnFailure`(中文(简体) ) |
| `TimeoutError` | 等待时间已耗尽(`lastReceipt`); tx 可能仍然着陆 |
| `AbortError` | 您的中止信号已发射 |
| `ViewError` | `POST /view` 已回复 `ok: false` |
| `RpcError` | HTTP 200 带一个 `error` 机构(地址差、散列差、治理失败读取) |
| `JsonRpcError` | a JSON-RPC 错误对象(`rpcCode`(中文(简体) ) |
| `RateLimitError` | HTTP 429 复试后(`retryAfterMs`(中文(简体) ) |
| `HttpError` | 任何其他非第-2xx项(`status`, (中文(简体) ), `body`(中文(简体) ) |
| `NetworkError` | 获取失败或超时 |

"没有找到"不是一个错误: `getReceipt`, (中文(简体) ), `getBlock`, (中文(简体) ), `getTransaction`, (中文(简体) ), `getRawBlock` 财务报告和审定财务报表 `getProposal` 返回时 `null`。 。 。 .

## 帮助者

```ts
import {
  toAse1, toHexAddress, hexToAse1, ase1ToHex, isAse1, isHexAddress, isAddress, shortAse1,
  ase1ArgsToHex, aseToWei, parseAse, formatAse, toWei, eventTopic, getContractAddress,
} from '@asentum/sdk';

toAse1('0x72f14d1509758feb87fdeb875d7255871d0329d3'); // 'ase1wtc569gfwk87hplaawr46uj4suwsx2wndgf8ue'
toHexAddress('ase1wtc569gfwk87hplaawr46uj4suwsx2wndgf8ue'); // '0x72f1...29d3'
ase1ArgsToHex(['ase1...', { owner: 'ase1...' }]); // every ase1 inside becomes 0x hex
aseToWei('1.5');        // 1500000000000000000n (always ASE)
formatAse(15n * 10n ** 17n); // '1.5'
eventTopic('Swap');     // topics[0] for eth_getLogs: BLAKE3 of the name
getContractAddress(wallet.address, 3n); // where a deploy with nonce 3 lands
```

## 从0.1.x升级

见 [变动情况](https://npmcn.com/package/%40asentum/sdk/CHANGELOG.md)。简短清单: `wallet.address` 财务报告和审定财务报表 `contract.address` 现为 ase1 (`addressHex` 有六分之一,收据 `sender`编号 :`recipient` 为 ase1, `getBlock` 返回时 `null` 对于一个缺失的街区, `getReceipt` 丢入运输错误而不是返回 `null`,则 水龙头帮手堕地.

## 如何运作

交易是SSZ编码,用 BLAKE3 散列,用 ML-DSA-65 签名 (锂3) 当地提交 `POST /tx`。交易 散列是已签名字节的 BLAKE3, 所以SDK 在节点之前就知道了 答对. 读取使用节点的REST路由,加上JSON-RPC用于代码,存储, 交易和日志。 见 [节点 API 参考](https://asentum.com/docs/reference/api) 财务报告和审定财务报表 [快速确认](https://asentum.com/docs/guides/fast-confirmations)。 。 。 .

## 发展

```bash
npm test                 # unit tests (mocked fetch)
npm run test:live        # read-only smoke test against https://testnet.asentum.com
npm run typecheck
npm run build
```

## 许可证

阿帕奇 - 2.0

## 常见问题

### @asentum/sdk 是什么？

TypeScript SDK for Asentum:链读取,ase1地址,Dilithium3签名,与块和最后确认的交易,合同和事件\. 在Node\.js和浏览器中工作\.

### 如何安装 @asentum/sdk？

在项目目录运行 npm install @asentum/sdk，或使用 pnpm add / yarn add / bun add。

### @asentum/sdk 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @asentum/sdk 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @asentum/sdk 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=18。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @asentum/sdk 可以商用吗？

@asentum/sdk 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @asentum/sdk 的下载量有多少？

根据 npm 官方下载统计，@asentum/sdk 在 2026/10/07 – 2026/11/05 这 30 天内被下载 1,972 次，日均约 66 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @asentum/sdk 还在维护吗？

最新版本 0\.3\.1 发布于 2026/11/07（今天）；至今共发布 4 个版本，其中过去 12 个月发布了 4 个；首次发布于 2026/05/16。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

