感谢你考虑为 NofyAI 做出贡献!
如果你发现了 Bug,请在 GitHub Issues 中报告,包含以下信息:
- 标题:简明扼要的描述
- 环境:Node.js 版本、操作系统、浏览器等
- 重现步骤:详细的步骤说明
- 期望行为:你期望发生什么
- 实际行为:实际发生了什么
- 截图:如果适用,添加截图帮助解释问题
- 日志:相关的控制台输出或错误日志
如果你有新功能的想法,请先在 Issues 中讨论:
- 检查是否已有相关的 Issue
- 创建新 Issue 并打上
enhancement标签 - 清楚描述功能的用途和预期行为
- 等待维护者反馈后再开始编码
-
Fork 仓库
# 在 GitHub 上点击 Fork 按钮 git clone https://github.com/你的用户名/nofyai.git cd nofyai
-
创建分支
git checkout -b feature/amazing-feature # 或 git checkout -b fix/bug-description -
安装依赖
npm install
-
配置开发环境
cp config.json.example config.json cp .env.local.example .env.local # 编辑配置文件 -
进行开发
- 编写代码
- 确保遵循代码规范
- 添加必要的注释
-
测试
npm run lint # 检查代码风格 npm run build # 确保构建成功 npm run dev # 本地测试
-
提交改动
git add . git commit -m "feat: 添加某某功能" # 提交信息格式请参考下方说明
-
推送分支
git push origin feature/amazing-feature
-
创建 Pull Request
- 在 GitHub 上打开你的 Fork 仓库
- 点击 "New Pull Request"
- 填写 PR 描述,说明你的改动
使用 Conventional Commits 规范:
<类型>(<范围>): <描述>
[可选的正文]
[可选的脚注]
类型:
feat: 新功能fix: Bug 修复docs: 文档更新style: 代码格式(不影响代码运行)refactor: 重构(既不是新功能也不是 Bug 修复)perf: 性能优化test: 测试相关chore: 构建过程或辅助工具的变动
示例:
feat(ai): 添加 Claude AI 模型支持
- 实现 Anthropic API 集成
- 添加模型配置选项
- 更新 AI 提示词模板
Closes #123
fix(aster): 修复 Aster DEX 签名错误
- 修正私钥格式处理
- 更新 ethers.js 钱包签名逻辑
- 添加错误提示
Fixes #456
- 严格模式:启用 TypeScript strict mode
- 类型定义:为所有函数和变量提供明确的类型
- 避免
any:尽量使用具体类型 - 接口优先:使用
interface而非type(除非需要联合类型)
- 函数组件:使用函数组件和 Hooks
- Props 类型:为所有组件定义 Props 接口
- 命名规范:组件使用 PascalCase,文件名与组件名一致
- 避免内联样式:使用 Tailwind CSS 类名
- Tailwind CSS:优先使用 Tailwind 工具类
- 响应式设计:使用
sm:、md:、lg:前缀 - 自定义类:必要时在
globals.css中定义 - 避免
!important:除非绝对必要
- 路径别名:使用
@/导入模块(如@/lib/api) - 相对路径:避免深层相对路径(
../../../) - 单一职责:每个文件只做一件事
- 合理命名:文件名清晰描述其内容
如果你想添加对新 AI 模型的支持:
-
在
/lib/ai.ts中添加模型处理函数async function getNewModelDecision( context: TradingContext, apiKey: string, customUrl?: string ): Promise<AIResponse> { // 实现 API 调用逻辑 }
-
在
getFullDecision()中添加分支case 'newmodel': return await getNewModelDecision(context, config.newmodel_api_key);
-
更新类型定义
/types/index.tsexport interface TraderConfig { // ... 其他字段 newmodel_api_key?: string; newmodel_model_name?: string; }
-
更新配置文件示例
config.json.example -
更新文档:README.md 和 CLAUDE.md
当前系统仅支持 Aster DEX。如需添加其他交易所:
-
创建交易所客户端
/lib/exchanges/newexchange.tsexport class NewExchangeTrader { async getBalance(): Promise<AccountInfo> { } async getPositions(): Promise<Position[]> { } async openPosition(params: OpenPositionParams): Promise<any> { } async closePosition(params: ClosePositionParams): Promise<any> { } }
-
在
/lib/trading-engine.ts中集成- 在构造函数中初始化交易所客户端
- 更新
getAccount()和交易执行逻辑
-
更新配置类型:添加新交易所所需的凭证字段
-
测试脚本:创建
scripts/test-newexchange-connection.ts -
文档更新:详细说明新交易所的配置方法
决策日志系统位于 /lib/decision-logger.ts:
- 不要随意修改已有字段,这会破坏向后兼容性
- 可以添加新的可选字段
- 必须在类型定义中同步更新
- 建议提供数据迁移脚本(参考
scripts/migrate-closed-positions.ts)
系统使用 Binance API 获取市场数据,相关逻辑在 /lib/market-data.ts:
- 如需添加新数据源(如 CoinGecko),实现相同的接口
- 确保返回的数据格式一致
- 处理 API 限流和错误重试
- 更新配置以支持数据源选择
目前项目暂无自动化测试,但请确保:
- 所有页面能正常加载
- API 端点返回正确数据
- 无控制台错误或警告
- 在不同浏览器测试(Chrome、Firefox、Safari)
- 响应式设计在移动端正常显示
如果你的改动涉及交易逻辑:
- 配置测试:使用
config.json.example验证配置加载 - API 连接测试:
# 测试 Aster DEX 连接 npx tsx scripts/test-aster-connection.ts # 测试 AI 模型连接 npx tsx scripts/test-kimi.ts # 或其他 AI 模型测试脚本
- 交易流程测试:在测试环境小额运行完整交易周期
- 决策日志验证:检查
decision_logs/下生成的 JSON 文件格式正确 - 边界情况:测试余额不足、网络错误、API 限流等情况
- 多个交易员同时运行时的性能表现
- SWR 数据刷新不会造成页面卡顿
- 大量决策日志时的加载速度
- 净值图表渲染大数据集的性能
- API 密钥不会泄露到前端
- 管理员认证功能正常工作
- 敏感配置正确脱敏显示
- 无 XSS 或注入漏洞
在贡献代码时,请注意:
// ❌ 错误:直接在前端暴露 API 密钥
const apiKey = process.env.NEXT_PUBLIC_DEEPSEEK_KEY;
// ✅ 正确:API 密钥仅在服务端使用
const config = await loadConfig(); // 在 API Route 中
const apiKey = config.traders[0].deepseek_api_key;// ✅ 验证所有外部输入
export async function POST(request: Request) {
const body = await request.json();
// 验证必需字段
if (!body.trader_id || typeof body.trader_id !== 'string') {
return NextResponse.json({ error: 'Invalid trader_id' }, { status: 400 });
}
// 验证数值范围
if (body.amount && (body.amount <= 0 || body.amount > MAX_AMOUNT)) {
return NextResponse.json({ error: 'Invalid amount' }, { status: 400 });
}
}// ✅ 不要暴露敏感错误信息
try {
await executeTrader(traderId);
} catch (error) {
console.error('Trader execution failed:', error); // 服务端日志
return NextResponse.json(
{ error: 'Failed to execute trader' }, // 用户看到的
{ status: 500 }
);
}- 确保
config.json在.gitignore中 - 不要在代码示例中使用真实 API 密钥
- 使用环境变量或配置文件,避免硬编码敏感信息
如果你的改动涉及:
- 新功能:更新 README.md
- API 变化:更新 API 文档
- 配置变更:更新 config.json.example
- 架构调整:更新 CLAUDE.md
提交 PR 前,请确保:
- 代码遵循项目的代码规范
- 提交信息遵循 Conventional Commits
- 已在本地测试所有改动
- 构建成功(
npm run build) - 无 ESLint 错误(
npm run lint) - 更新了相关文档
- PR 描述清晰说明了改动内容
- 添加了必要的代码注释
- 没有引入新的安全风险
- 测试了边界情况和错误处理
-
VS Code:推荐的代码编辑器
- ESLint 扩展
- Prettier 扩展
- Tailwind CSS IntelliSense 扩展
- TypeScript and JavaScript Language Features
-
浏览器扩展
- React Developer Tools
- Redux DevTools(如果使用)
// 在 API Route 中添加日志
export async function GET(request: Request) {
console.log('[API] Request URL:', request.url);
console.log('[API] Request headers:', request.headers);
try {
const result = await someOperation();
console.log('[API] Result:', result);
return NextResponse.json(result);
} catch (error) {
console.error('[API] Error:', error);
return NextResponse.json({ error: 'Internal error' }, { status: 500 });
}
}在 lib/trading-engine.ts 中启用详细日志:
async runCycle(): Promise<void> {
console.log(`[${this.traderId}] Starting trading cycle...`);
const account = await this.getAccount();
console.log(`[${this.traderId}] Account balance:`, account.total_equity);
// ... 更多日志
}# 查看最新的决策日志
cat decision_logs/aster_deepseek/$(ls -t decision_logs/aster_deepseek/ | head -1) | jq .
# 查看特定周期的决策
cat decision_logs/aster_deepseek/50.json | jq '.decisions'
# 提取所有交易决策
find decision_logs/aster_deepseek -name "*.json" | xargs jq -r '.decisions[] | "\(.symbol) \(.action)"'# Docker 环境
docker compose logs -f nofyai
# 本地开发
npm run dev# 清除 Next.js 缓存
rm -rf .next
npm run dev# 重新生成类型定义
npm run build# 查找占用 3000 端口的进程
lsof -ti:3000
# 杀死进程
kill -9 $(lsof -ti:3000)
# 或使用其他端口
PORT=3001 npm run dev- 主版本号(Major):不兼容的 API 修改
- 次版本号(Minor):向下兼容的功能新增
- 修订号(Patch):向下兼容的问题修正
维护者在发布新版本时应:
- 更新
package.json中的版本号 - 更新
CHANGELOG.md(如果有) - 确保所有测试通过
- 更新文档(README、CLAUDE.md 等)
- 创建 Git tag
- 发布 Release Notes
为了营造开放和友好的环境,我们承诺:
- 使用友好和包容的语言
- 尊重不同的观点和经验
- 优雅地接受建设性批评
- 关注对社区最有利的事情
- 对其他社区成员表示同理心
- 使用性化的语言或图像
- 侮辱性或贬损性评论
- 人身攻击
- 骚扰行为
- 发布他人的私人信息
- 其他在专业环境中不适当的行为
- Bug 报告:使用 GitHub Issues
- 功能请求:使用 GitHub Issues(标签:
enhancement) - 一般问题:使用 GitHub Discussions
- 安全问题:请私下联系维护者
- README.md - 项目概览和快速开始
- CLAUDE.md - AI 开发助手指南
- config.json.example - 配置文件示例
- Next.js Documentation - Next.js 官方文档
- React Documentation - React 官方文档
- TypeScript Handbook - TypeScript 手册
- Tailwind CSS - Tailwind CSS 文档
- SWR Documentation - SWR 数据获取库
- Aster DEX Documentation - Aster DEX 官方文档
- Binance API Documentation - Binance API(市场数据)
- DeepSeek API - DeepSeek API 文档
- Qwen API - 通义千问 API 文档
- Kimi API - Moonshot AI API 文档
提交代码即表示你同意将你的贡献按照 MIT License 授权。
再次感谢你的贡献!🎉
如果你有任何问题,欢迎在 GitHub Issues 或 Discussions 中提问!
Made with ❤️ by NofyAI Community