# @chainlink/functions-toolkit 中文文档

规范地址：https://npmcn.com/package/%40chainlink/functions-toolkit/

版本：0\.3\.2
npm 元数据更新时间：2025-01-30T17:23:41.000Z
中文译文更新时间：2026-11-09T19:16:52.629Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40chainlink/functions-toolkit
原文对照：https://npmcn.com/package/%40chainlink/functions-toolkit/?lang=original
项目主页：https://github.com/smartcontractkit/functions-toolkit#readme
源码仓库：https://github.com/smartcontractkit/functions-toolkit

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

- 包体积（解压后）：1.7 MB，57 个文件
- 模块格式：CommonJS
- TypeScript 类型：包内自带
- 运行依赖：7 个
- 首次发布：2023-09-05T20:22:32.040Z
- 最新版本发布：2024-09-16T19:48:36.586Z
- 近 30 天下载量：1808（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：38（近 12 个月 0 个）

## 中文简介

国家防范机制软件包,其功能集可用于与链路连接函数合作.

## 安装

```sh
npm install @chainlink/functions-toolkit
```

也可以使用：`pnpm add @chainlink/functions-toolkit`、`yarn add @chainlink/functions-toolkit`、`bun add @chainlink/functions-toolkit`

## README

# 函数工具

可用于合作的国家防范机制软件包 [链路链接函数](https://chain.link/functions)。 。 。 .

可找到链路函数的最新文档 [这里](https://docs.chain.link/chainlink-functions)。 。 。 .

# 目录

-   [目录](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-table-of-contents)
-   [先决条件](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-prerequisites)
    -   [记账订阅管理](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-functions-billing-subscription-management)
        -   [订阅](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-subscription-initialization)
        -   [创建订阅](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-create-subscription)
        -   [基金订阅](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-fund-subscription)
        -   [增加/取消核准的消费者合同](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-addingremoving-authorized-consumer-contracts)
        -   [取消订阅](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-cancelling-subscriptions)
        -   [转让和接受订阅](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-transferring-and-accepting-transfers-of-subscriptions)
        -   [获取订阅细节](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-get-subscription-details)
        -   [B. 时间安排要求](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-timing-out-requests)
        -   [估计请求费用](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-estimating-request-costs)
        -   [添加交易选项](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-adding-transaction-options)
    -   [加密机密管理功能](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-functions-encrypted-secrets-management)
        -   [初始化密管实例](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-initialize-a-secretsmanager-instance)
        -   [获取公钥](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-fetch-public-keys)
        -   [加密密钥](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-encrypting-secrets)
        -   [完成主机密钥](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-don-hosted-secrets)
        -   [外链主机密](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-off-chain-hosted-secrets)
    -   [函数响应](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-functions-response-listener)
    -   [公用事业](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-functions-utilities)
        -   [本地函数模拟器](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-local-functions-simulator)
        -   [本地函数测试网](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-local-functions-testnet)
        -   [解码响应字节](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-decoding-response-bytes)
        -   [在 Gist 中存储加密的秘密](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-storing-encrypted-secrets-in-gists)
        -   [构建函数请求 CBOR 字节](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-building-functions-request-cbor-bytes)
    -   [浏览器的使用](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-browser-use)

# 先决条件

安装节点.js 版本 `18.18.0` 或更高 _财务报告和审定财务报表_ Deno 版本 `1.36.0` 或更高级.

链路连接函数需要在创建收费订阅之前签署服务协议条款. 看这个 [开始中](https://docs.chain.link/chainlink-functions/getting-started) 文档中的章节.

## 记账订阅管理

这个 `SubscriptionManager` 类用于管理链链链接计费 [订阅](https://docs.chain.link/chainlink-functions/resources/subscriptions) 用于支付函数请求.

### 订阅

要创建订阅管理器,您需要3个输入的对象.

1.  一个以太.js的例子 [签名类](https://docs.ethers.org/v5/api/signer/#Signer)。确保您拥有 [提供者](https://docs.ethers.org/v5/api/providers/) 连接起来就可以与区块链通信. 您可以使用Infura或Alchemy或其他提供访问源的提供者 [链链函数支持的块链](https://npmcn.com/package/%40chainlink/functions-toolkit/\(https://docs.chain.link/chainlink-functions/supported-networks\))。 。 。 .
2.  相应区块链网络LINK标志的合同地址来自 [这里](https://docs.chain.link/resources/link-token-contracts)。 。 。 .
3.  相应的区块链网络合同的功能路由器的合同地址来自 [这里](https://npmcn.com/package/%40chainlink/functions-toolkit/\(https://docs.chain.link/chainlink-functions/supported-networks\))。 。 。 .

然后通过传递这3个输入来创建订阅管理器的例子.

```
const subscriptionManager = new SubscriptionManager({
  signer,
  linkTokenAddress,
  functionsRouterAddress,
})
```

类被即时化后,必须先被初始化才能被使用. 这是通过运行 `initialize` aync 函数如下:

```
await subscriptionManager.initialize()
```

### 创建订阅

`createSubscription()` 使用函数路由器合同创建新的函数计费订阅, 并返回解析类型订阅 ID 的保证 `number`. 也可以通过消费者合同地址创建订阅,并在单一交易中添加一个授权的消费者.

```
const subscriptionId: number = await subscriptionManager.createSubscription({
  consumerAddress,
})
```

记下你的订阅身份证 因为它会包含你的基金。 在使用Chainlink函数时,您还需要使用订阅ID作为许多操作的输入.

### 基金订阅

`fundSubscription()` 用于为您订阅 LINK 令牌提供资金。 您的订阅必须有 LINK 余额, 才能支付函数请求 。 此外,为了上传DOHosted加密机密,您必须拥有最低的订阅余额. 将加密机密上传到DON的最低订阅余额要求可见于 [链路函数文件](https://docs.chain.link/chainlink-functions/supported-networks)。 。 。 .

为了资助LINK的订阅,确保您已经连接的钱包有足够的LINK. 你可以从中获取一些测试网LINK [水龙头](https://faucets.chain.link/)。 。 。 .

注意所有数值均以 [朱尔斯](https://docs.chain.link/resources/link-token-contracts)1 000 000 000 000 000 000 000 (1e18) Juels等于1 LINK。 不使用 Java 脚本 `number` 以 Juels 为最大安全 JavaScript 整数的计算类型 `2^54 - 1`。 。 。 .

```
const juelsAmount:  BigInt | string = BigInt(2) * BigInt(10**18)
await subscriptionManager.fundSubscription({
  subscriptionId,
  juelsAmount,
})
```

`fundSubscription()` 返回解析到以太.js的保证 [交易接收](https://docs.ethers.org/v5/api/providers/types/#providers-TransactionReceipt)

### 增加/取消核准的消费者合同

一个函数消费者是能够将函数请求发送到链链链甲骨文网络的智能合同,其中甲骨文网络将返回您分散计算的结果. 下文可视化这一请求/答复流程.

![Request/Response Flow](https://docs.chain.link/images/chainlink-functions/requestAndReceive.png) (单位:千美元)[来源](https://npmcn.com/package/%40chainlink/functions-toolkit/\(https://docs.chain.link/chainlink-functions/resources/architecture\))(中文(简体) )

每个订阅可以持有数量有限的授权功能消费者. 参见 [服务限制](https://docs.chain.link/chainlink-functions/resources/service-limits) 以查看每次订阅的消费者合同的最大数量。 这些是消费者合同 被授权使用您的 LINK 余额 支付请求.

```
const addConsumerTxReceipt = await subscriptionManager.addConsumer({
  subscriptionId,
  consumerAddress,
})
```

类似地,您可以取消授权的消费者合同.

```
const removeConsumerTxReceipt = await subscriptionManager.removeConsumer({
  subscriptionId,
  consumerAddress,
})
```

两者 `addConsumer()` 财务报告和审定财务报表 `removeConsumer()` 返回一个能解决以太JS的诺言 [交易接收](https://docs.ethers.org/v5/api/providers/types/#providers-TransactionReceipt)。 。 。 .

### 取消订阅

您可以取消订阅 `cancelSubscription()`。如果有任何待决请求,您必须使用 [超时请求 () 函数](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-timing-out-requests) 在取消订阅之前.

```
const cancelSubTxReceipt = await subscriptionManager.cancelSubscription({ subscriptionId })
```

`cancelSubscription()` 取一个有以下类型定义的配置对象。 可以选择,您可以指定一个钱包地址,订阅的 LINK 余额将退款到该地址. 如果未指明,则默认订阅者地址.

```
type SubCancelConfig = {
  subscriptionId: BigInt | number | string
  refundAddress?: string
  txOptions?: TransactionOptions
}
```

### 转让和接受订阅

转会订阅是一个两阶段的过程. 第一,订阅者提议转让 `requestSubscriptionTransfer()` 并且记录在链上,但所有权在受让人通过调用接受之前不会转让 `acceptTransfer()`。 。 。 .

```
const transferTxReceipt = await subscriptionManager.requestSubscriptionTransfer({
  subscriptionId,
  newOwner, // transferee wallet address
})
```

为了接受所有权转让,受让人需要拥有自己的 `SubscriptionManager` 连接到钱包地址的示例 `newOwner`。然后受让人可以拨打 `acceptSubTransfer()` 方法.

```
const acceptTransferTxReceipt =  await transfereeSubManager.acceptSubTransfer({ subscriptionId })
```

### 获取订阅细节

您可以使用下列方式请求获得特定订阅的详细信息: `getSubscriptionInfo()`。 。 。 .

```
const subscriptionInfo = await getSubscriptionInfo(subscriptionId)
```

这是与块链的只读交互.

返回的许诺解决了类型值 `SubscriptionInfo` 其结构如下:

```
type SubscriptionInfo = {
  balance: BigInt // Represented in Juels (1,000,000,000,000,000,000 (1e18) Juels are equal to 1 LINK)
  owner: string // Subscription owner's address
  blockedBalance: BigInt // Balance reserved to pay for in-flight requests represented in Juels
  proposedOwner: string // Address used for transferring subscriptions
  consumers: string[] // Addresses of consumer contracts allowed to use the subscription
  flags: string // Indicates resource limits for a given subscription (If the default limits are not enough for your use case, contact the Chainlink team by emailing support@chain.link to inquire about a potential increase.)
}
```

### B. 时间安排要求

在某些情况下,如完成费用超过启动请求时所分配的数额,待决请求可能过期,必须人工超时。 这是因为,当一个请求是在飞行中时,支付该计算费的LINK符号在请求的生命周期内被锁定. 通话 `timeoutRequest()` 如果请求到期而得不到满足,则解锁这些资金.

请注意, 您不能在请求过期前超时 。 请求在请求交易确认后300秒内未履行的,请求失效.

要超时请求, 您必须首先获取包含请求交易所释放的请求数据的请求承诺 。 使用 `fetchRequestCommitment` 返回一个承诺 `RequestCommitment` 对象.

```
type RequestCommitment = {
  requestId: string
  coordinator: string
  estimatedTotalCostJuels: BigInt
  client: string
  subscriptionId: number
  callbackGasLimit: BigInt
  adminFee: BigInt
  donFee: BigInt
  gasOverheadBeforeCallback: BigInt
  gasOverheadAfterCallback: BigInt
  timeoutTimestamp: BigInt
}
```

以下是使用 `fetchRequestCommitment`每个网络的DON ID可以在 [链路函数文件](https://docs.chain.link/chainlink-functions/supported-networks)。 。 。 .

```
const provider: ethers.providers.JsonRpcProvider = new ethers.providers.JsonRpcProvider('http://YOUR_RPC_URL.com/')
const requestCommitment: RequestCommitment = await fetchRequestCommitment({
  requestId: '0xYOUR_REQUEST_ID',
  provider,
  functionsRouterAddress: '0xFUNCTIONS_ROUTER_ADDRESS'
  donId: 'DON_ID_FOR_NETWORK',
  toBlock: 100_000, // Optional value for ending block in range to search (defaults to latest block)
  pastBlocksToSearch: 2000, // Optional value for the number of blocks to search before the toBlock (defaults to 1000)
})
```

现在你可以暂停请求了.

```
const timeoutRequestConfig: SubTimeoutConfig = {
  requestCommitments: [ requestCommitment ],
}
const timeoutReceipt: TransactionReceipt | void = await timeoutRequests(timeoutReqConfig)
```

### 估计请求费用

这个 `estimateFunctionsRequestCost()` 方法可用于估算函数请求的成本。 每个网络的DON ID可见于 [链路函数文件](https://docs.chain.link/chainlink-functions/supported-networks)。 。 。 .

```
const estimatedCostInJuels: BigInt = await subscriptionManager.estimateFunctionsRequestCost({
  donId, // ID of the DON to which the Functions request will be sent
  subscriptionId, // Subscription ID
  callbackGasLimit, // Total gas used by the consumer contract's callback
  gasPriceWei, // Gas price in wei
})
```

这种方法会让一个承诺回归 `BigInt` 以Juels为单位的估计费用(1 000 000 000 000 000 (1e18) Juels等于1 LINK).

### 添加交易选项

所有写入块链的订阅管理类方法都可以选择 `TransactionOptions` 对象,其形状如下.

```
export type TransactionOptions = {
  overrides?: Overrides
  confirmations?: number
}
```

覆盖由 Ethers.js 为 [合同功能调用](https://docs.ethers.org/v5/api/contract/contract/#Contract-functionsCall)。 。 。 . `confirmations` 是指在程序之前等待的区块确认的数量.

## 加密机密管理功能

此类帮助您加密和管理您函数源代码使用的秘密 。 秘诀是敏感值,如API密钥或密码等,通常作为环境变量被存储,以避免这些值被公文所暴露.

函数密钥使用阈值公钥加密,需要多个节点参与分散的解密过程,这样节点就可以在DON其他部分未达成共识的情况下解密.

加密的秘密从不直接存储在区块链上,而是可以由DON(`Location.DONHosted`)或存储在位于一个或多个 URL 的 JSON 文件( )`Location.Remote`) (中文(简体) ). 然后,加密的秘密可以被引用,并用于函数请求中.

### 初始化密管实例

要创建密件管理器, 您需要3个输入的对象 .

1.  一个以太.js的例子 [签名类](https://docs.ethers.org/v5/api/signer/#Signer)。确保您拥有 [提供者](https://docs.ethers.org/v5/api/providers/) 与区块链连接。 您可以使用 Infura 或 Alchemy 或其他提供访问权限的类似提供者 [链链函数支持的块链](https://npmcn.com/package/%40chainlink/functions-toolkit/\(https://docs.chain.link/chainlink-functions/supported-networks\))。 。 。 .
2.  函数路由器智能合同的合同地址 [这里](https://npmcn.com/package/%40chainlink/functions-toolkit/\(https://docs.chain.link/chainlink-functions/supported-networks\))。 。 。 .
3.  这个 `donId` 引用您想要使用的 DON 的字符串, 也可以找到 [这里](https://npmcn.com/package/%40chainlink/functions-toolkit/\(https://docs.chain.link/chainlink-functions/supported-networks\))。 。 。 .

```
const secretsManager = new SecretsManager({
  signer,
  functionsRouterAddress,
  donId,
})
```

类被即时化后,必须先被初始化才能被使用. 这是通过运行 `initialize()` 合成方法.

```
await secretsManager.initialize()
```

### 获取公钥

您可以通过查询 [协调员合同](https://docs.chain.link/chainlink-functions/resources/architecture)。 。 。 .

在大多数情况下,您不需要直接调用这种方法 。 其他方法包括: `SecretsManager` 将自动使用此方法.

```
const keys = await secretsManager.fetchKeys()
```

`fetchKeys()` 返回解析对象的许诺,其属性如下:

```
{
  thresholdPublicKey: ThresholdPublicKey
  donPublicKey: string
}
```

阈值公钥是用于保护您 API 机密的一层加密保护。 你的秘密被加密两次 - 首先与 `donPublicKey` 然后与 `thresholdPublicKey`。 。 。 .

正在用 `thresholdPublicKey` 要求节点合作以解密秘密。 这是因为秘密不能用单一的密钥来解密;相反,每个DON节点都有解密密钥的硬度,多个节点必须在分散的进程中聚集来解密. 这改善了安全性,因为没有一个单独的DON节点可以不与其他DON节点合作就解密秘密.

### 加密密钥

秘密通过传送到对象来加密 `encryptSecrets()` 方法.

在为链链函数配置您的秘密时, 您必须满足一些重要条件 .

1.  秘密是可选的。 如果您的自定义函数源代码不需要访问任何秘密值, 您不需要配置机密 .
2.  您的秘密必须在带有字符串密钥/ 值对的对象中传递 :

```
{
  testKey: 'testValue1',
  testKey2: 'testValue2',
  testKey3: 'testValue3',
}
```

```
const encryptedSecrets = await secretsManager.encryptSecrets({
  testKey: 'testValue0'
})
```

`encryptSecrets()` 返回一个以单一属性解决对象的许诺 `encryptedSecrets`。 。 。 .

```
{
  encryptedSecrets: string
}
```

`encryptedSecrets` 包含您秘密的字符串表示,转换为字节,并使用公钥加密.

### 完成主机密钥

加密的秘密可以通过网关URL直接上传到DON,这样在提出链上请求时就可以被使用. 通过发送一个签名的 POST 请求来访问连接到 DON 的 URL 来实现 。 然后,DON维持一个具有最终一致性的分散数据库,使所储存的值能够传播到所有DON节点.

首先,用密码加密秘密 [`encryptSecrets()`](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-encrypting-secrets)然后,通过 `encryptedSecrets` 对象中的六进制字符串 `uploadEncryptedSecretsToDON()` 方法如下。 这个 `slotId` 可以是任何零或以上的整数值,但使用先前使用的插槽ID将覆盖现有数据。 之后 `minutesUntilExpiration`,该条目将从所有的DON节点中删除。 从中获取每个块链网络的有效网关 URL 列表 [链路链接函数文档](https://docs.chain.link/chainlink-functions/supported-networks)。 。 。 .

```
const encryptedSecretsObj = await secretsManager.encryptSecrets({ mySecret: 'secret' })
const mySlotIdNumber = 0
const myExpirationTimeInMinutes = 10

const {
  version, // Secrets version number (corresponds to timestamp when encrypted secrets were uploaded to DON)
  success, // Boolean value indicating if encrypted secrets were successfully uploaded to all nodes connected to the gateway
} = await secretsManager.uploadEncryptedSecretsToDON({
  encryptedSecretsHexstring: encryptedSecretsObj.encryptedSecrets,
  gatewayUrls: [ 'https://exampleGatewayUrl1.com/gateway', 'https://exampleGatewayUrl2.com/gateway', ... ],
  slotId: mySlotIdNumber,
  minutesUntilExpiration: myExpirationTimeInMinutes,
})
```

这个 `uploadEncryptedSecretsToDON()` 方法将返回解析到以下类型对象的许诺.

```
{
  version: number,
  success: boolean,
}
```

这个 `version` 是代表上传加密密钥的版本的数字;是POSIX的时间 `uploadEncryptedSecretsToDON()` 方法已经启动。 这将用于函数请求,以确保使用最新版本的加密机密。 如果一个或多个节点的上传失败, 将会打印一个警告消息, 并且 `success` 字段将会是 `false`。如果所有节点的上传失败,则该方法会出错.

```
const secretsEntriesForGateway = await secretsManager.listDONHostedEncryptedSecrets([ 'https://exampleGatewayUrl1.com/gateway', 'https://exampleGatewayUrl2.com/gateway', ... ])
```

`listDONHostedEncryptedSecrets()` 将返回带有以下形状的阵列,或丢出错误。 如果该方法成功返回, 但是 `error` 字段中包含返回对象的字段,它表明列出机密的请求是成功的,但节点响应之间有差异.

```
{
  result: [
    {
      gatewayUrl: 'https://examplegatewayurl.com/gateway',
      nodeResponses: [
        {
          success: true,
          rows: [
            {
              slot_id: 0,
              version: 0,
              expiration: 100_000,
            },
            ...
          ],
        },
        ...
      ],
    },
    ...
  ],
  error: 'Possible error message <may be undefined>'
}
```

`buildDONHostedEncryptedSecretsReference()` 可用于构建代表 `encryptedSecretsReference` 用于引用 DON 主机加密密件的字节 。 在链上请求中使用DON主机加密机密,并确保 `secretsLocation` 设置为 `Location.DONHosted` (即: `2`) (中文(简体) ).

```
const encryptedSecretsReference: string = secretsManager.buildDONHostedEncryptedSecretsReference({
  slotId: number,
  version: number
})
```

### 外链主机密

加密后的秘密也可以被储存在JSON文件的外链上,而不是被托管在DON上,从而能够更直接地控制加密后的秘密数据的存储方式. DO 节点从一个或多个 URL 获取此文件 .

首先加密这些秘密 [`encryptSecrets()`](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-encrypting-secrets) 然后粘贴或上传到私有的 Github Gist 、 云存储桶或任何其他位置, 这样加密的 JSON 对象就可以被 DON 通过 URL 获取 。 这些秘密是加密的,所以即使JSON文件被托管在一个公开的URL,你的秘密也看不到.

你也可以使用这个 [gist上传工具函数](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-storing-encrypted-secrets-in-gists) 将加密机密字符串上传到 Github Gist 中的 JSON 文件.

作为额外的安全层,指向您的 JSON 文件的 URL 也必须先用 DON Public 密钥加密,然后用作 `encryptedSecretsReference` 在链上请求。 这是为了防止将URL直接暴露给除DON成员以外的任何人,减轻DDOS或其他攻击向量的风险. 您可以构建加密的 URL `encryptSecretsUrls()`。 。 。 .

```
const encryptedSecretsReference: string = await encryptSecretsUrls(secretsUrls: string[])
```

`encryptSecretsUrls()` 返回一个解析到代表秘密 URL 的十六进制字符串的保证,作为空间分隔 URL 的加密字符串.

结果 `encryptedSecretsReference` 然后可以用作构建函数请求的参数之一.

## 函数响应

这个 `ResponseListener` 类提供了一种容易听取对函数请求的链上响应的方法.

要创建请求倾听器,您需要一个包含2个输入的对象 .

1.  一个以太.js的例子 [提供者](https://docs.ethers.org/v5/api/providers/)。 您可以使用 Infura 或 Alchemy 或另一个类似的供应商, 提供访问权限 [链链函数支持的块链](https://npmcn.com/package/%40chainlink/functions-toolkit/\(https://docs.chain.link/chainlink-functions/supported-networks\))。 。 。 .
2.  函数路由器智能合同的合同地址: [这里](https://npmcn.com/package/%40chainlink/functions-toolkit/\(https://docs.chain.link/chainlink-functions/supported-networks\))。 。 。 .

const 响应倾听器 = 新响应倾听器 ({) 提供者, 函数路透社地址, }

要听到对单个函数请求的响应,请使用 `listenForResponseFromTransaction()` 方法. 可以选择提供:

-   超时后,听者会投出一个错误,显示超过时限(默认为5分钟,以毫秒表示)
-   区块确认数(默认1,但注意应为2个或2个以上,以提高对最终性的信心并防范重置)
-   检查请求是否已经包含在链上( 或在链重新连接后被移动)( 默认 2 秒, 但请注意 ) `checkInterval`s 高于块时间可能导致该收听器被挂起,因为响应将在下一次检查前完成. )

```
const response: FunctionsResponse = await responseListener.listenForResponseFromTransaction(
  txHash: string,
  timeoutMs?: number, // milliseconds
  confirmations?: number,
  checkInterval?: number,
)
```

`listenForResponseFromTransaction()` 返回以下结构的响应:

```
{
  requestId: string // Request ID of the fulfilled request represented as a bytes32 hex string
  subscriptionId: number // Subscription ID billed for request
  totalCostInJuels: bigint // Actual cost of request in Juels (1,000,000,000,000,000,000 (1e18) Juels are equal to 1 LINK)
  responseBytesHexstring: string // Response bytes sent to client contract represented as a hex string ("0x" if no response)
  errorString: string // Error sent to client contract interpreted as a UTF-8 string ("" if no error)
  returnDataBytesHexstring: string // Data returned by consumer contract's handleOracleFulfillment method represented as a hex string
  fulfillmentCode: FulfillmentCode // Indicates whether the request was fulfilled successfully or not
}
```

或者,使用请求ID监听,使用 `listenForResponse()` 方法.

**注释:**

1.  请求ID可以在链重置时更改,因此它比请求交易散列更不可靠.
2.  如果这些方法在响应已经上链后被调用,则不会被正确还原.
3.  同步聆听多个响应并没有得到上述方法的支持,并将导致未定义的行为.

```
const response: FunctionsResponse = await responseListener.listenForResponse(
  requestId: string,
  timeout?: number,
)
```

这个 `FunctionsResponse` 将具有以下形状.

```
{
  requestId: string // Request ID of the fulfilled request represented as a bytes32 hex string
  subscriptionId: number // Subscription ID billed for request
  totalCostInJuels: BigInt // Actual cost of request in Juels (1,000,000,000,000,000,000 (1e18) Juels are equal to 1 LINK)
  responseBytesHexstring: string // Response bytes sent to client contract represented as a hex string
  errorString: string // Error bytes sent to client contract represented as a hex string
  returnDataBytesHexstring: string // Data returned by consumer contract's handleOracleFulfillment method represented as a hex string
  fulfillmentCode: FulfillmentCode // Indicates whether the request was fulfilled successfully or not
}
```

以下列出可能的实现代码.

```
{
  FULFILLED = 0, // Indicates that a Function was executed and calling the consumer contract's handleOracleFulfill method was successful
  USER_CALLBACK_ERROR = 1, // Indicates that the consumer contract's handleOracleFulfill method reverted
  // all other codes indicate internal errors
}
```

要为给定的订阅ID收听多个函数响应,请使用 `listenForResponses()` 方法。 当链路链接自动化被用来触发函数请求时,这种方法特别有用. `listenForResponses()` 以订阅 ID 和调用为参数。 召回会得到一个 `FunctionsResponse` 作为争论.

**说明:** 为了避免未定义的行为,确保每次只运行一个收听器方法.

```
const callback = (response: FunctionsResponse) => { console.log(response) }
responseListener.listenForResponses(
  subscriptionId: number | string,
  callback,
)
```

完成响应时,请使用 `stopListeningForResponses` 阻止听众的方法.

```
responseListener.stopListeningForResponses()
```

## 公用事业

### 本地函数模拟器

> 本地函数 JavaScript 模拟器需要将 Deno 安装在您的机器上,并通过 PATH 环境变量访问(通过确保 `deno --version` 页:1. 访问 [deno.land/#安装](https://deno.land/#installation) 用于安装指令.

这个 `simulateScript` 函数用于模拟您自定义的函数 JavaScript 源代码在您的机器上的执行。 这意味着可以在开发过程中使用模拟器来测试你的JavaScript代码. 这对调试很有用,特别是因为 `simulateScript` 函数返回包含任何控制台日志消息或错误的已捕获终端输出.

`simulateScript` 以对象为参数,参数如下。 可以通过全局变量在源代码内访问参数 `args` 财务报告和审定财务报表 `bytesArgs` 输入运行时间. `bytesArgs` 用于传递任意的非字符串 `bytes` 来自您请求的合同的值; 它们将在 JavaScript 运行时间中以十六进制字符串表示 。 您也可以使用此选项添加 API 密钥和其他机密 `secrets` 在运行时作为全局变量被注入的对象.

```
const result = await simulateScript({
  source: string // JavaScript source code
  args?: string[] // Array of string arguments accessible from the source code via the global variable `args`
  bytesArgs?: string[] // Array of bytes arguments, represented as hex strings, accessible from the source code via the global variable `bytesArgs`
  secrets?: Record<string, string> // Secret values represented as key-value pairs
  maxOnChainResponseBytes?: number // Maximum size of the returned value in bytes (defaults to 256)
  maxExecutionTimeMs?: number // Maximum execution duration (defaults to 10_000ms)
  maxMemoryUsageMb?: number // Maximum RAM usage (defaults to 128mb)
  numAllowedQueries?: number // Maximum number of HTTP requests (defaults to 5)
  maxQueryDurationMs?: number // Maximum duration of each HTTP request (defaults to 9_000ms)
  maxQueryUrlLength?: number // Maximum HTTP request URL length (defaults to 2048)
  maxQueryRequestBytes?: number // Maximum size of outgoing HTTP request payload (defaults to 2048 == 2 KB)
  maxQueryResponseBytes?: number // Maximum size of incoming HTTP response payload (defaults to 2_097_152 == 2 MB)
})
```

`simulateScript` 返回以下显示的对对象的解析承诺.

```
{
  responseBytesHexstring?: string // Response bytes which would be returned on-chain, represented as a hex string
  errorString?: string // Error message that would be returned on-chain (either errorString or responseBytesHexstring will be defined)
  capturedTerminalOutput: string // stdout or stderr terminal output captured during simulated execution. Print this to view console.log messages.
}
```

在 JavaScript 源代码中使用的任何第三方进口,都会在运行时同步加载. 因此,在源代码中使用第三方的进口,该源代码由执行 `simulateScript` 函数,您必须使用同步 `import` 函数如下所示.

```
const { format } = await import("npm:date-fns");
return Functions.encodeString(format(new Date(), "yyyy-MM-dd"));
```

```
const { escape } = await import("https://deno.land/std/regexp/mod.ts");
return Functions.encodeString(escape("$hello*world?"));
```

**_注:_** 运行时 `simulateScript`,取决于您的安全设置,您可能会得到一个弹出,询问您是否愿意接受进入的网络连接。 你可以安全地接受或忽略这个弹出,当模拟完成时它应该消失.

**_注:_** 这个 `simulateScript` 函数是一个调试工具,因此不能完美地反映实际的链链链执行环境。 因此,在主网使用之前,必须就一个受支持的测试网块链提出函数请求.

### 本地函数测试网

在本地机上调试智能合同和端到端请求流量时,可以使用 `localFunctionsTestnet` 函数。 这创造了本地测试网RPC节点并带有模拟链链链函数合同. 然后您可以将自己的函数消费者合同部署到这个本地网络,创建和管理订阅,并发送请求. 请求处理将模拟一个实际的DON的行为,在那里执行请求4次,离散的中位响应被传送回消费者合同. (注意链路函数使用以下计算来选择离散中位响应: `const medianResponse = responses[responses.length - 1) / 2]`) (中文(简体) ).

这个 `localFunctionsTestnet` 函数将下列值作为参数.

```
const localFunctionsTestnet = await startLocalFunctionsTestnet(
  simulationConfigPath?: string // Absolute path to config file which exports simulation config parameters
  options?: ServerOptions, // Ganache server options
  port?: number, // Defaults to 8545
)
```

看着 `localFunctionsTestnet` 带入一个 `simulationConfigPath` 字符串作为可选参数。 主要原因是本地测试网无法访问或解密请求交易中提供的加密秘密。 相反,您可以导出一个名为 `secrets` 从 TypeScript 或 JavaScript 文件提供该文件的绝对路径 `simulationConfigPath` 参数。 当 JavaScript 代码在请求中执行时,该文件中指定的秘密将会在 JavaScript 代码中可以访问,而无论 `secretsLocation` 或者说 `encryptedSecretsReference` 在请求交易中发送的值。 这个配置文件也可以包含其他模拟配置参数. 此配置文件的例子如下:.

```
export const secrets: { test: 'hello world' } // `secrets` object which can be accessed by the JavaScript code during request execution (can only contain string values)
export const maxOnChainResponseBytes = 256 // Maximum size of the returned value in bytes (defaults to 256)
export const maxExecutionTimeMs = 10000 // Maximum execution duration (defaults to 10_000ms)
export const maxMemoryUsageMb = 128 // Maximum RAM usage (defaults to 128mb)
export const numAllowedQueries = 5 // Maximum number of HTTP requests (defaults to 5)
export const maxQueryDurationMs = 9000// Maximum duration of each HTTP request (defaults to 9_000ms)
export const maxQueryUrlLength = 2048 // Maximum HTTP request URL length (defaults to 2048)
export const maxQueryRequestBytes = 2048 // Maximum size of outgoing HTTP request payload (defaults to 2048 == 2 KB)
export const maxQueryResponseBytes = 2097152 // Maximum size of incoming HTTP response payload (defaults to 2_097_152 == 2 MB)
```

`localFunctionsTestnet` 返回解决以下类型的承诺.

```
{
  server: Server // Ganache server
  adminWallet: { address: string, privateKey: string } // Funded admin wallet
  getFunds: (address: string, { weiAmount, juelsAmount }: { weiAmount?: BigInt | string; juelsAmount?: BigInt | string }) => Promise<void> // Method which can be called to send funds to any address
  close: () => Promise<void> // Method to close the server
  donId: string // DON ID for simulated DON
  // The following values are all Ethers.js contract types: https://docs.ethers.org/v5/api/contract/contract/
  linkTokenContract: Contract // Mock LINK token contract
  functionsRouterContract: Contract // Mock FunctionsRouter contract
}
```

现在您可以用您喜欢的块链工具连接本地函数测试网RPC节点, 部署函数计算器合同, 即时并初始化`SubscriptionManager`,创建、添加消费者合同并资助订阅、发送请求和使用 `ResponseListener` 在你的机器上听到所有的反应.

参见使用 `localFunctionsTestnet` 输入 [函数 HardHat 启动套件](https://github.com/smartcontractkit/functions-hardhat-starter-kit/blob/main/scripts/startLocalFunctionsTestnet.js)。 。 。 .

**_注:_** 当模拟请求执行时, 根据您的安全设置, 您可能会收到多个弹出, 询问您是否愿意接受导入的网络连接 。 你可以安全地接受或忽略这些弹出 当处决完成时它们应该消失.

**_注:_** 成本估算和其他配置值可能与直播测试网或主网链上的实际值相差很大.

**_注:_** 这个 `localFunctionsTestnet` 函数是一个调试工具,因此不能完美地反映实际的链链链执行环境。 因此,在主网使用之前,必须就一个受支持的测试网块链提出函数请求.

### 解码响应字节

链上响应编码为固态 `bytes` 通常显示为十六进制字符串。 然而,这些十六进制字符串往往需要被解码为可使用类型. 为了将xx字符串解码为人可读值,此包提供了 `decodeResult` 函数。 目前 `decodeResult` 函数支持将十六进制字符串解码为 `uint256`, (中文(简体) ), `int256` 或者说 `string` 数值.

```
const result: BigInt | string = decodeResult(
  resultHexString: string,
  expectedReturnType: ReturnType // 'uint256' | 'int256' | 'string'
)
```

可能的返回值在 `ReturnType` 说明如下.

```
export enum ReturnType {
  uint = 'uint256',
  uint256 = 'uint256',
  int = 'int256',
  int256 = 'int256',
  string = 'string',
  bytes = 'bytes',
}
```

### 在 Gist 中存储加密的秘密

在描述使用 [非链外机密](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-off-chain-hosted-secrets),有人提到加密的机密JSON文件可以在URL中托管,而不是上传到DON主机存储. 其中一个例子是将加密的JSON文件存储在私人的GitHub gist中. 为了支持这种常见的托管方法,您可以使用提供的 `createGist()` 财务报告和审定财务报表 `deleteGist()` 公用事业.

首先,你需要创建一个 [Github 个人访问托肯](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)然后,你可以加密你的秘密 并创建一个焦点.

```
const encryptedSecrets = await secretsManager.encryptSecrets({
  mySecret: 'secretValue'
})
```

由 : [加密密钥](https://npmcn.com/package/%40chainlink/functions-toolkit/\(#encrypting-secrets\)) 显示对象.

```
{
 "encryptedSecrets": '0x1234567890abcdef', // some long hex string
}
```

现在,你可以将这个对象字符串化,并用它来创建一个要旨.

```
const gistURL = await createGist(githubApiToken: string, JSON.stringify(encryptedSecrets)) // encryptedSecrets must be a string, not an object.
```

这个 `gistURL` 本身必须通过调用加密 [加密SecretsUrls ()](https://npmcn.com/package/%40chainlink/functions-toolkit/#readme-off-chain-hosted-secrets) 以产生 `encryptedSecretsReference` 用于提出函数请求.

您也可以使用 `deleteGist()`。 。 。 .

```
const success: boolean = await deleteGist(githubApiToken: string, gistURL: string)
```

此函数将返回一个下定决心的承诺 `true` 如果删除成功,则会出错.

### 构建函数请求 CBOR 字节

而不是执行 [函数链上请求的 CBOR 编码](https://docs.chain.link/chainlink-functions/api-reference/functions#encodecbor) 在功能消费者合同中,也可以生成CBOR 编码,以节省气体。 然后,生成的编码为CBOR字节的可被用于在链上请求时. 您可以将编码请求存储在 `bytes` 在消费者合同中存储变量,或者通过通过 CBOR 编码请求对象启动函数请求 `bytes` 直接进入 `_sendRequest()` 方法 [是从 `FunctionsClient.sol`](https://docs.chain.link/chainlink-functions/api-reference/functions-client) 。 。 。 .

请注意,当编码一个请求时, `args` 或者说 `bytesArgs` 无法添加到链上的请求中。 这是CBOR编码的一个限制,因为它的结构不可改变.

要构建 CBOR 编码函数请求离链字节,请使用 `buildRequestCBOR()` 函数如下.

```
const functionsRequestBytesHexString: string = buildRequestCBOR({
  codeLocation: number  // Must be 0 for inline source code.  No other values are supported at this time.
  secretsLocation?: number // Must be 1 for Remote or 2 for DONHosted secrets.  No other values are supported at this time.
  codeLanguage: number // Must be 0 for JavaScript.  No other values are supported at this time.
  source: string // JavaScript source code
  encryptedSecretsReference?: string // Hex string representing an encrypted secrets URLs or DON hosted encrypted secrets reference
  args?: string[] // Array of string arguments
  bytesArgs?: string[] // Array of bytes arguments, represented as hex strings
})
```

## 浏览器的使用

这个软件包也可以被用在大多数现代的网页浏览器中. 您可以在您的前端应用程序中导入软件包, 并按后端节点Js/ Deno 环境使用 API .

## 常见问题

### @chainlink/functions-toolkit 是什么？

国家防范机制软件包,其功能集可用于与链路连接函数合作\.

### 如何安装 @chainlink/functions-toolkit？

在项目目录运行 npm install @chainlink/functions-toolkit，或使用 pnpm add / yarn add / bun add。

### @chainlink/functions-toolkit 支持 TypeScript 吗？

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

### @chainlink/functions-toolkit 支持 ESM 还是 CommonJS？

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

### @chainlink/functions-toolkit 可以商用吗？

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

### @chainlink/functions-toolkit 的下载量有多少？

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

### @chainlink/functions-toolkit 还在维护吗？

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

