name: Bankr 开发 - 客户端模式 description: 这个技能应在用户请求“实现Bankr客户端”、“编写bankr-client.ts”、“创建Bankr的API客户端”、“Bankr项目的通用文件”、“Bankr的package.json”、“Bankr的tsconfig”、“Bankr TypeScript模式”、“Bankr响应类型”时使用,或需要可重用的客户端代码和常见项目文件用于Bankr API集成。 version: 1.0.0
Bankr 客户端模式
用于Bankr API项目的可重用客户端代码和常见文件。
bankr-client.ts
所有Bankr项目的核心API客户端模块:
import "dotenv/config";
const API_URL = process.env.BANKR_API_URL || "https://api.bankr.bot";
const API_KEY = process.env.BANKR_API_KEY;
// ============================================
// 类型定义
// ============================================
export type JobStatus = "pending" | "processing" | "completed" | "failed" | "cancelled";
export interface JobStatusResponse {
success: boolean;
jobId: string;
status: JobStatus;
prompt: string;
response?: string;
transactions?: Transaction[];
richData?: RichData[];
statusUpdates?: StatusUpdate[];
error?: string;
createdAt: string;
startedAt?: string;
completedAt?: string;
cancelledAt?: string;
processingTime?: number;
cancellable?: boolean;
}
export interface StatusUpdate {
message: string;
timestamp: string;
}
// 交易类型
export type Transaction =
| SwapTransaction
| ApprovalTransaction
| TransferErc20Transaction
| TransferEthTransaction
| ConvertEthToWethTransaction
| ConvertWethToEthTransaction
| TransferNftTransaction
| MintManifoldNftTransaction
| MintSeaDropNftTransaction
| BuyNftTransaction
| AvantisTradeTransaction
| SwapCrossChainTransaction
| ManageBankrStakingTransaction;
interface BaseTransactionMetadata {
__ORIGINAL_TX_DATA__: {
chain: string;
humanReadableMessage: string;
inputTokenAddress: string;
inputTokenAmount: string;
inputTokenTicker: string;
outputTokenAddress: string;
outputTokenTicker: string;
receiver: string;
};
transaction: {
chainId: number;
to: string;
data: string;
gas: string;
gasPrice: string;
value: string;
};
}
export interface SwapTransaction {
type: "swap";
metadata: BaseTransactionMetadata & {
approvalRequired?: boolean;
approvalTx?: { to: string; data: string };
permit2?: object;
};
}
export interface ApprovalTransaction {
type: "approval";
metadata: BaseTransactionMetadata;
}
export interface TransferErc20Transaction {
type: "transfer_erc20";
metadata: BaseTransactionMetadata;
}
export interface TransferEthTransaction {
type: "transfer_eth";
metadata: BaseTransactionMetadata;
}
export interface ConvertEthToWethTransaction {
type: "convert_eth_to_weth";
metadata: BaseTransactionMetadata;
}
export interface ConvertWethToEthTransaction {
type: "convert_weth_to_eth";
metadata: BaseTransactionMetadata;
}
export interface TransferNftTransaction {
type: "transfer_nft";
metadata: BaseTransactionMetadata;
}
export interface MintManifoldNftTransaction {
type: "mint_manifold_nft";
metadata: BaseTransactionMetadata;
}
export interface MintSeaDropNftTransaction {
type: "mint_seadrop_nft";
metadata: BaseTransactionMetadata;
}
export interface BuyNftTransaction {
type: "buy_nft";
metadata: BaseTransactionMetadata;
}
export interface AvantisTradeTransaction {
type: "avantisTrade";
metadata: {
chainId: number;
description: string;
to: string;
data: string;
value?: string;
};
}
export interface SwapCrossChainTransaction {
type: "swapCrossChain";
metadata: {
chainId: number;
description: string;
to: string;
data: string;
value: string;
};
}
export interface ManageBankrStakingTransaction {
type: "manage_bankr_staking";
metadata: {
chainId: number;
description: string;
to: string;
data: string;
value?: string;
};
}
// 富数据类型
export type RichData = SocialCard | Chart;
export interface SocialCard {
type: "social-card";
variant: "analysis";
text: string;
}
export interface Chart {
type: "chart";
url: string;
}
// ============================================
// API 函数
// ============================================
export async function submitPrompt(prompt: string): Promise<{ jobId: string }> {
if (!API_KEY) {
throw new Error("BANKR_API_KEY 未设置。请访问 https://bankr.bot/api 获取");
}
const response = await fetch(`${API_URL}/agent/prompt`, {
method: "POST",
headers: {
"x-api-key": API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ prompt }),
});
if (!response.ok) {
const text = await response.text();
throw new Error(`API 错误 ${response.status}: ${text}`);
}
const data = await response.json();
if (!data.success) {
throw new Error(data.error || "提交提示失败");
}
return { jobId: data.jobId };
}
export async function getJobStatus(jobId: string): Promise<JobStatusResponse> {
if (!API_KEY) {
throw new Error("BANKR_API_KEY 未设置");
}
const response = await fetch(`${API_URL}/agent/job/${jobId}`, {
headers: { "x-api-key": API_KEY },
});
if (!response.ok) {
const text = await response.text();
throw new Error(`API 错误 ${response.status}: ${text}`);
}
return response.json();
}
export async function cancelJob(jobId: string): Promise<JobStatusResponse> {
if (!API_KEY) {
throw new Error("BANKR_API_KEY 未设置");
}
const response = await fetch(`${API_URL}/agent/job/${jobId}/cancel`, {
method: "POST",
headers: {
"x-api-key": API_KEY,
"Content-Type": "application/json",
},
});
if (!response.ok) {
const text = await response.text();
throw new Error(`API 错误 ${response.status}: ${text}`);
}
return response.json();
}
export async function waitForCompletion(
jobId: string,
onProgress?: (message: string) => void,
options?: { pollInterval?: number; maxAttempts?: number }
): Promise<JobStatusResponse> {
const pollInterval = options?.pollInterval || 2000;
const maxAttempts = options?.maxAttempts || 150; // 最大5分钟
let lastUpdateCount = 0;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const status = await getJobStatus(jobId);
// 报告新状态更新
if (onProgress && status.statusUpdates) {
for (let i = lastUpdateCount; i < status.statusUpdates.length; i++) {
onProgress(status.statusUpdates[i].message);
}
lastUpdateCount = status.statusUpdates.length;
}
// 检查终端状态
if (["completed", "failed", "cancelled"].includes(status.status)) {
return status;
}
await new Promise((resolve) => setTimeout(resolve, pollInterval));
}
throw new Error("作业在最大尝试次数后超时");
}
/**
* 执行Bankr提示并等待完成
* 结合提交和轮询的便捷函数
*/
export async function execute(
prompt: string,
onProgress?: (message: string) => void
): Promise<JobStatusResponse> {
const { jobId } = await submitPrompt(prompt);
onProgress?.(`作业已提交: ${jobId}`);
return waitForCompletion(jobId, onProgress);
}
通用文件
package.json
所有Bankr项目的基础package.json:
{
"name": "{项目名称}",
"version": "0.1.0",
"description": "{描述}",
"type": "module",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsx src/index.ts"
},
"dependencies": {
"dotenv": "^16.3.1"
},
"devDependencies": {
"@types/node": "^20.10.0",
"tsx": "^4.7.0",
"typescript": "^5.3.0"
}
}
框架特定依赖
根据项目模板添加:
Web服务 (Express):
"dependencies": {
"express": "^4.18.0"
},
"devDependencies": {
"@types/express": "^4.17.21"
}
Web服务 (Fastify):
"dependencies": {
"fastify": "^4.25.0"
}
CLI:
"dependencies": {
"commander": "^12.0.0"
}
tsconfig.json
TypeScript配置:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
.env.example
环境变量模板:
# Bankr API配置
BANKR_API_KEY=bk_your_api_key_here
BANKR_API_URL=https://api.bankr.bot
# 可选:用于上下文的钱包地址
BANKR_WALLET_ADDRESS=0x...
.gitignore
标准忽略模式:
# 依赖
node_modules/
# 构建输出
dist/
# 环境
.env
.env.local
.env.*.local
# 日志
*.log
npm-debug.log*
# IDE
.idea/
.vscode/
*.swp
*.swo
# 操作系统
.DS_Store
Thumbs.db
# 测试
coverage/
使用模式
基本用法
import { execute } from "./bankr-client";
const result = await execute("ETH的价格是多少?", (msg) => {
console.log("进度:", msg);
});
console.log(result.response);
带错误处理
import { execute } from "./bankr-client";
try {
const result = await execute("在Base上购买50美元的ETH");
if (result.status === "completed") {
console.log("成功:", result.response);
// 处理交易
if (result.transactions) {
for (const tx of result.transactions) {
console.log(`${tx.type}:`, tx.metadata.__ORIGINAL_TX_DATA__?.humanReadableMessage);
}
}
} else if (result.status === "failed") {
console.error("失败:", result.error);
}
} catch (error) {
console.error("错误:", error.message);
}
手动控制
import { submitPrompt, waitForCompletion, cancelJob } from "./bankr-client";
// 提交
const { jobId } = await submitPrompt("分析ETH市场");
// 设置超时
const timeout = setTimeout(() => {
cancelJob(jobId);
}, 120000);
// 等待并自定义选项
const result = await waitForCompletion(jobId, console.log, {
pollInterval: 2000,
maxAttempts: 60,
});
clearTimeout(timeout);
API参考
请参阅bankr-api-basics技能获取:
- 完整端点文档
- 认证详情
- 响应字段描述
- 错误代码和处理