eForest Agent Skills:为AI Agent与开发者打造的aelf区块链操作工具集
1. 项目概述:eForest Agent Skills,一个为aelf区块链生态赋能的AI Agent工具集
如果你正在aelf区块链上构建NFT市场、游戏或者任何需要与链上资产交互的应用,并且希望将这些复杂的链上操作能力无缝集成到AI助手(比如Claude、Cursor的AI功能)或者你自己的自动化脚本里,那么你很可能已经遇到了一个核心痛点:如何让一个“不懂代码”的AI,或者一个希望快速上手的开发者,安全、可靠地执行购买SEED、创建NFT、上架交易这些操作?这正是
eforest-finance/eforest-agent-skills
这个项目要解决的问题。它不是一个简单的SDK,而是一个将aelf和eForest平台的核心业务能力(特别是Symbol市场和Forest NFT领域)封装成标准化“技能”(Skills)的工具包,并通过CLI、MCP Server和SDK三种方式暴露出来,让集成变得异常简单。
简单来说,你可以把它理解为一套为AI Agent量身定做的“区块链操作手柄”。过去,要让AI调用智能合约,你需要编写复杂的适配层,处理私钥安全、交易构造、错误处理等一系列繁琐问题。现在,这个项目把这些都标准化了。它定义了从“检查NFT名称是否可用”到“批量创建NFT”、“接受报价成交”等一整套工作流技能,每个技能都有清晰的输入输出规范。这意味着,无论是你在终端里用命令行快速测试,还是在Claude Desktop里直接告诉AI“帮我把这个NFT上架,定价1.2 ELF”,抑或是在你自己的Node.js后端服务里以编程方式调用,体验都是一致的、安全的。
这个项目的核心价值在于“降低门槛”和“统一体验”。对于开发者,它提供了开箱即用的高质量TypeScript SDK和清晰的错误反馈;对于AI应用构建者,它通过MCP(Model Context Protocol)协议,使得Claude、Cursor等能直接理解并使用这些区块链技能,无需额外的模型微调。而它提出的“服务分级”(P0/P1/P2)和“优雅降级”机制,更是体现了其设计上的成熟度,确保核心交易环路(P0)永远稳定可用,而实验性功能(P2)可以独立控制,不影响主流程。
1.1 核心架构与设计哲学
这个项目的架构设计清晰地反映了其“技能化”和“分层治理”的思想。整个代码库不是一个大一统的庞杂系统,而是围绕“技能注册表”和“统一调度器”构建的模块化结构。
技能注册表
是核心的大脑。它维护了一个所有可用技能的清单,每个技能不仅仅是一个函数名,而是一个完整的定义,包括:技能的唯一标识符(如
aelf-forest-list-item
)、输入参数的JSON Schema(严格定义参数类型、是否必填、枚举值等)、输出格式、以及该技能所属的业务域和服务级别(P0/P1/P2)。当CLI、MCP Server或SDK接收到一个请求时,调度器会首先查询这个注册表,找到对应的技能执行器。
统一调度器 是执行引擎。它负责接收请求,根据技能标识从注册表中找到对应的实现,然后进行参数验证、环境配置解析、签名人上下文处理,最后调用底层的执行器。执行器可能是直接与aelf区块链RPC交互的合约调用,也可能是调用eForest后端API的HTTP请求。调度器的一个重要职责是封装统一的响应信封和错误契约,无论底层操作成功还是失败,上层调用者收到的数据结构都是可预测的。
这种设计带来了几个关键优势:
-
可发现性
:通过
listForestSkills()这样的SDK函数,可以动态获取所有可用技能,便于构建动态的用户界面或AI提示词。 - 可维护性 :新增一个技能,只需要在注册表中添加定义,并实现对应的执行器即可,不会影响其他技能。
- 安全性 :统一的参数验证层可以防止无效或恶意输入进入底层系统。统一的错误处理也使得问题排查更简单。
环境配置的优先级设计
是另一个亮点。它定义了一个清晰的配置解析顺序:函数调用参数 > 命令行参数 > 环境变量 >
.env
文件 > 远程配置 > 代码默认值。这种设计确保了最大的灵活性。例如,在自动化脚本中,你可以通过SDK调用参数硬编码RPC地址;在开发时,可以使用
.env
文件管理私钥;在部署到不同环境(测试网/主网)时,通过一个
EFOREST_NETWORK
环境变量就能切换所有预设配置。这避免了配置散落各处、优先级混乱的常见问题。
签名人上下文的跨技能共享
机制对于AI Agent场景至关重要。想象一下,用户通过AI助手执行一连串操作:先创建NFT集合,再铸造几个NFT,最后上架其中一个。如果每个操作都需要用户重新输入私钥,体验将是灾难性的。这个项目通过“活跃上下文”文件(默认位于
~/.portkey/skill-wallet/context.v1.json
)来解决。一旦用户在某个会话中授权了钱包(通过输入密码解密等),这个上下文就会被保存,后续的所有写操作技能都会自动尝试从这个上下文中获取签名人信息,实现了会话内的无缝体验。这背后是Portkey的CA(合约账户)或EOA(外部账户)钱包体系的支撑,提供了比单纯私钥文件更安全的管理方式。
2. 核心技能域解析:从Symbol市场到Forest NFT生态
项目将能力主要划分为两大域:Symbol市场和Forest NFT。理解这两个域的区别和联系,是正确使用这些技能的关键。
2.1 Symbol-Market域:资产发行的基石
在aelf区块链上,创建同质化代币(FT)或非同质化代币(NFT)之前,你需要一个独特的符号。这个域的技能围绕“SEED”展开。SEED是一种特殊的NFT,代表了创建特定符号的权利。你可以把它理解为“域名注册”或“商标申请”。
-
aelf-forest-get-price-quote(P0) : 这是所有操作的起点。在购买SEED或创建资产前,调用此技能可以预估所需的ELF代币数量(包括SEED费用和网络Gas费)。 实操要点 :务必在关键操作前进行“干跑”,这能避免因余额不足导致的交易失败,并让用户对成本有清晰预期。 -
buy-seed: 购买指定符号的SEED。这里有一个 重要经验 :项目文档中提到的--force 2参数,意思是“最多花费2 ELF来竞拍这个SEED”。在拍卖机制下,设置一个合理的上限可以防止在激烈竞价中付出过高成本。 -
create-token: 在获得SEED后,使用它来创建FT或NFT资产。这里需要仔细填写代币符号、全称、总供应量、小数位数等元数据。 特别注意--issue-chain参数,它决定了资产创建在哪个侧链上(如tDVV)。aelf的多侧链架构允许你将资产创建在最适合你应用生态的链上,以优化性能和费用。 -
issue-token: 资产创建后,初始供应量是锁定的。此技能用于将代币从发行者账户“铸造”并发送到目标地址。对于NFT,这通常对应着“铸造”单个或多个NFT物品到用户钱包。
这个域的技能设计体现了“先检查,后执行”的谨慎原则,并且通过“干跑”模式提供了完美的预览功能,非常适合集成到需要用户确认的交互流程中。
2.2 Forest域:NFT生命周期的全栈管理
这是项目的重心,涵盖了NFT从诞生到流通的全生命周期。技能被分为P0(核心交易循环)、P1(增长功能)和P2(扩展功能)三个优先级,这为项目的迭代和稳定性管理提供了框架。
P0核心交易循环 是任何NFT市场都必须稳定、高效运行的闭环。它模拟了一个用户从创建到完成一次交易的基本路径:
-
创建集合与物品
:
create-collection定义NFT系列(如“ CryptoPunks”),create-item或batch-create-items则在系列下铸造具体的NFT。 批量创建 对于游戏道具空投或艺术系列发行至关重要,它能显著降低Gas成本并提升效率。 -
上架与购买
:
list-item将NFT以固定价格挂单出售;buy-now则允许买家直接以标价购买。这是最直接的交易方式。 -
报价与协商
:
make-offer允许潜在买家对未上架或已上架的NFT提出一个报价(可以是不同的价格或代币)。卖家可以通过deal-offer接受某个报价,从而达成交易。cancel-offer和cancel-listing则提供了撤销操作的灵活性。这个“报价”系统实现了更复杂的市场机制。 -
资产转移与询价
:
transfer-item用于钱包间的NFT赠送或转移;get-price-quote为上述几乎所有写操作提供费用预估。
P1增长功能 引入了更高级的市场机制,旨在提升活跃度和用户参与。
-
拍卖
:
place-bid和相关的合约技能,支持英式拍卖等模式。 -
空投
:
claim-drop和query-drop,用于面向特定用户群体的NFT分发活动。 -
白名单
:
whitelist-manage和whitelist-read,为预售、社区奖励等场景提供权限管理。
P2扩展功能 则展望了更前沿的集成,如AI生成NFT、小程序交互、用户档案更新等。这些技能目前可能处于实验阶段,但通过项目的“服务门控”机制,可以安全地引入而不影响核心服务的稳定性。
2.3 方法技能与工作流技能的区分
细心的你会注意到,技能列表中有“Workflow”和“Method”两种。这是项目一个精妙的设计分层。
- Workflow技能 :面向最终用户或高级AI指令。它们对应一个完整的、有业务意义的操作,如“上架NFT”。内部可能会按顺序调用多个合约方法或API,并处理相关的错误和状态更新。你通常直接与这类技能交互。
-
Method技能
:面向开发者或需要精细控制的场景。它们对应一个单一的合约调用或API端点,如
aelf-forest-contract-market。当Workflow技能无法满足你的定制需求时,你可以直接调用这些底层Method技能进行组合。
这种分层既保证了易用性,又保留了灵活性。
3. 三种集成方式深度实操:CLI、MCP Server与SDK
3.1 CLI:开发者的快速测试与脚本利器
命令行接口是最直接、最透明的交互方式。它非常适合做快速原型验证、编写自动化脚本或进行故障排查。
安装与配置 :
# 1. 克隆项目并安装依赖
git clone https://github.com/eforest-finance/eforest-agent-skills.git
cd eforest-agent-skills
bun install
# 2. 复制环境变量模板并配置
cp .env.example .env
# 编辑 .env 文件,至少设置网络和签名人信息
# 例如,对于测试网EOA账户:
EFOREST_NETWORK=testnet
AELF_PRIVATE_KEY=你的测试网私钥
核心命令实战 : 假设我们要在测试网上创建一个名为“MYART-001”的NFT。
# 步骤1:干跑预览,检查名称和费用
bun run cli aelf-forest-get-price-quote --symbol MYART-001 --include tokenData,txFee --env testnet
# 输出会显示预估的ELF消耗,确认无误后进行下一步。
# 步骤2:购买SEED(假设符号可用)
bun run cli buy-seed --symbol MYART-001 --issuer 你的地址 --force 0.5 --env testnet
# 这会发起一笔链上交易。使用`--dry-run`可以先模拟不真正执行。
# 步骤3:创建NFT集合(如果需要新集合)
bun run cli aelf-forest-create-collection --symbol MYART --name "My Art Collection" --env testnet
# 步骤4:在集合下创建NFT物品
bun run cli aelf-forest-create-item --collection-symbol MYART --item-symbol MYART-001 --name "My First Art" --env testnet
注意事项 :
-
私钥安全
:永远不要将包含真实私钥的
.env文件提交到版本控制系统。在生产环境中,应使用环境变量或安全的密钥管理服务。 -
网络选择
:明确指定
--env testnet或--env mainnet。默认是主网,误操作可能导致真实资产损失。 -
干跑习惯
:对于任何写操作(
buy-seed,create-item,list-item等),养成先加--dry-run参数预览的习惯。这能捕获参数错误并估算费用,避免无谓的链上交易失败和Gas浪费。
3.2 MCP Server:让AI助手成为你的区块链代理
MCP是Anthropic提出的一个协议,旨在让AI模型能够安全、可控地调用外部工具。这是本项目最革命性的部分。通过配置MCP Server,你可以让Claude Desktop、Cursor IDE等直接使用这些区块链技能。
一键式设置 : 项目提供了极其便捷的设置脚本。
# 为 Claude Desktop 配置
bun run setup claude
# 为 Cursor IDE(项目级别)配置
bun run setup cursor
# 为 Cursor IDE(全局级别)配置
bun run setup cursor --global
运行后,这些AI应用会自动在其MCP配置中添加指向本地技能服务器的条目。
工作原理
:当你运行
bun run setup claude
后,脚本会向Claude Desktop的配置文件(通常位于
~/Library/Application Support/Claude/claude_desktop_config.json
)添加一个MCP服务器配置。这个服务器启动的命令就是
bun run src/mcp/server.ts
。当你在Claude中输入“帮我在eForest测试网上创建一个叫‘DragonEgg’的NFT集合”时,Claude会通过MCP协议向这个本地服务器发送请求,服务器调用对应的
aelf-forest-create-collection
技能,并将结果返回给Claude,Claude再以自然语言呈现给你。
IronClaw集成详解 : 对于更注重安全和权限管理的OpenClaw/IronClaw框架,项目也提供了专门支持。
# 安装为受信任技能(保留写权限)
bun run setup ironclaw
这里有一个
关键陷阱
需要规避:IronClaw默认会将安装的技能降级为“只读”工具。这意味着,如果你通过常规方式安装,AI将只能查询NFT价格,而不能执行上架、购买等写操作。项目的
setup ironclaw
命令通过两个步骤规避了这个问题:1)在MCP服务器列表中添加一个标准服务器;2)将技能的描述文件(
SKILL.md
)复制到受信任的技能目录。这样,技能既能被IronClaw识别,又保留了其完整的读写能力。
务必不要
直接从IronClaw的“已安装技能”目录安装此包,那会导致写操作失效。
手动配置(高级) : 如果一键设置不生效,或者你需要更定制化的配置(如使用CA钱包),可以手动编辑MCP配置文件。
{
"mcpServers": {
"eforest-agent": {
"command": "bun",
"args": ["run", "/ABSOLUTE/PATH/TO/eforest-agent-skills/src/mcp/server.ts"],
"env": {
"PORTKEY_PRIVATE_KEY": "your_manager_key",
"PORTKEY_CA_HASH": "your_ca_hash",
"PORTKEY_CA_ADDRESS": "your_ca_address",
"EFOREST_NETWORK": "testnet"
}
}
}
}
实操心得
:在MacOS或Linux上,获取绝对路径的一个简单方法是进入项目目录后运行
pwd -P
命令。确保路径正确是手动配置成功的关键。
3.3 SDK:在自己的应用中嵌入区块链能力
对于想要在自己的Node.js/TypeScript后端服务、机器人或前端(需通过后端代理)中集成eForest功能的开发者,SDK是最佳选择。它提供了类型安全的函数调用和完整的异步Promise支持。
基础使用 :
import { dispatchForestSkill, getNetworkConfig } from '@eforest-finance/agent-skills';
async function listMyNFT() {
// 1. 获取网络配置(会自动读取环境变量)
const config = await getNetworkConfig({ env: 'testnet' });
// 2. 调用技能
const result = await dispatchForestSkill(
'aelf-forest-api-nft', // 技能名称
{
env: 'testnet',
payload: {
action: 'fetchMyNFTs',
params: {
address: 'your_wallet_address',
chainId: 'tDVV',
page: 1,
limit: 20
}
}
},
{ config } // 传入可选配置对象
);
// 3. 处理统一响应信封
if (!result.success) {
console.error(`操作失败 [${result.code}]: ${result.message}`);
if (result.maintenance) {
console.log('该服务正在维护中');
}
// 可以根据 result.code 进行特定的错误处理
return;
}
console.log('我的NFT列表:', result.data);
// result.data 的类型会根据技能定义自动推断(如果使用TypeScript)
}
高级模式:使用共享配置与上下文
:
在实际应用中,你通常不希望在每个函数调用中都传递
env
和
config
。你可以初始化一个共享的客户端实例。
import { createForestClient } from '@eforest-finance/agent-skills';
// 在应用启动时创建客户端
const forestClient = createForestClient({
defaultEnv: 'testnet',
// 可以在这里覆盖任何默认配置,如RPC URL
overrides: {
rpcUrls: {
AELF: 'https://your-custom-rpc.aelf.io',
},
},
});
// 在业务代码中直接使用客户端
async function createAndListNFT(symbol, name) {
// 创建集合
const createResult = await forestClient.dispatch('aelf-forest-create-collection', {
symbol: symbol,
name: name,
});
if (!createResult.success) throw new Error(createResult.message);
// 创建物品
const itemResult = await forestClient.dispatch('aelf-forest-create-item', {
collectionSymbol: symbol,
itemSymbol: `${symbol}-001`,
name: `${name} #1`,
});
if (!itemResult.success) throw new Error(itemResult.message);
// 上架物品
const listResult = await forestClient.dispatch('aelf-forest-list-item', {
symbol: `${symbol}-001`,
quantity: 1,
priceSymbol: 'ELF',
priceAmount: 0.5,
durationJson: JSON.stringify({ days: 7 }), // 注意:参数需要序列化为JSON字符串
chain: 'AELF',
});
return listResult;
}
重要提示
:注意
durationJson
这样的参数,它需要传递一个JSON字符串,而不是一个对象。这是因为技能接口通过MCP暴露时,需要处理简单的标量类型。务必查阅具体技能的Schema定义或源码来确认参数格式。
4. 配置、错误处理与服务治理实战指南
4.1 环境变量与配置优先级详解
项目的配置系统非常灵活,但也需要清晰理解其优先级,否则容易踩坑。以下是一个完整的配置解析案例,帮助你理解不同场景下如何设置。
场景一:本地开发
使用
.env
文件是最方便的。在项目根目录创建
.env
:
# .env
EFOREST_NETWORK=testnet
AELF_PRIVATE_KEY=0x你的测试网私钥
# 如果你想覆盖默认的测试网RPC
EFOREST_RPC_URL_TDVV=https://tdvv-test-node.eforest.finance
此时,任何通过CLI或SDK(未显式指定参数)发起的调用,都会使用测试网和这个私钥。
场景二:CI/CD流水线 在GitHub Actions或Jenkins中,你绝不会提交私钥文件。应该使用仓库的Secrets功能设置环境变量。
# GitHub Actions .yml 示例
- name: Run E2E Tests
env:
EFOREST_NETWORK: testnet
AELF_PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }}
run: bun test:e2e:smoke
在这里,环境变量的优先级高于
.env
文件(如果存在),因此会使用Secrets中的私钥。
场景三:多环境SDK调用 在你的后端服务中,你可能需要根据请求动态选择网络。
async function handleUserRequest(userEnv: 'mainnet' | 'testnet', userOperation: string) {
// 通过函数参数传入,这是最高优先级,会覆盖所有环境变量和.env设置
const result = await dispatchForestSkill(
`aelf-forest-${userOperation}`,
{
env: userEnv, // 动态指定环境
payload: { /* ... */ },
},
{
// 甚至可以动态覆盖RPC
config: {
rpcUrls: {
AELF: userEnv === 'testnet' ? CUSTOM_TEST_RPC : CUSTOM_MAIN_RPC,
},
},
}
);
return result;
}
配置陷阱排查清单 :
-
问题
:调用一直返回网络错误或超时。
-
检查1
:确认
EFOREST_NETWORK设置正确(mainnet/testnet)。大小写敏感。 -
检查2
:检查
EFOREST_RPC_URL_*对应的链RPC是否可访问。可以尝试用curl命令直接调用RPC端点。
-
检查1
:确认
-
问题
:交易失败,提示签名错误或权限不足。
-
检查1
:确认
AELF_PRIVATE_KEY或PORTKEY_*系列变量设置正确,且对应账户在目标网络上有足够的ELF支付Gas费。 -
检查2
:如果使用CA钱包,确保
PORTKEY_CA_ADDRESS、PORTKEY_CA_HASH和PORTKEY_PRIVATE_KEY(Manager Key)三者匹配。
-
检查1
:确认
-
问题
:技能返回
SERVICE_DISABLED。-
检查
:查看是否设置了
EFOREST_DISABLED_SERVICES或EFOREST_DISABLE_ALL_SERVICES环境变量,意外禁用了所需服务。
-
检查
:查看是否设置了
4.2 统一的错误响应契约与处理策略
所有通过
dispatchForestSkill
调用的技能,无论成功与否,都会返回一个结构统一的信封对象。正确处理这个响应是构建健壮应用的关键。
成功响应结构 :
{
"success": true,
"code": "OK",
"data": { /* 技能特定的返回数据 */ },
"warnings": [], // 可能包含非致命的警告信息,如“Gas费预估可能偏低”
"traceId": "req_abc123" // 用于服务端日志追踪,排查问题时非常有用
}
失败响应结构 :
{
"success": false,
"code": "INSUFFICIENT_BALANCE",
"message": "Issuer address ELF balance is insufficient for token creation.",
"maintenance": false, // 是否因为服务维护而失败
"retryable": true, // 指示该错误是否可以通过重试解决(如网络超时)
"traceId": "req_def456",
"details": { // 附加的错误详情,可能包含链上交易哈希、验证错误字段等
"requiredBalance": "1.5 ELF",
"currentBalance": "0.8 ELF"
}
}
基于错误码的处理策略
:
你需要根据
code
字段来决定如何应对。
-
INVALID_PARAMS: 输入参数错误。应检查并提示用户修正输入。details字段通常会指出具体是哪个参数有问题。 -
SERVICE_DISABLED或MAINTENANCE: 服务被禁用或维护中。应向用户显示友好提示,并可能禁用相关功能按钮。 注意 :MAINTENANCE是SERVICE_DISABLED的一个子状态,专门用于计划内维护。 -
INSUFFICIENT_BALANCE: 余额不足。应引导用户充值。 -
NETWORK_ERROR或TIMEOUT: 网络问题。如果retryable为true,可以实现指数退避重试逻辑。 -
TX_FAILED: 交易上链失败。details中可能包含transactionId或error信息,可用于进一步查询链上状态。
最佳实践
:在你的应用层封装一个通用的技能调用函数,集中处理错误响应,将技术性的错误码转换为用户友好的提示信息,并根据
retryable
和
maintenance
决定UI状态。
4.3 服务门控与优雅降级:保障核心体验
对于一款面向生产环境的产品,并非所有功能都需要7x24小时可用。实验性的AI生成功能(P2)出问题,不应该影响核心的NFT买卖(P0)。项目的服务门控系统正是为此而生。
通过环境变量控制服务状态 :
# 示例1:禁用整个AI相关域,但其他功能正常
export EFOREST_DISABLED_SERVICES="forest.ai.*"
# 此时,调用 `aelf-forest-ai-generate` 会立即返回 `SERVICE_DISABLED`,根本不会执行实际逻辑。
# 示例2:将市场相关技能置于维护模式
export EFOREST_MAINTENANCE_SERVICES="forest.market.*"
# 此时,调用 `aelf-forest-list-item` 会返回 `MAINTENANCE` 错误,前端可以显示“市场功能升级中,请稍后再试”。
# 示例3:精细控制到具体技能
export EFOREST_SERVICE_FOREST_MARKET_WORKFLOW_BUY_NOW=false
# 仅禁用“立即购买”工作流,其他市场功能如“报价”仍可用。
# 示例4:核武器开关(极端情况)
export EFOREST_DISABLE_ALL_SERVICES=true
# 所有森林技能将被禁用。通常用于紧急情况或全局维护。
设计模式启示
:在你的业务代码中,也可以借鉴这种模式。在调用技能前,可以先检查其服务状态(虽然目前SDK未直接暴露查询状态的函数,但你可以通过尝试调用并捕获
SERVICE_DISABLED
错误来模拟)。在前端UI上,可以根据配置动态隐藏或禁用某些功能入口,实现优雅降级。
API路由映射配置
:
对于
aelf-forest-api-*
这类方法技能,它们需要知道后端API的具体端点。默认配置已经内置了eForest官方地址,但如果你需要指向自建的后端或测试环境,就需要使用
EFOREST_FOREST_API_ACTION_MAP_JSON
。
export EFOREST_FOREST_API_ACTION_MAP_JSON='{
"aelf-forest-api-market": {
"fetchTokens": {
"method": "GET",
"url": "https://your-staging-api.eforest.finance/app/market/tokens",
"auth": true
}
}
}'
这是一个强大的功能,尤其适用于企业部署或定制化开发。 注意 :环境变量中的JSON需要是压缩后的单行字符串,或者通过配置文件加载。
5. 测试策略与持续集成
一个健壮的工具库离不开完善的测试。
eforest-agent-skills
提供了清晰的测试脚本,确保代码质量和稳定性。
本地运行测试套件 :
# 运行所有单元测试和集成测试(不包含e2e)
bun test
# 仅运行单元测试(快速反馈)
bun test:unit
# 运行集成测试(可能需要本地或测试网节点)
bun test:integration
# 运行端到端冒烟测试(干跑模式,CI门禁)
bun test:e2e:smoke
# 运行完整的端到端测试(干跑模式)
bun test:e2e:full # 或 bun test:e2e
关键点
:
e2e
测试套件被设计为“干跑”模式,这意味着它们会模拟交易但不会真正签名和广播到链上。这保证了测试的确定性和速度,且不需要消耗真实的测试币,非常适合在CI/CD流水线中作为质量门禁。
为你的技能编写测试
:
如果你要为项目贡献新的技能,编写测试是必须的。测试文件通常位于
__tests__/
目录下,与源码结构对应。
// __tests__/core/forest/workflow/create-item.test.ts
import { describe, it, expect, beforeEach } from 'bun:test';
import { dispatchForestSkill } from '../../../src';
import { mockAelfClient } from '../../mocks'; // 假设有模拟客户端
describe('aelf-forest-create-item workflow', () => {
beforeEach(() => {
// 在每个测试前设置模拟或清理环境
});
it('should validate required parameters', async () => {
const result = await dispatchForestSkill('aelf-forest-create-item', {
env: 'testnet',
payload: { /* 缺少 collectionSymbol */ },
});
expect(result.success).toBe(false);
expect(result.code).toBe('INVALID_PARAMS');
expect(result.message).toContain('collectionSymbol');
});
it('should dry-run successfully with valid input', async () => {
// 模拟一个成功的干跑响应
const result = await dispatchForestSkill('aelf-forest-create-item', {
env: 'testnet',
payload: {
collectionSymbol: 'TEST-COL',
itemSymbol: 'TEST-COL-001',
name: 'Test Item',
// ... 其他必要参数
},
});
expect(result.success).toBe(true);
// 可以进一步断言返回的数据结构
});
});
CI/CD集成示例
:
项目的
.github/workflows/test.yml
展示了标准的测试流水线。在你的项目中,可以借鉴如下步骤:
-
代码检查
:运行
bun lint。 -
类型检查
:运行
bun run type-check(如果项目有)。 -
单元与集成测试
:运行
bun test。 -
端到端冒烟测试
:在每次Pull Request时运行
bun test:e2e:smoke,作为合并前的必须通过项。 -
完整端到端测试
:在代码合并到主分支后,运行
bun test:e2e:full,进行更全面的验证。
通过这样分层级的测试策略,既能保证开发效率(单元测试快),又能保障核心功能在集成后的稳定性(e2e测试全)。
更多推荐



所有评论(0)