@senal-group/senal-sdk
v0.0.1-beta.8
Published
本文档覆盖 SDK 的所有功能模块,包含完整的代码示例与说明。
Downloads
13
Readme
Prediction Market MM SDK — Demo
本文档覆盖 SDK 的所有功能模块,包含完整的代码示例与说明。
安装
npm install @senal-group/senal-sdk初始化客户端
ApiClient 继承自 BaseClient,同时提供 REST API 和 WebSocket 能力。
API 凭证(apiKey / apiSecret / passphrase)由平台统一分配,开始前请确认已获取。
import { ApiClient } from '@senal-group/senal-sdk';
const client = new ApiClient({
baseUrl: 'https://api.example.com',
wsUrl: 'wss://ws.example.com',
apiKey: 'YOUR_API_KEY',
apiSecret: 'YOUR_API_SECRET',
passphrase: 'YOUR_PASSPHRASE',
timeoutMs: 5000,
l1Address: '0xYourWalletAddress', // 可选
});模块一:账户 mm.account
查询余额
const balance = await client.mm.account.getBalance({});
console.log(`可用: ${balance.available} 锁定: ${balance.locked}`);查询所有持仓
返回账户当前持有的所有预测市场头寸,包含盈亏、当前价格等信息。
const position = await client.mm.account.getPositions({});
console.log(`
市场: ${position.marketTitle}
结果: ${position.outcomeName}
持仓量: ${position.size}
均价: ${position.avgPrice}
当前价: ${position.curPrice}
未实现PnL: ${position.cashPnl} (${position.percentPnl}%)
已实现PnL: ${position.percentRealizedPnl}%
可赎回: ${position.redeemable}
`);查询持仓总价值
const { totalValue } = await client.mm.account.getPositionsTotalValue({});
console.log(`持仓总价值: ${totalValue}`);查询单个持仓(by tokenId)
const position = await client.mm.account.getPosition({
tokenId: 'token-xxx',
});
console.log(`持仓量: ${position.size} 均价: ${position.avgPrice} 已实现PnL: ${position.realizedPnl}`);模块二:市场 mm.markets
获取市场列表
支持按状态、是否接受挂单过滤,使用游标分页。
const result = await client.mm.markets.getMarkets({
status: 'active',
acceptingOrders: true,
limit: 20,
});
console.log(`共 ${result.count} 个市场`);
for (const market of result.data) {
console.log(`[${market.id}] ${market.question}`);
console.log(` 状态: ${market.status} 最小下单量: ${market.minimumOrderSize} tick: ${market.tickSize}`);
for (const outcome of market.outcomes) {
console.log(` - ${outcome.name} tokenId=${outcome.tokenId} price=${outcome.price}`);
}
}
// 翻页
if (result.next_cursor) {
const nextPage = await client.mm.markets.getMarkets({
cursor: result.next_cursor,
limit: 20,
});
}获取单个市场详情
const market = await client.mm.markets.getMarketById({
id: 'market-id-xxx',
});
console.log(market.question, market.outcomes);模块三:行情 mm.market
查询订单簿
返回指定 token 的当前买卖盘深度。
const orderbook = await client.mm.market.getOrderbook({
marketId: 'market-id-xxx',
tokenId: 'token-xxx',
});
console.log('卖单 (asks):');
orderbook.asks.forEach(a => console.log(` ${a.price} x ${a.size}`));
console.log('买单 (bids):');
orderbook.bids.forEach(b => console.log(` ${b.price} x ${b.size}`));查询最新成交价
返回指定市场下所有 outcome 的最新成交价,key 为 tokenId。
const prices = await client.mm.market.getLastTradePrices({
marketId: 'market-id-xxx',
});
// { 'token-yes': '0.62', 'token-no': '0.38' }查询价格历史
const history = await client.mm.market.getPriceHistory({
outcomeId: 'token-xxx',
interval: '1h', // 时间粒度
fidelity: 100, // 返回数据点数量上限
});
history.forEach(point => {
console.log(`${point.timestamp} price=${point.price}`);
});模块四:订单 mm.order
单笔下单
const order = await client.mm.order.placeOrder({
marketId: 'market-id-xxx',
tokenId: 'token-xxx',
side: 'BUY', // 'BUY' | 'SELL'
orderType: 'GTC', // 'GTC' | 'FOK' | 'GTD' | 'FAK'
price: 0.47,
size: 100,
postOnly: true, // 可选,仅挂单不吃单
});
console.log(`订单ID: ${order.id} 状态: ${order.status}`);orderType 说明:
| 类型 | 含义 |
|-------|------|
| GTC | Good Till Cancelled,挂单直到手动撤销 |
| FOK | Fill Or Kill,立即全部成交否则撤销 |
| GTD | Good Till Date,到期自动撤销,需传 expiration |
| FAK | Fill And Kill,立即成交可成交部分,剩余撤销 |
批量下单
单次最多提交 15 个订单。
const results = await client.mm.order.batchPlaceOrders({
orders: [
{ marketId, tokenId, side: 'BUY', orderType: 'GTC', price: 0.44, size: 50 },
{ marketId, tokenId, side: 'BUY', orderType: 'GTC', price: 0.41, size: 40 },
{ marketId, tokenId, side: 'SELL', orderType: 'GTC', price: 0.56, size: 50 },
{ marketId, tokenId, side: 'SELL', orderType: 'GTC', price: 0.59, size: 40 },
],
});
results.forEach(r => {
console.log(`订单 ${r.id} 状态: ${r.status} 成交笔数: ${r.trades.length}`);
});查询订单列表
const { items, total, page, pageSize } = await client.mm.order.getOrders({
marketId,
status: 'open', // 'open' | 'filled' | 'cancelled' | 'expired'
page: 1,
pageSize: 20,
});
console.log(`共 ${total} 笔,当前第 ${page} 页`);
items.forEach(o => {
console.log(`[${o.id}] ${o.side} ${o.size}@${o.price} 已成交: ${o.filledSize} 剩余: ${o.remainingSize}`);
});查询单笔订单
const order = await client.mm.order.getOrder({
id: 'order-id-xxx',
});
console.log(order.status, order.filledSize);撤销单笔订单
const result = await client.mm.order.cancelOrder({
orderId: 'order-id-xxx',
});
console.log(result.results[0].success);批量撤单(by orderIds)
const result = await client.mm.order.batchCancelOrders({
orderIds: ['order-id-1', 'order-id-2', 'order-id-3'],
});
result.results.forEach(r => {
console.log(`${r.orderId} 成功: ${r.success} ${r.reason ?? ''}`);
});撤销某市场全部订单(by tokenId)
const result = await client.mm.order.cancelMarketOrders({
tokenId: 'token-xxx',
});
console.log(`撤单 ${result.results.length} 笔`);撤销所有订单
const result = await client.mm.order.cancelAllOrders({});
console.log(`撤单 ${result.results.length} 笔`);模块五:成交记录 mm.trade
查询作为 Maker 的历史成交,支持游标分页。
const result = await client.mm.trade.getMakerTrades({
marketId,
tokenId,
limit: 20,
});
console.log(`共 ${result.count} 笔成交`);
result.data.forEach(t => {
console.log(`[${t.id}] ${t.side} ${t.size}@${t.price} 链上状态: ${t.status}`);
});
// 翻页
if (result.next_cursor) {
const next = await client.mm.trade.getMakerTrades({
cursor: result.next_cursor,
limit: 20,
});
}链上状态(ChainStatus):
| 状态 | 含义 |
|-------------|----------------|
| pending | 等待上链 |
| submitted | 已提交至链上 |
| confirmed | 链上已确认 |
| failed | 链上执行失败 |
模块六:WebSocket 实时推送
SDK 内置 WebSocket 客户端,支持订单、持仓、行情的实时推送。
连接与认证
await client.connect();
await client.authenticate();内置频道常量
| 常量 | 频道名 | 说明 |
|--------------------------------------|-------------|--------------------|
| ApiClient.CHANNAL_ORDERS | orders | 私有:订单更新 |
| ApiClient.CHANNAL_POSITIONS | positions | 私有:持仓更新 |
| ApiClient.CHANNAL_TRADE_PREFIX | trade | 公共:成交推送前缀 |
| ApiClient.CHANNAL_ORDERBOOK_PREFIX | orderbook | 公共:盘口推送前缀 |
构建行情频道名
公共行情频道需通过 buildChannel 拼接 tokenId 生成完整频道名。
const tradeChannel = client.buildChannel('trade', tokenId);
const orderbookChannel = client.buildChannel('orderbook', tokenId);
// e.g. "trade:token-xxx" / "orderbook:token-xxx"订阅 / 取消订阅
// 订阅
client.subscribe([
ApiClient.CHANNAL_ORDERS,
ApiClient.CHANNAL_POSITIONS,
tradeChannel,
orderbookChannel,
]);
// 取消订阅
client.unsubscribe([tradeChannel, orderbookChannel]);监听消息
// 所有消息(调试用)
client.onMessage(msg => {
console.log('raw:', msg);
});
// 订阅成功回调
client.onSubscribed(msg => {
console.log('已订阅:', msg.channel);
});
// 取消订阅回调
client.onUnsubscribed(msg => {
console.log('已取消:', msg.channel);
});
// 指定频道的数据更新
client.onUpdate(ApiClient.CHANNAL_ORDERS, msg => {
console.log('订单更新:', msg.data);
});
client.onUpdate(ApiClient.CHANNAL_POSITIONS, msg => {
console.log('持仓更新:', msg.data);
});
client.onUpdate(orderbookChannel, msg => {
console.log('Orderbook 更新:', msg.data);
});
client.onUpdate(tradeChannel, msg => {
console.log('成交更新:', msg.data);
});等待单次消息(Promise 风格)
适合启动时等待初始快照,或做简单的请求-响应交互。
const msg = await client.waitOnce(
msg => msg.channel === orderbookChannel,
10_000, // 超时 ms,超时后 reject
);
console.log('首条 orderbook 快照:', msg.data);关闭连接
client.close();附录:订单状态(ExchangeOrderStatus)
| 状态 | 含义 |
|--------------------|----------|
| pending | 待处理 |
| open | 挂单中 |
| partially_filled | 部分成交 |
| filled | 完全成交 |
| cancelled | 已撤销 |
| rejected | 已拒绝 |
