# @1money/protocol-ts-sdk 中文文档

规范地址：https://npmcn.com/package/%401money/protocol-ts-sdk/

版本：3\.1\.1
npm 元数据更新时间：2026-10-15T11:53:43.788Z
中文译文更新时间：2026-11-06T13:12:12.095Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%401money/protocol-ts-sdk
原文对照：https://npmcn.com/package/%401money/protocol-ts-sdk/?lang=original
项目主页：https://github.com/1Money-Co/1money-protocol-ts-sdk#readme
源码仓库：https://github.com/1Money-Co/1money-protocol-ts-sdk

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

- 包体积（解压后）：1.2 MB，176 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：viem \>=2\.0\.0 \<3\.0\.0，axios \>=1\.15\.0 \<2\.0\.0，@ethereumjs/rlp \>=10\.0\.0 \<11\.0\.0
- 首次发布：2025-08-18T02:53:21.212Z
- 最新版本发布：2026-10-15T11:53:43.373Z
- 近 30 天下载量：3157（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：27（近 12 个月 24 个）

## 中文简介

1Money协议网络的 sdk

## 安装

```sh
npm install @1money/protocol-ts-sdk
```

也可以使用：`pnpm add @1money/protocol-ts-sdk`、`yarn add @1money/protocol-ts-sdk`、`bun add @1money/protocol-ts-sdk`

## README

# @ 1 钱/ protocol- ts- sdk

![1Money Logo](https://npmcn.com/package/%401money/protocol-ts-sdk/public/logo.png)

1货币网络协议的TS-SDK

[![Build Status](https://github.com/1Money-Co/1money-protocol-ts-sdk/actions/workflows/cicd-npm.yml/badge.svg)](https://github.com/1Money-Co/1money-protocol-ts-sdk/actions/workflows/cicd-npm.yml) [![NPM downloads](http://img.shields.io/npm/dm/%401money%2Fprotocol-ts-sdk.svg?style=flat-square)](https://www.npmjs.com/package/@1money/protocol-ts-sdk) [![npm version](https://badge.fury.io/js/%401money%2Fprotocol-ts-sdk.svg)](https://badge.fury.io/js/%401money%2Fprotocol-ts-sdk) [![install size](https://packagephobia.now.sh/badge?p=%401money%2Fprotocol-ts-sdk)](https://packagephobia.now.sh/result?p=%401money%2Fprotocol-ts-sdk) [![license](http://img.shields.io/npm/l/%401money%2Fprotocol-ts-sdk.svg)](https://github.com/1Money-Co/1money-protocol-ts-sdk/blob/main/LICENSE)

## 快开始

### 安装

```shell
npm i -S @1money/protocol-ts-sdk axios viem @ethereumjs/rlp
# or
yarn add @1money/protocol-ts-sdk axios viem @ethereumjs/rlp
# or
pnpm i @1money/protocol-ts-sdk axios viem @ethereumjs/rlp
```

### 初始化 API 客户端

```typescript
import { api } from '@1money/protocol-ts-sdk';

// Initialize with default settings (mainnet)
const apiClient = api();

// Or specify testnet network
const testnetClient = api({ network: 'testnet' });

// You can also set a custom timeout (in milliseconds)
const apiClient = api({
  network: 'testnet',
  timeout: 5000 // 5 seconds
});
```

### 配置自定义 HTTP 页眉

您可以设置所有 API 请求中包含的自定义 HTTP 信头 :

```typescript
import { setInitConfig } from '@1money/protocol-ts-sdk/client';

// Set custom headers for all requests
setInitConfig({
  headers: {
    'Authorization': 'Bearer your-token',
    'X-Custom-Header': 'custom-value'
  }
});

// You can also combine with other configuration options
setInitConfig({
  baseURL: 'https://api.custom-domain.com',
  timeout: 10000,
  headers: {
    'Authorization': 'Bearer your-token',
    'X-API-Key': 'your-api-key'
  }
});
```

**说明**:自定义头被自动与轴默认头合并,确保您的自定义头和库默认的安全头同时包含在所有请求中.

### 获取当前检查站编号

```typescript
const number = await apiClient.checkpoints.getNumber()
  .success(response => {
    console.log('number', response.number);
    return response.number;
  })
  .error(err => {
    console.error('Error:', err);
    // return a default value
    return 0;
  });

// do something with the number
// ...
```

### 按号码叫检查站

```typescript
const checkpoint = await apiClient.checkpoints.getByNumber(1)
  .success(response => {
    console.log('checkpoint', response);
  });
```

## 光盘N

```html
<script src="https://unpkg.com/@1money/protocol-ts-sdk@latest/umd/1money-protocol-ts-sdk.min.js"></script>

<script>
  const apiClient = window.$1money.api({
    network: 'testnet'
  });

  async function getNumber () {
    const res = await apiClient.checkpoints.getNumber();
    console.log('res: ', res);
  }

  getNumber();
</script>
```

## 处理错误

**读取返回一个可连锁的类似承诺的包装; v2 写出一个简单的承诺 .** 每读(`apiClient.<module>.get*`, (中文(简体) ), `apiClient.<module>.estimateFee`(等等)和 每个 `legacyV1.*` 写入返回类似承诺的对象 `.success()`, (中文(简体) ), `.timeout()`, (中文(简体) ), `.error()` 财务报告和审定财务报表 `.rest()` 处理器,如下所示。 这个 **本土 v2** 写法( e)`apiClient.tokens.issueToken`, (中文(简体) ), `apiClient.transactions.payment`, (中文(简体) ), 和其余部分 `TransactionBuilder` → `authorize` - 提交管道) 简单 `async` 函数并返回本地 `Promise` —— 说 `await` 他们在一个 `try/catch` 而不是连锁 `.success()/.error()`; 参见写入示例 下级 [API 方法](https://npmcn.com/package/%401money/protocol-ts-sdk/#readme-api-methods) 见下文.

#### v2 写入结果

V2 写入解析 `{ hash }` 当节点承认交易时. 否则它就会产生一个错误。 分会 `instanceof`数字 :

| 丢弃 | `submitted` | 怎么办 |
| --- | --- | --- |
| `TransactionSubmissionError` | `false` | 节点在录取前拒绝了请求. 纠正原因( :`err.action`, (中文(简体) ), `err.status`, (中文(简体) ), `err.errorCode`然后再次发送. |
| `TransactionLockedError` | `true` | 节点持有这个确切的交易. 重新发送相同的 `authorized` 直到其收据出现. |
| `TransactionOutcomeUnknownError` | `'unknown'` | SDK不能说 抬头看 `err.transactionHash` 并重发 `authorized` 直到你知道这个州. |
| `TransactionHashMismatchError` | `true` | 节点承认交易,但返回了不同的散列. 别再寄了. |

在锁定之后,在任何非交易中,不得为同一目的签署新交易 未知结果: 支付可以执行两次 。 重订 **不变** 签名 交易总是安全的:它有相同的散列,所以最多一个副本执行. `apiClient.transactions.settle(authorized)` 重新发送相同的签名字节并用收件解决; 发送新书写方式 `apiClient.transactions.submitAndSettle(authorized)` 在一个电话中同时进行(见 `src/api/transactions/README.md`) (中文(简体) ). SDK决定由 `action` 节点错误体的成员; 在没有节点的节点上, a `422` `business_transaction_failed` (单位:千美元) `408` 未知,但一些固定文本除外 被释放的节点: "已经飞行"的意思是锁定, 拒绝 已签名字节( 例如一个错误的签名或一个错误的链条 id) 表示拒绝 。 见 `skills/1money-protocol-sdk/references/client-and-errors.md` 全部规则.

#### 问题细节

API 错误合同的节点发送一个 [RFC 9457 (韩语)](https://www.rfc-editor.org/rfc/rfc9457) aPI 错误( 不在 `/api/health`, (中文(简体) ), `/api/status` 或者说 `/metrics`) (中文(简体) ). SDK将其分析为 `err.problem` (类型) `ApiProblem`每张 `ParsedError` (单位:千美元) 值为 `.error()` 得到一个被拒绝的诺言 `TransactionSubmissionError`, (中文(简体) ), `TransactionLockedError` 财务报告和审定财务报表 `TransactionOutcomeUnknownError` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}一个单一的呈文 {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢. `err.problem` 实值 `undefined` 何时 身体没有弦 `type`,例如,在更古老的节点上;写入错误保留 `err.action` 财务报告和审定财务报表 `err.problemType` 以及那些错误 `settle` 掷出 最后没有尸体 HTTP 401 不是一个 `ParsedError`: 默认客户端的登录 规则将生体传递给 `.login()`或者用它来决定承诺 那个身体 `type` 财务报告和审定财务报表 `action` 作为普通成员,但没有 `problem`。 。 。 .

| 成员 | 含义 |
| --- | --- |
| `type` | 问题类型 URI, `https://developer.1moneynetwork.com/problem/<identifier>`,或 `about:blank`比较整个字符串. |
| `action` | `fix_request`, (中文(简体) ), `retry_later`, (中文(简体) ), `in_progress`, (中文(简体) ), `check_status` 或者说 `use_other_node`。 。 。 . `undefined` 当身体没有动作或SDK不知道时:在呈文中,视作为 `check_status`。 。 。 . |
| `instance` | 请求身份, `urn:uuid:<id>`当您向节点操作员报告一个问题时引用它. |
| `title`, (中文(简体) ), `status` | 该类型简略和HTTP状态. |
| `members` | 发送类型中输入的成员( 例如) `tx_hash`, (中文(简体) ), `nonce`, (中文(简体) ), `path`) (中文(简体) ). 一个成员可能在更古老的节点失踪. `txHash` 财务报告和审定财务报表 `retryAfterSecs` 读取两个常见的. |

决定: `type` 财务报告和审定财务报表 `action`,没有打开 `message` 或者说 `title`:他们的文本可以更改. 404不一定是"缺席":节点不服务的路径给定 `route_not_found`。 。 。 .

```typescript
import type { ParsedError } from '@1money/protocol-ts-sdk';

const TRANSACTION_NOT_FOUND =
  'https://developer.1moneynetwork.com/problem/transaction_not_found';

try {
  await apiClient.transactions.getByHash(hash);
} catch (err) {
  const { problem } = err as ParsedError;
  if (problem?.type === TRANSACTION_NOT_FOUND) {
    // Not found yet. Look it up again later.
  } else {
    console.error(problem?.instance, err);
  }
}
```

对于可连锁包装器,总是执行两个处理器进行适当的错误管理:

1.  `.success()`:处理成功的API响应
2.  `.timeout()`: 具体处理超时出错
3.  `.error()`: 处理所有其他类型的错误
4.  `.rest()`: 在上述任何处理者完成后运行的最后处理器

```typescript
import { api } from '@1money/protocol-ts-sdk';

const apiClient = api();

apiClient.someMethod()
  .success(response => {
    // Handle successful response
  })
  .timeout(err => {
    // Handle timeout case
  })
  .error(err => {
    // Handle other errors
  });
```

你用得着 `rest` 来处理所有其他错误:

```typescript
apiClient.someMethod()
  .success(response => {
    // Handle successful response
  })
  .rest(err => {
    // Handle other cases
  });
```

#### 自动/等待

您也可以使用 async/ 等待处理响应 :

```typescript
import { api } from '@1money/protocol-ts-sdk';

const apiClient = api();

try {
  const response = await apiClient.someMethod();
  console.log('Response:', response);
} catch (err) {
  console.error('Error:', err);
}
```

#### 答应

您也可以使用标准 `promise` 处理响应:

```typescript
import { api } from '@1money/protocol-ts-sdk';

const apiClient = api();

apiClient.someMethod()
  .then(response => {
    console.log('Response:', response);
  })
  .catch(err => {
    console.error('Error:', err);
  });
```

## API 方法

下面的每个文字都遵循同样的 **本土 v2** 形状 : `prepare` 签字 文摘 • `authorize` - 提交结果 `AuthorizedTxV2`。见 [从 2. x 移到 3. 0](https://npmcn.com/package/%401money/protocol-ts-sdk/#readme-migrating-from-2x-to-30) 财务报告和审定财务报表 `skills/1money-protocol-sdk/references/transactions.md` 为整个管道, 每个建筑工的田地和遗产 `LegacyV1TransactionBuilder` 编号 : `api().<module>.legacyV1.*` 路径.

### 链式 API

#### 获取链式标识

```typescript
apiClient.chain.getChainId()
  .success(response => {
    console.log('Current chain id:', response.chain_id);
  })
  .error(err => {
    console.error('Error:', err);
  });
```

### 账户 API

#### 获取账户 Nonce

```typescript
const address = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';
apiClient.accounts.getNonce(address)
  .success(response => {
    console.log('Account nonce:', response);
  })
  .error(err => {
    console.error('Error:', err);
  });
```

#### 获取关联的托肯账户

```typescript
const address = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';
const token = '0x2cd8999Be299373D7881f4aDD11510030ad1412F';
apiClient.accounts.getTokenAccount(address, token)
  .success(response => {
    console.log('Associated token account:', response);
  })
  .error(err => {
    console.error('Error:', err);
  });
```

#### 创建多西格账户

`createMultisig` 实值 **v2 仅** 没有 `legacyV1` 窗体和无 `accounts.legacyV1` 名称空间.

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner,
  deriveMultisigAddress
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const creatorAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// 33-byte SEC1-compressed public keys. 2-20 signers; a weight is a u8
// (1-255) and the threshold must not exceed the total signer weight.
const signers = [
  { public_key: '0x02...', weight: 1 },
  { public_key: '0x03...', weight: 1 }
];
const threshold = 2;

// The node never echoes the new account's address, so compute it first --
// this is the same value the node derives at execution.
const multisigAddress = deriveMultisigAddress(signers, threshold);

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(creatorAddress);

const prepared = TransactionBuilder.createMultisig({
  chain_id,
  nonce,
  signers,
  threshold
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.accounts.createMultisig(authorized);
  console.log('Multisig', multisigAddress, 'created in tx', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

见 [获取多西格账户地址](https://npmcn.com/package/%401money/protocol-ts-sdk/#readme-derive-a-multisig-account-address) 页:1 由自己决定.

### 托肯斯 API

#### 获取 Token 元数据

```typescript
const tokenAddress = '0x2cd8999Be299373D7881f4aDD11510030ad1412F';
apiClient.tokens.getTokenMetadata(tokenAddress)
  .success(response => {
    console.log('Token metadata:', response);
  })
  .error(err => {
    console.error('Error:', err);
  });
```

#### 发行新托肯

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const masterAuthority = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(masterAuthority);

// Prepare (validates fields, computes the digest to sign).
const prepared = TransactionBuilder.tokenIssue({
  chain_id,
  nonce,
  symbol: 'MTK',
  name: 'My Token',
  decimals: 18,
  master_authority: masterAuthority,
  is_private: true,
  clawback_enabled: true
});

// Sign the digest, then authorize it into a plain-JSON request.
const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: submitAuthorized returns a plain Promise, not the chainable
// wrapper -- await it in a try/catch.
try {
  const response = await apiClient.tokens.issueToken(authorized);
  console.log('Token issued:', response.token, 'in tx', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

#### 薄荷图案

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const mintAuthority = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(mintAuthority);

const prepared = TransactionBuilder.tokenMint({
  chain_id,
  nonce,
  recipient: '0xa128999be299373d7881f4add11510030ad13512',
  value: '1000000000000000000',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.mintToken(authorized);
  console.log('Mint transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

签名人一定是签名人的 `master_authority` 或持有所赋予的薄荷 权力——见 [格兰特·托肯管理局](https://npmcn.com/package/%401money/protocol-ts-sdk/#readme-grant-token-authority)授予 (a) 允许使用薄荷,以抵减每薄荷的有限津贴 主权威是没有干扰的.

#### 管理托肯黑名单/白名单

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';
import { ManageListAction } from '@1money/protocol-ts-sdk/api';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const operatorAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(operatorAddress);

// tokenBlacklist and tokenWhitelist are distinct v2 operations (distinct
// signing hashes) — build the one you intend to submit, they are not
// interchangeable the way the pre-3.0 tokenManageList builder was.
const prepared = TransactionBuilder.tokenBlacklist({
  chain_id,
  nonce,
  action: ManageListAction.Add,
  address: operatorAddress,
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.manageBlacklist(authorized);
  console.log('Blacklist update transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

白名单是相同的形状结束到结束——将建设者和 提交方法,并在您实际打算提交的方法上签名:

```typescript
const prepared = TransactionBuilder.tokenWhitelist({
  chain_id,
  nonce,
  action: ManageListAction.Add,
  address: '0xa128999be299373d7881f4add11510030ad13512',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const response = await apiClient.tokens.manageWhitelist(prepared.authorize(signature));
```

白名单适用于以 `is_private: true`启用 `ManageListAction.Remove` 将地址从任何一份名单上删除.

#### 烧掉托肯斯

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const ownerAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(ownerAddress);

const prepared = TransactionBuilder.tokenBurn({
  chain_id,
  nonce,
  value: '1000000000000000000',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.burnToken(authorized);
  console.log('Burn transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

#### 抓回脚趾

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const clawbackAuthority = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(clawbackAuthority);

const prepared = TransactionBuilder.tokenClawback({
  chain_id,
  nonce,
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F',
  from: '0xa128999be299373d7881f4add11510030ad13512',
  recipient: clawbackAuthority,
  value: '1000000000000000000'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.clawbackToken(authorized);
  console.log('Clawback transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

Clawback 移动符号出 `from` 没有那个账户的签名,所以它 只工作于发行的符号 `clawback_enabled: true` (默认)和 签名者必须是签名者 `master_authority` 或持有给予的 `AuthorityType.Clawback` 权力.

#### 格兰特·托肯管理局

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';
import { AuthorityAction, AuthorityType } from '@1money/protocol-ts-sdk/api';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const masterAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(masterAddress);

const prepared = TransactionBuilder.tokenAuthority({
  chain_id,
  nonce,
  action: AuthorityAction.Grant,
  authority_type: AuthorityType.MasterMint,
  authority_address: '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F',
  value: '1000000000000000000000'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.grantAuthority(authorized);
  console.log('Authority update transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

#### 暂停/ 取消暂停托肯

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';
import { PauseAction } from '@1money/protocol-ts-sdk/api';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const pauseAuthority = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(pauseAuthority);

const prepared = TransactionBuilder.tokenPause({
  chain_id,
  nonce,
  action: PauseAction.Pause, // PauseAction.Unpause to lift it
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.pauseToken(authorized);
  console.log('Pause transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

#### 更新托肯元数据

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const metadataAuthority = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(metadataAuthority);

const prepared = TransactionBuilder.tokenMetadata({
  chain_id,
  nonce,
  name: 'My Token',
  uri: 'https://example.com/my-token.json',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F',
  additional_metadata: [{ key: 'category', value: 'stablecoin' }]
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.updateMetadata(authorized);
  console.log('Metadata transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

`additional_metadata` 取代整个清单,而不是合并到其中—— 发送所有你想要的对。 过 `[]` 来清理它.

#### 桥梁和薄荷

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const bridgeOperatorAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(bridgeOperatorAddress);

const prepared = TransactionBuilder.tokenBridgeAndMint({
  chain_id,
  nonce,
  recipient: '0x6324dAc598f9B637824978eD6b268C896E0c40E0',
  value: '25000000000000000000',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F',
  source_chain_id: 1,
  source_tx_hash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
  bridge_metadata: 'bridge_from_chain_1'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.bridgeAndMint(authorized);
  console.log('Bridge and mint transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

#### 燃烧和桥梁

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const senderAddress = '0x6324dAc598f9B637824978eD6b268C896E0c40E0';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(senderAddress);

const prepared = TransactionBuilder.tokenBurnAndBridge({
  chain_id,
  nonce,
  sender: senderAddress,
  value: '20000000000000000000',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F',
  destination_chain_id: 1,
  destination_address: '0x1234567890abcdef1234567890abcdef12345678',
  escrow_fee: '1000000000000000000',
  bridge_metadata: 'bridge_to_chain_1',
  bridge_param: '0x'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.burnAndBridge(authorized);
  console.log('Burn and bridge transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

### 交易 API

#### 获取交易细节

```typescript
const txHash = '0xf55f9525be94633b56f954d3252d52b8ef42f5fd5f9491b243708471c15cc40c';
apiClient.transactions.getByHash(txHash)
  .success(response => {
    console.log('Transaction details:', response);
  })
  .error(err => {
    console.error('Error:', err);
  });
```

#### 获取交易收据

```typescript
const txHash = '0xf55f9525be94633b56f954d3252d52b8ef42f5fd5f9491b243708471c15cc40c';
apiClient.transactions.getReceiptByHash(txHash)
  .success(response => {
    console.log('Transaction receipt:', response);
  })
  .error(err => {
    console.error('Error:', err);
  });
```

#### 估计交易费

```typescript
const fromAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';
const toAddress = '0x6324dAc598f9B637824978eD6b268C896E0c40E0';
const value = '1000000000';
const tokenAddress = '0x2cd8999Be299373D7881f4aDD11510030ad1412F';

apiClient.transactions.estimateFee(fromAddress, toAddress, value, tokenAddress)
  .success(response => {
    console.log('Estimated fee:', response);
  })
  .error(err => {
    console.error('Error:', err);
  });
```

#### 提交付款交易

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const senderAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(senderAddress);

// Prepare (validates fields, computes the digest to sign). `memo` is always
// sent on the wire; omit the option for the all-empty "no business memo".
const prepared = TransactionBuilder.payment({
  chain_id,
  nonce,
  recipient: '0xa128999be299373d7881f4add11510030ad13512',
  value: '1000000000',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
});

// Sign the digest, then authorize it into a plain-JSON request.
const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature); // signature.v must be 0 or 1

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.transactions.payment(authorized);
  console.log('Payment transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

#### 在付款后附上备忘录

每个v2的构建者都会接受一个可选的第二个论点,持有备忘录. 备忘录 实值 **签字有效载荷的一部分**,所以同样的付款 与不同的备忘录 生成不同的 `signingHash` 和不同的交易散列 后面贴有信头或注释.

```typescript
import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

const prepared = TransactionBuilder.payment(
  {
    chain_id,
    nonce,
    recipient: '0xa128999be299373d7881f4add11510030ad13512',
    value: '1000000000',
    token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
  },
  {
    memo: {
      type: 'purpose/SALA',
      format: 'text/plain',
      data: 'August salary'
    }
  }
);

// Everything downstream is unchanged -- the memo is already inside the digest.
const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const response = await apiClient.transactions.payment(prepared.authorize(signature));
```

字段限制,由 SDK 和节点相同执行 :

| 外地 | 马克斯 | 允许字符 |
| --- | --- | --- |
| `type` | 128 字节 | 仅限URL安全(RFC 3986 无保留 + gen-delims + sub-delims +) `%`(中文(简体) ) |
| `format` | 64 字节 | 只有 URL 安全, 同一集 |
| `data` | 256 字节 | 除NUL、C0/C1控制编码点外的任何UTF-8和代号 |

限制是 **UTF-8 字节长度, 不是字符计数** —— 说 `'结算备注'` 实值 四个字符,但十二字节。 每个字段都是可选的 备忘以空字符串填充其余部分,省略选项完全发送 `{ type: '', format: '', data: '' }`,但仍在签名.

校验为局部并发生 **在引用任何签名符之前**: 建造者 电话 `validateMemo` 在计算摘要时, 错误的备忘抛出 而不是花一个签名操作—— 这很重要,当签名者是 由HSM或KMS支持.

```typescript
import { MemoValidationError } from '@1money/protocol-ts-sdk';

try {
  TransactionBuilder.payment(payload, {
    memo: { type: 'a'.repeat(200), format: '', data: '' }
  });
} catch (err) {
  if (err instanceof MemoValidationError) {
    // 'MEMO_TYPE_TOO_LONG' | 'MEMO_TYPE_INVALID_CHARS' | 'MEMO_FORMAT_TOO_LONG'
    // | 'MEMO_FORMAT_INVALID_CHARS' | 'MEMO_DATA_TOO_LONG'
    // | 'MEMO_DATA_CONTROL_CHARS' | 'MEMO_TOO_LARGE'
    console.error(err.code, err.message);
  }
}
```

从交易中读取(不是收据),在交易中归还 每个包含备忘的 v2 信封 :

```typescript
const tx = await apiClient.transactions.getByHash(
  prepared.authorize(signature).transactionHash
);
console.log(tx.memo); // { type: 'purpose/SALA', format: 'text/plain', data: 'August salary' }
```

同样的选项对每个v2的构建者都起作用—— `tokenIssue`, (中文(简体) ), `tokenMint`, (中文(简体) ), `tokenBlacklist`, (中文(简体) ), `batchPayment` 其他人都接受了 `{ memo }` 作为 第二次辩论就是这种形式.

#### 提交批次付款

在一桩土生土长的V2交易中,向许多受款人支付一枚地契. `batchPayment` 实值 **v2 仅**: SDK 刻意暴露出没有遗留的批量 付款构建者或 `transactions.legacyV1.batchPayment`,即使一个节点仍然 保留已贬值的 v1 路由 .

```typescript
import {
  TransactionBuilder,
  calculateBatchPaymentOperationsHash,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const senderAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

const token = '0x2cd8999Be299373D7881f4aDD11510030ad1412F';
const operations = [
  { recipient: '0xa128999be299373d7881f4add11510030ad13512', amount: '1000000000' },
  { recipient: '0x6324dAc598f9B637824978eD6b268C896E0c40E0', amount: '2000000000' }
];

// An unsigned, non-binding point-in-time quote. It is not a fee cap and is
// not copied into the payload, signing hash, authorization, or submission.
const quote = await apiClient.transactions.estimateBatchPaymentFee({
  from: senderAddress,
  token,
  operations
});
console.log('Estimated fee:', quote.fee, 'plan:', quote.plan);

// Get chain id and a fresh current nonce.
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(senderAddress);

// This optional field is a caller choice. If supplied, the builder recomputes
// it and rejects a mismatch locally before any signer is invoked.
const operationsHash = calculateBatchPaymentOperationsHash(operations);

const prepared = TransactionBuilder.batchPayment({
  chain_id,
  nonce,
  token,
  operations,
  created_at: Math.floor(Date.now() / 1000), // unix seconds
  operations_hash: operationsHash,
  batch_id: 'payroll-2026-08'
}, {
  memo: {
    type: 'purpose/SALA',
    format: 'text/plain',
    data: 'payroll-2026-08'
  }
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.transactions.batchPayment(authorized);
  // The SDK already checks this case-insensitively before resolving.
  if (
    response.hash.toLowerCase() !==
    authorized.transactionHash.toLowerCase()
  ) {
    throw new Error('SDK already rejects a server/local hash mismatch');
  }
  console.log('Batch payment transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}
```

`operations` 不得为空;每个收款人和金额必须是非零,以及 总和不得超过U256:MAX. `operations_hash` 可选,但 提供值必须是峡谷 `calculateBatchPaymentOperationsHash(operations)` 结果或准备失败 当地. `batch_id` 仅被签名的相关元数据 : 它没有独有性, 分解、一能或重放保证。 交易非ce 仍然保留 交易级重放机制。 每个操作都签名并发送为 没错 `{ recipient, amount }`; 未键入的额外运行时间属性 呼叫者被忽略, 无法到达授权请求 .

批发付款总是会签名和发送完整的备忘录. 选择 `memo` 实值 有效并发送 `{ type: '', format: '', data: '' }`; 这三个空字符串 仍然是所签署有效载荷的一部分。 过时的客户端 `max_fee` 字段 不接受。 实际发送者借项是所有操作金额的总和 加收据的实际字符串 `fee_used`而不是估计 批量赋能, 操作计数和编码大小限制,收费资产是动态节点 治理规则,所以成功的估计不是录取保证.

将返回的散列索引后,阅读其收据(或最终收据)和 使用情况 `execution_events` 检查接收者:

```typescript
const receipt = await apiClient.transactions.getReceiptByHash(
  authorized.transactionHash
);

// Batch Payment has no single recipient. This zero address is a sentinel.
console.log(receipt.success_info?.receiver);

for (const event of receipt.execution_events ?? []) {
  if (event.event_type === 'PaymentExecuted') {
    console.log(event.recipient, event.amount);
  }
}

console.log('actual fee:', receipt.fee_used);
```

对于批付款, `success_info.receiver` 是零地址监视器,不是 转移目的地; 实际收款人和金额是订购的 `PaymentExecuted` 事件. `batch_info.failure` 保留用于转发 兼容性但为 `null` 在目前生产形状的反应中,不是 终端故障信号。 如果操作失败, 节点会回滚 收款人信贷、汇款人借项和操作员-收费移动在一起;不 从这个规则推断出一个非核故障对象.

为了核实有意退缩的情况,不依赖收据或 错误体作为终端信号:故障可能为收不到或模糊,以及 `batch_info.failure` 遗 物 `null` 在目前的行为。 在提交之前, 发送方、每个计划接收方和操作费简表余额 接收者。 提交一次,仅对划界案提出有限度的观察 普通/ 最终化的接收路径, 然后验证每个快照没有变化 。 使用 一个孤立的发送者,所以任何不确定的非ce 或 mempol 状态都不会影响其他 交易.

## 工具函数

### 计算交易散列

```typescript
import { calcTxHash } from '@1money/protocol-ts-sdk';

// Create the payload array
const payload = [
  1212101, // chain_id
  2, // nonce
  '0x0000000000000000000000000000000000000000', // recipient
  1024, // value
  '0x0000000000000000000000000000000000000000', // token
];

// Create the signature object
const signature = {
  r: '0xe9ef6ce7aaeb4656f197b63a96c932ab5e0fd2df0913f6af1c8e7b1879e5ed0a',
  s: '0x68a9cbaa35af5e3d896a2841d19a42dba729380a1c91864403de872578f6f6c3',
  v: 0,
};

// Calculate the transaction hash
const hash = calcTxHash(payload, signature);
console.log('Transaction hash:', hash);
```

### 随笔地址

```typescript
import { deriveTokenAddress } from '@1money/protocol-ts-sdk';

const walletAddress = '0xA634dfba8c7550550817898bC4820cD10888Aac5';
const mintAddress = '0x8E9d1b45293e30EF38564582979195DD16A16E13';

// Derive the token account address
const tokenAddress = deriveTokenAddress(walletAddress, mintAddress);
console.log('Token account address:', tokenAddress);
```

### 转换为十六进制

```typescript
import { toHex } from '@1money/protocol-ts-sdk';

// Convert different types to hex
const boolHex = toHex(true); // '0x1' (minimal hex, not zero-padded)
const numHex = toHex(123); // '0x7b'
const strHex = toHex('hello'); // '0x68656c6c6f'
const arrHex = toHex([1, 2, 3]); // '0x010203'
```

### 获取多西格账户地址

计算本地多西格账户的地址 _在此之前_ 创建它 - `accounts.createMultisig` 仅返回 `{ hash }`从没有地址:

```typescript
import { deriveMultisigAddress } from '@1money/protocol-ts-sdk';

const address = deriveMultisigAddress(
  [
    { public_key: '0x02...', weight: 1 },
    { public_key: '0x03...', weight: 1 },
  ],
  2 // threshold
); // → '0x…'
```

### 签名信件( 过期 )

```typescript
import { signMessage } from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = 'YOUR_PRIVATE_KEY';

// Create the payload array for signing
const payload = [
  1212101, // chain_id
  2, // nonce
  '0x0000000000000000000000000000000000000000', // recipient
  '1000000000000000000', // value (in wei)
  '0x0000000000000000000000000000000000000000', // token
];

// Sign the message
const signature = await signMessage(payload, privateKey);
```

`signMessage` 财务报告和审定财务报表 `encodePayload` 是遗产 `@deprecated` 帮手 偏爱 `TransactionBuilder` (或 `LegacyV1TransactionBuilder` 移民期间 窗口),用于新代码 - 见 [从 2. x 移到 3. 0](https://npmcn.com/package/%401money/protocol-ts-sdk/#readme-migrating-from-2x-to-30)。 。 。 .

## 从 2. x 移到 3. 0

3.0 使域分隔 **本土 v2** 签名默认方案 将预-3.0方案移动到明确的命名空间后。 这是破解 更改任何代码调用 `TransactionBuilder` 直接说.

-   **`TransactionBuilder` 现在意味着v2.** `TransactionBuilder.payment(...)` (和 每个其它操作)返回 a `PreparedTxV2`而不是旧的 `PreparedTx`。 。 。 . 它已经没有了 `.sign()` 编号 : `.attachSignature()` 编号 : `.rlpBytes` 编号 : `.signatureHash`它已经 `.signingHash` 财务报告和审定财务报表 `.authorize(signature)` 换句话说.
    
-   **3:0前计划仍然存在**,不变,作为 `LegacyV1TransactionBuilder` (同样的建筑师名称,相同 `.sign()`编号 : `.attachSignature()`编号 :`.toRequest()` 形状和以前一样) `api().<module>.legacyV1.*` 提交方法(例如:. `client.transactions.legacyV1.payment(...)`, (中文(简体) ), `client.tokens.legacyV1.manageBlacklist(...)`) (中文(简体) ). `accounts` 没有 `legacyV1` 命名空间,以及 `batchPayment` 编号 : `createMultisig` 没有遗产 两者都是 v2 .
    
-   **写作方法现在采用 `AuthorizedTxV2`**,输出 `prepared.authorize(signature)`,而不是从 `signed.toRequest()`。 。 。 . `AuthorizedTxV2` 是一个简单的 JSON 并可以跨越一个进程 边界(在一个地方签名,从另一个地方提交)。 每次打给 `authorize` 返回一个独立的请求快照; 更改早先的请求, 包括备忘录在内,不得影响以后的授权或仓促执行.
    
-   **写法现在返回原生 `Promise`,而不是链式包装.** 这是很容易错过的,因为 **原文不变** 一样 客户端现在有两个调用样式:
    
    ```typescript
    // Read: still the promise wrapper.
    apiClient.tokens.getTokenMetadata(token).success(res => …).error(err => …);
    
    // Write: a plain Promise. Calling .success() on it throws
    // "apiClient.tokens.issueToken(...).success is not a function".
    try {
      const res = await apiClient.tokens.issueToken(authorized);
    } catch (err) { … }
    ```
    
    这么说吧 `.success()`编号 :`.error()`编号 :`.timeout()`编号 :`.rest()` 任何2.x上的链条 **写入** 电话必须是 `await` 在一个 `try`编号 :`catch`键入脚本标记 编译时间; plain-JavaScript呼叫器只在运行时查找.
    
-   **`tokenManageList` 不见了.** 它分裂成 `tokenBlacklist` 财务报告和审定财务报表 `tokenWhitelist` • 不同的业务,有明显的签名散列车,配对 与 `tokens.manageBlacklist` 编号 : `tokens.manageWhitelist` 页:1 你个 无法再制造出一个有效载荷并将其提交两个终点.
    
-   **`memo` 现在总是发送** 在v2表面。 每一次行动都带有 电线上的备忘录; 省略 `memo` 选项发送全空 `{ type: '', format: '', data: '' }` 而不是离开球场 完全没有。 这与3:0前的行为不同,当时没有备忘录 与当前不同的代码路径.
    
-   **批量支付使用克能克 v2载荷.** 被除名者 `max_fee` 字段 既未签名也未接受; 请求未签名 `transactions.estimateBatchPaymentFee({ from, token, operations })` 引用 换句话说 共享 `EstimateFee` 现在的反应是 `fee: string` 和可选 `plan?: string`因此,这也适用于现有的 `estimateFee()` 电话.
    
-   **对所有呼叫者都更正接收字段.** `TransactionReceipt.fee_used` 是小数字符串(不是数字),并且 `to` 改为 `recipient`。 。 。 . `FinalizedTransactionReceipt` 扩展此更正的常见收件形状, 因此,最终读取的呼叫者必须做出同样的更新.
    
-   **签署 `v` 必须是 `0` 或者说 `1`** v2 表面; 遗留 `27`编号 :`28` 实值 被拒绝 `authorize`,没有转换.
    

遗产没有公布日落日期 `/v1` 写入表面或用于 `LegacyV1TransactionBuilder` ——节点不作广告,操作员 运行切换 在他们自己的时间表。 检查 `client.status.getNativeWriteStatus()` 以查看当前存在的表面 之前取决于其中之一.

见 `skills/1money-protocol-sdk/references/transactions.md` 全数v2 管道和每个建筑工的田地 `skills/1money-protocol-sdk/references/client-and-errors.md` 用于新v2 错误代码和 `TransactionHashMismatchError`。 。 。 .

## 许可证

麻省理工学院

## 常见问题

### @1money/protocol-ts-sdk 是什么？

1Money协议网络的 sdk

### 如何安装 @1money/protocol-ts-sdk？

在项目目录运行 npm install @1money/protocol-ts-sdk，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：viem（\>=2\.0\.0 \<3\.0\.0）、axios（\>=1\.15\.0 \<2\.0\.0）、@ethereumjs/rlp（\>=10\.0\.0 \<11\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @1money/protocol-ts-sdk 支持 TypeScript 吗？

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

### @1money/protocol-ts-sdk 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @1money/protocol-ts-sdk 可以商用吗？

@1money/protocol-ts-sdk 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @1money/protocol-ts-sdk 的下载量有多少？

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

### @1money/protocol-ts-sdk 还在维护吗？

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

