diff --git a/adapter/adapter.go b/adapter/adapter.go index 507f385..2be7938 100644 --- a/adapter/adapter.go +++ b/adapter/adapter.go @@ -17,12 +17,12 @@ import ( // - IsBuy: BotEvent.Type == "BUY". // - Price / Size: BotEvent already exposes float64 fields. // - ReduceOnly: true for SELL + take-profit BotEvent. -func ToCreateOrderRequest(d *tc.Deal, event recomma.BotEvent, md metadata.Metadata) hyperliquid.CreateOrderRequest { +func ToCreateOrderRequest(currency string, event recomma.BotEvent, md metadata.Metadata) hyperliquid.CreateOrderRequest { isBuy := event.Type == tc.BUY reduceOnly := !isBuy && event.OrderType == tc.MarketOrderDealOrderTypeTakeProfit req := hyperliquid.CreateOrderRequest{ - Coin: d.ToCurrency, + Coin: currency, IsBuy: isBuy, Price: event.Price, Size: event.Size, @@ -95,7 +95,7 @@ func almostEqual(a, b float64) bool { // prev is nil if we have no prior snapshot stored. func BuildAction( - deal *tc.Deal, + currency string, prev *recomma.BotEvent, next recomma.BotEvent, md metadata.Metadata, @@ -107,20 +107,20 @@ func BuildAction( switch { case prev == nil && nextState == stateActive: // New order we have never submitted → create - req := ToCreateOrderRequest(deal, next, md) + req := ToCreateOrderRequest(currency, next, md) return recomma.Action{Type: recomma.ActionCreate, Create: &req} case prev == nil: // Never saw it active; HL won’t have it either return recomma.Action{Type: recomma.ActionNone, Reason: "skipped: no prior order submitted"} case prevState == stateActive && nextState == stateCancelled: - cancel := ToCancelByCloidRequest(deal, md) + cancel := ToCancelByCloidRequest(currency, md) return recomma.Action{Type: recomma.ActionCancel, Cancel: &cancel} case prevState == stateActive && nextState == stateFilled: // Nothing to do on Hyperliquid, but tell caller to persist updated snapshot return recomma.Action{Type: recomma.ActionNone, Reason: "filled locally"} case prevState == stateActive && nextState == stateActive: if needsModify(prev, &next) { - modify := ToModifyOrderRequest(deal, next, md) + modify := ToModifyOrderRequest(currency, next, md) return recomma.Action{Type: recomma.ActionModify, Modify: &modify} } return recomma.Action{Type: recomma.ActionNone, Reason: "no material change"} @@ -129,15 +129,15 @@ func BuildAction( } } -func ToCancelByCloidRequest(d *tc.Deal, md metadata.Metadata) hyperliquid.CancelOrderRequestByCloid { +func ToCancelByCloidRequest(currency string, md metadata.Metadata) hyperliquid.CancelOrderRequestByCloid { return hyperliquid.CancelOrderRequestByCloid{ - Coin: d.ToCurrency, + Coin: currency, Cloid: md.Hex(), } } -func ToModifyOrderRequest(d *tc.Deal, next recomma.BotEvent, md metadata.Metadata) hyperliquid.ModifyOrderRequest { - req := ToCreateOrderRequest(d, next, md) +func ToModifyOrderRequest(currency string, next recomma.BotEvent, md metadata.Metadata) hyperliquid.ModifyOrderRequest { + req := ToCreateOrderRequest(currency, next, md) return hyperliquid.ModifyOrderRequest{ Oid: hyperliquid.Cloid{Value: md.Hex()}, Order: req, diff --git a/engine/engine.go b/engine/engine.go index 9156a58..a830b03 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -157,10 +157,10 @@ func (e *Engine) HandleDeal(ctx context.Context, wi WorkKey) error { return err } - return e.processDeal(ctx, wi, deal, deal.Events()) + return e.processDeal(ctx, wi, deal.ToCurrency, deal.Events()) } -func (e *Engine) processDeal(ctx context.Context, wi WorkKey, deal *tc.Deal, events []tc.BotEvent) error { +func (e *Engine) processDeal(ctx context.Context, wi WorkKey, currency string, events []tc.BotEvent) error { logger := e.logger.With("deal-id", wi.DealID).With("bot-id", wi.BotID) seen := make(map[uint32]metadata.Metadata) @@ -202,7 +202,7 @@ func (e *Engine) processDeal(ctx context.Context, wi WorkKey, deal *tc.Deal, eve } for _, md := range seen { - action, latestEvent, shouldEmit, err := e.reduceOrderEvents(deal, md, logger.With("botevent-id", md.BotEventID)) + action, latestEvent, shouldEmit, err := e.reduceOrderEvents(currency, md, logger.With("botevent-id", md.BotEventID)) if err != nil { return fmt.Errorf("reduce order %d: %w", md.BotEventID, err) } @@ -226,7 +226,7 @@ func (e *Engine) processDeal(ctx context.Context, wi WorkKey, deal *tc.Deal, eve // on Hyperliquid". It returns the action plus a flag telling the caller whether // anything needs to be emitted. func (e *Engine) reduceOrderEvents( - deal *tc.Deal, + currency string, md metadata.Metadata, logger *slog.Logger, ) (recomma.Action, *recomma.BotEvent, bool, error) { @@ -259,7 +259,7 @@ func (e *Engine) reduceOrderEvents( prev = nil } - action := adapter.BuildAction(deal, prev, latest, md) + action := adapter.BuildAction(currency, prev, latest, md) switch action.Type { case recomma.ActionNone: @@ -277,7 +277,7 @@ func (e *Engine) reduceOrderEvents( // differ. If HL never saw the create we fall back to a create using // the freshest snapshot so the venue ends up with the right values. if !hasLocalOrder { - req := adapter.ToCreateOrderRequest(deal, latest, md) + req := adapter.ToCreateOrderRequest(currency, latest, md) logger.Warn("modify requested before create; falling back", slog.Any("latest", latest)) logger.Debug("emit create", slog.Any("request", req)) return recomma.Action{Type: recomma.ActionCreate, Create: &req}, &latestCopy, true, nil diff --git a/engine/handle_deal_test.go b/engine/handle_deal_test.go index ba4c80e..d1e700a 100644 --- a/engine/handle_deal_test.go +++ b/engine/handle_deal_test.go @@ -124,7 +124,7 @@ func TestProcessDeal_TableDriven(t *testing.T) { BotEvent: activeEvent, } - createReq := adapter.ToCreateOrderRequest(h.deal, be, activeMD) + createReq := adapter.ToCreateOrderRequest(h.deal.ToCurrency, be, activeMD) require.NoError(t, h.store.RecordHyperliquidOrderRequest(activeMD, createReq, inserted)) }, wantActions: []recomma.ActionType{recomma.ActionCancel}, @@ -146,7 +146,7 @@ func TestProcessDeal_TableDriven(t *testing.T) { BotEvent: activeEvent, } - createReq := adapter.ToCreateOrderRequest(h.deal, be, activeMD) + createReq := adapter.ToCreateOrderRequest(h.deal.ToCurrency, be, activeMD) require.NoError(t, h.store.RecordHyperliquidOrderRequest(activeMD, createReq, inserted)) }, wantActions: []recomma.ActionType{recomma.ActionModify}, @@ -169,7 +169,7 @@ func TestProcessDeal_TableDriven(t *testing.T) { tc.prepare(t, h) } - err := h.engine.processDeal(h.ctx, h.key, h.deal, tc.events) + err := h.engine.processDeal(h.ctx, h.key, h.deal.ToCurrency, tc.events) require.NoError(t, err) require.Len(t, h.emitter.items, len(tc.wantActions))