mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-11 09:18:08 +00:00
feat: 增强 Lighter 适配器的账户更新逻辑,支持市场账户的实时更新和合并处理
This commit is contained in:
@@ -457,6 +457,14 @@ export class LighterGateway {
|
|||||||
ws.send(JSON.stringify({ type: "subscribe", channel: `order_book/${marketId}` }));
|
ws.send(JSON.stringify({ type: "subscribe", channel: `order_book/${marketId}` }));
|
||||||
ws.send(JSON.stringify({ type: "subscribe", channel: `account_all/${Number(this.signer.accountIndex)}` }));
|
ws.send(JSON.stringify({ type: "subscribe", channel: `account_all/${Number(this.signer.accountIndex)}` }));
|
||||||
const auth = await this.ensureAuthToken();
|
const auth = await this.ensureAuthToken();
|
||||||
|
// Subscribe to per-market account updates to receive timely position changes
|
||||||
|
ws.send(
|
||||||
|
JSON.stringify({
|
||||||
|
type: "subscribe",
|
||||||
|
channel: `account_market/${Number(marketId)}/${Number(this.signer.accountIndex)}`,
|
||||||
|
auth,
|
||||||
|
})
|
||||||
|
);
|
||||||
ws.send(
|
ws.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: "subscribe",
|
type: "subscribe",
|
||||||
@@ -504,6 +512,10 @@ export class LighterGateway {
|
|||||||
case "update/account_all":
|
case "update/account_all":
|
||||||
this.handleAccountAll(message);
|
this.handleAccountAll(message);
|
||||||
break;
|
break;
|
||||||
|
case "subscribed/account_market":
|
||||||
|
case "update/account_market":
|
||||||
|
this.handleAccountMarket(message);
|
||||||
|
break;
|
||||||
case "subscribed/account_all_orders":
|
case "subscribed/account_all_orders":
|
||||||
case "update/account_all_orders":
|
case "update/account_all_orders":
|
||||||
this.handleAccountOrders(message);
|
this.handleAccountOrders(message);
|
||||||
@@ -566,13 +578,54 @@ export class LighterGateway {
|
|||||||
|
|
||||||
private handleAccountAll(message: any): void {
|
private handleAccountAll(message: any): void {
|
||||||
if (!message) return;
|
if (!message) return;
|
||||||
// account_all messages may be partial updates; if positions is omitted, retain existing positions
|
// account_all may be partial; merge provided markets into existing positions
|
||||||
if (Object.prototype.hasOwnProperty.call(message, "positions")) {
|
if (Object.prototype.hasOwnProperty.call(message, "positions")) {
|
||||||
const positionsObject = message.positions ?? {};
|
const positionsObject = message.positions ?? {};
|
||||||
const positions: LighterPosition[] = (Array.isArray(positionsObject)
|
const incoming: LighterPosition[] = (Array.isArray(positionsObject)
|
||||||
? (positionsObject as LighterPosition[])
|
? (positionsObject as LighterPosition[])
|
||||||
: (Object.values(positionsObject) as LighterPosition[])) as LighterPosition[];
|
: (Object.values(positionsObject) as LighterPosition[])) as LighterPosition[];
|
||||||
this.positions = positions;
|
|
||||||
|
const byMarket = new Map<number, LighterPosition>();
|
||||||
|
for (const p of this.positions ?? []) {
|
||||||
|
const mid = Number(p.market_id);
|
||||||
|
if (Number.isFinite(mid)) byMarket.set(mid, p);
|
||||||
|
}
|
||||||
|
for (const p of incoming) {
|
||||||
|
const mid = Number(p.market_id);
|
||||||
|
if (!Number.isFinite(mid)) continue;
|
||||||
|
const sign = Number(p.sign ?? 0);
|
||||||
|
const size = Number(p.position ?? 0);
|
||||||
|
if (sign === 0 || Math.abs(size) < 1e-12) {
|
||||||
|
byMarket.delete(mid);
|
||||||
|
} else {
|
||||||
|
byMarket.set(mid, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.positions = Array.from(byMarket.values());
|
||||||
|
}
|
||||||
|
this.emitAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleAccountMarket(message: any): void {
|
||||||
|
if (!message) return;
|
||||||
|
const position: LighterPosition | undefined = message.position as LighterPosition | undefined;
|
||||||
|
if (!position || !Number.isFinite(Number(position.market_id))) return;
|
||||||
|
const marketId = Number(position.market_id);
|
||||||
|
const sign = Number(position.sign ?? 0);
|
||||||
|
const size = Number(position.position ?? 0);
|
||||||
|
const shouldRemove = sign === 0 || Math.abs(size) < 1e-12;
|
||||||
|
if (shouldRemove) {
|
||||||
|
this.positions = (this.positions ?? []).filter((p) => Number(p.market_id) !== marketId);
|
||||||
|
} else {
|
||||||
|
let updated = false;
|
||||||
|
this.positions = (this.positions ?? []).map((p) => {
|
||||||
|
if (Number(p.market_id) === marketId) {
|
||||||
|
updated = true;
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
});
|
||||||
|
if (!updated) this.positions.push(position);
|
||||||
}
|
}
|
||||||
this.emitAccount();
|
this.emitAccount();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,7 +172,8 @@ function lighterPositionToAster(symbol: string, position: LighterPosition): Aste
|
|||||||
const sign = position.sign ?? 0;
|
const sign = position.sign ?? 0;
|
||||||
const positionSide = sign > 0 ? "LONG" : sign < 0 ? "SHORT" : "BOTH";
|
const positionSide = sign > 0 ? "LONG" : sign < 0 ? "SHORT" : "BOTH";
|
||||||
const magnitude = Number(position.position ?? 0);
|
const magnitude = Number(position.position ?? 0);
|
||||||
const signed = sign < 0 ? -Math.abs(magnitude) : Math.abs(magnitude);
|
// Normalize: when sign is 0, treat as flat regardless of reported magnitude
|
||||||
|
const signed = sign === 0 ? 0 : sign < 0 ? -Math.abs(magnitude) : Math.abs(magnitude);
|
||||||
return {
|
return {
|
||||||
symbol,
|
symbol,
|
||||||
positionAmt: Number.isFinite(signed) ? signed.toString() : position.position ?? "0",
|
positionAmt: Number.isFinite(signed) ? signed.toString() : position.position ?? "0",
|
||||||
|
|||||||
Reference in New Issue
Block a user