构建网关连接器¶
概述¶
本指南将引导您完成为去中心化交易所(DEX)构建新网关连接器的过程。网关连接器使 Hummingbot 能够通过标准化的 REST API 接口与基于区块链的交易协议进行交互。
网关支持三种类型的 DEX 连接器:
- 路由器:寻找最优兑换路径的 DEX 聚合器
- AMM:传统的 V2 风格恒定乘积资金池
- CLMM:具有自定义价格区间的集中流动性做市商
前提条件¶
在构建网关连接器之前,请确保您已具备以下条件:
开发环境¶
- Node.js 18+ 和 pnpm
- TypeScript 知识
- 对目标区块链和 DEX 协议的理解
协议知识¶
- 熟悉该 DEX 的智能合约
- 了解该协议的 SDK 或 API
- 了解流动性池的机制
网关设置¶
- 已配置网关开发环境
- 能够在本地运行和测试网关
连接器架构¶
网关连接器采用模块化架构:
src/connectors/{protocol}/
├── {protocol}.ts # Main connector class
├── {protocol}.config.ts # Configuration interface
├── {protocol}.constants.ts # Protocol-specific constants
├── {protocol}.utils.ts # Helper functions
├── router-routes/ # Router endpoints (if applicable)
├── amm-routes/ # AMM endpoints (if applicable)
└── clmm-routes/ # CLMM endpoints (if applicable)
实现步骤¶
步骤 1:选择连接器类型¶
确定您的 DEX 支持哪些交易类型:
| 类型 | 使用场景 | 关键方法 |
|---|---|---|
| 路由 | DEX 聚合器、仅支持兑换的协议 | quote、trade、estimateGas |
| AMM | 带有流动性代币(LP tokens)的 V2 风格资金池 | poolPrice、addLiquidity、removeLiquidity |
| CLMM | 支持价格区间的集中流动性 | openPosition、addLiquidity、collectFees |
步骤 2:创建连接器类¶
创建主连接器类——如果你正在构建基于以太坊的去中心化交易所(DEX)连接器,请参考 Uniswap;如果你正在构建基于 Solana 的 DEX 连接器,请参考 Raydium。
// src/connectors/mydex/mydex.ts
export class MyDex {
private static instances: Record<string, MyDex> = {};
public solana: Solana; // or Ethereum
public sdk: MyDEXSDK;
public config: MyDexConfig.RootConfig;
private constructor() {
this.config = MyDexConfig.config;
this.txVersion = TxVersion.V0;
}
// Gets singleton instance
public static getInstance(network: string): MyDex {
if (!MyDex._instances) {
MyDex._instances = {};
}
if (!MyDex._instances[network]) {
const instance = new MyDex();
await instance.init(network);
MyDex._instances[network] = instance;
}
return MyDex._instances[network];
}
// Initializes instance
private async init(network: string) {
try {
this.solana = await Solana.getInstance(network);
this.sdk = await MyDEXSDK.load({
connection: this.solana.connection,
blockhashCommitment: 'confirmed',
});
logger.info('MyDEX initialized successfully');
} catch (error) {
logger.error('MyDEX initialization failed:', error);
throw error;
}
}
}
步骤 3:实现交易方法¶
根据你的连接器类型,实现所需的方法:
路由方法¶
// Quote a swap
async quote(
base: Token,
quote: Token,
amount: BigNumber,
side: 'BUY' | 'SELL'
): Promise<SwapQuote> {
// Implement quote logic
return {
route: optimalRoute,
expectedOut: outputAmount,
priceImpact: impact,
gasEstimate: gasLimit
};
}
// Execute a swap
async trade(
wallet: Wallet,
quote: SwapQuote,
slippage: number
): Promise<Transaction> {
// Build and execute transaction
return transaction;
}
AMM 方法¶
// Get pool information
async poolInfo(
base: Token,
quote: Token
): Promise<PoolInfo> {
// Fetch pool data
return {
reserves: [baseReserve, quoteReserve],
fee: poolFee,
liquidity: totalLiquidity
};
}
// Add liquidity
async addLiquidity(
wallet: Wallet,
base: Token,
quote: Token,
baseAmount: BigNumber,
quoteAmount: BigNumber,
slippage: number
): Promise<Transaction> {
// Add liquidity logic
return transaction;
}
CLMM 方法¶
// Open a concentrated liquidity position
async openPosition(
wallet: Wallet,
pool: Pool,
lowerPrice: number,
upperPrice: number,
baseAmount: BigNumber,
quoteAmount: BigNumber
): Promise<Position> {
// Create position NFT
return position;
}
// Collect earned fees
async collectFees(
wallet: Wallet,
positionId: string
): Promise<Transaction> {
// Collect fees logic
return transaction;
}
步骤 4:创建路由处理器¶
为你支持的操作创建路由处理器文件:
// src/connectors/mydex/router-routes/router.routes.ts
import { Router, Request, Response } from 'express';
import { MyDex } from '../mydex';
import {
QuoteSwapRequest,
QuoteSwapResponse,
ExecuteSwapRequest,
ExecuteSwapResponse
} from '../../../schemas/router-schema';
export const routerRoutes = Router();
routerRoutes.post('/quote-swap', async (req: Request, res: Response) => {
const request = req.body as QuoteSwapRequest;
const connector = MyDex.getInstance(request.chain, request.network);
try {
const quote = await connector.quote(
request.base,
request.quote,
request.amount,
request.side
);
const response: QuoteSwapResponse = {
network: request.network,
timestamp: Date.now(),
latency: 0,
base: request.base,
quote: request.quote,
amount: request.amount,
expectedOut: quote.expectedOut,
price: quote.price,
gasEstimate: quote.gasEstimate,
route: quote.route
};
res.status(200).json(response);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
routerRoutes.post('/execute-swap', async (req: Request, res: Response) => {
// Implementation for swap execution
});
步骤 5:添加配置¶
为你的连接器创建配置文件:
模式定义¶
// src/templates/namespace/mydex-schema.json
{
"type": "object",
"properties": {
"slippagePct": {
"type": "number",
"description": "Maximum slippage percentage",
"default": 1.0
},
"customParam": {
"type": "number",
"description": "Custom parameter",
},
},
"required": ["slippagePct"]
}
默认配置¶
步骤 6:注册连接器¶
在主连接器路由中注册你的连接器:
// src/connectors/connector.routes.ts
import { Router } from 'express';
import { routerRoutes as mydexRouterRoutes } from './mydex/router-routes/router.routes';
import { ammRoutes as mydexAmmRoutes } from './mydex/amm-routes/amm.routes';
export const connectorRoutes = Router();
// Add your connector routes
connectorRoutes.use('/mydex/router', mydexRouterRoutes);
connectorRoutes.use('/mydex/amm', mydexAmmRoutes);
步骤 7:编写测试¶
为你的连接器创建全面的测试:
// test/connectors/mydex/mydex.test.ts
import { MyDex } from '../../../src/connectors/mydex/mydex';
describe('MyDex Connector', () => {
let connector: MyDex;
beforeEach(() => {
connector = MyDex.getInstance('ethereum', 'mainnet');
});
describe('quote', () => {
it('should return valid quote for token swap', async () => {
const quote = await connector.quote(
mockTokenA,
mockTokenB,
BigNumber.from('1000000'),
'SELL'
);
expect(quote).toBeDefined();
expect(quote.expectedOut).toBeGreaterThan(0);
expect(quote.priceImpact).toBeLessThan(0.1);
});
it('should handle insufficient liquidity', async () => {
await expect(
connector.quote(
mockTokenA,
mockTokenB,
BigNumber.from('999999999999'),
'SELL'
)
).rejects.toThrow('Insufficient liquidity');
});
});
// Add tests for all methods
});
添加链支持¶
链支持状态
Gateway 当前不接受新的区块链实现的拉取请求。该框架目前支持: - EVM 链:以太坊及 EVM 兼容链(Arbitrum、Optimism、Base、Polygon、BSC、Avalanche 等) - SVM 链:Solana 及 SVM 兼容链
如果你的连接器需要基于 EVM 或 SVM 架构的链,你可以继续执行以下实现。对于全新的区块链架构,请查看 GitHub 仓库,了解何时将接受新的链支持。
如果你的连接器需要一个新的区块链:
步骤 1:创建链实现¶
// src/chains/mychain/mychain.ts
import { ChainBase } from '../../services/chain-base';
export class MyChain extends ChainBase {
private static instances: Record<string, MyChain> = {};
public static getInstance(network: string): MyChain {
if (!MyChain.instances[network]) {
MyChain.instances[network] = new MyChain(network);
}
return MyChain.instances[network];
}
// Implement required methods
async getWallet(address: string): Promise<Wallet> {
// Wallet implementation
}
async getBalance(address: string): Promise<Balance> {
// Balance checking logic
}
async getTokens(symbols: string[]): Promise<Token[]> {
// Token resolution logic
}
}
步骤 2:创建链路由¶
// src/chains/mychain/routes/mychain.routes.ts
import { Router } from 'express';
import { MyChain } from '../mychain';
export const chainRoutes = Router();
chainRoutes.get('/balance', async (req, res) => {
const { address } = req.query;
const chain = MyChain.getInstance(req.query.network);
const balance = await chain.getBalance(address);
res.json(balance);
});
步骤 3:添加链配置¶
# src/templates/chains/mychain.yml
networks:
mainnet:
rpcUrl: 'https://rpc.mychain.io'
chainId: 1234
nativeCurrency: 'MYCOIN'
testnet:
rpcUrl: 'https://testnet-rpc.mychain.io'
chainId: 5678
nativeCurrency: 'TESTCOIN'
测试要求¶
所有 Gateway 连接器必须满足以下测试标准:
- 代码覆盖率:最低 75% 覆盖率
- 单元测试:测试所有公共方法
- 集成测试:测试 API 端点
- 错误处理:测试失败场景
- 模拟数据:使用真实的测试数据
运行测试¶
# Run all tests
pnpm test
# Run tests for specific connector
pnpm test -- mydex
# Check coverage
pnpm test:coverage
代码质量标准¶
代码检查与格式化¶
网关使用 ESLint 和 Prettier 来保证代码质量:
TypeScript 最佳实践¶
- 强类型:使用明确的类型,避免使用
any - 错误处理:实现正确的错误类
- 异步/等待:使用现代的异步模式
- 文档:为公共方法添加 JSDoc 注释
提交清单¶
在提交连接器之前:
- 所有测试通过且覆盖率超过 75%
- 代码通过代码检查和格式化检查
- 为所有支持的网络添加了配置文件
- API 端点符合模式规范
- 文档包含使用示例
- 错误处理覆盖边界情况
- 已使用真实负载进行性能测试
- 安全审查已完成
下一步¶
- 本地测试:使用你的连接器运行网关并测试所有操作
- 创建示例:添加展示连接器用法的示例脚本
- 提交 PR:向网关仓库创建拉取请求
- 治理提案:如需,提交新连接器提案
资源¶
- 网关 GitHub 仓库
- 网关 API 文档
- 连接器模式
- 示例连接器
- Discord 支持