Neue neutrale Handelsvertraege (Maerkte, Orderbuch, Orders, Portfolio, Gebuehren) hinter IPlatformAdapter, aufgeloest ueber IPlatformRegistry je Konto. Polymarket Global ist eine duenne Huelle um die bestehenden Dienste; PolymarketClobClient bleibt unveraendert. Das Gateway lehnt ab, was die heutige Anbindung nicht sauber kann (Post-only, IOC/GTD, falsche Plattform), bevor etwas an den CLOB geht. core_accounts und core_markets bekommen die Spalte Platform (Vorgabe polymarket-global), core_markets den Schluessel (Platform, Id). core_positions bleibt: die Plattform folgt aus dem Konto. Noch nutzt kein Modul die Vertraege - das Handelsverhalten ist unveraendert. Vor dem ersten Start auf dem Server: dotnet ef database update --project src/PolyTrader.Core (Migration AddPlatformColumns). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
67 lines
3.3 KiB
C#
67 lines
3.3 KiB
C#
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
using PolyTraderSharp.Models;
|
|
using PolyTraderSharp.Services;
|
|
|
|
namespace PolyTrader.Tests.Fakes
|
|
{
|
|
/// <summary>
|
|
/// In-Memory-Stub für <see cref="IClobClient"/>. Zeichnet Aufrufe auf und liefert steuerbare
|
|
/// Antworten, damit die Service-Interaktionen (SELL-Leiter, Startup-Reconciliation) ohne echten
|
|
/// CLOB integrationstestbar sind. Bewusst simpel und synchron (Task.FromResult).
|
|
/// </summary>
|
|
public sealed class FakeClobClient : IClobClient
|
|
{
|
|
public sealed record PlacedOrder(string TokenId, string Side, decimal Usdc, decimal Price, string OrderType,
|
|
bool IsNegRisk = false, int FeeBps = 0);
|
|
|
|
// Aufzeichnungen
|
|
public List<PlacedOrder> Placed { get; } = new();
|
|
public List<string> CanceledOrderIds { get; } = new();
|
|
public List<(string AssetId, decimal NewPrice, string Side)> ConflictCancels { get; } = new();
|
|
|
|
// Steuerbare Antworten
|
|
/// <summary>Ergebnis von PlaceOrderAsync (Default "OK"). Queue hat Vorrang, sonst dieser Wert.</summary>
|
|
public string PlaceResult { get; set; } = "OK";
|
|
public Queue<string> PlaceResults { get; } = new();
|
|
public bool CancelResult { get; set; } = true;
|
|
|
|
/// <summary>Offene Orders je Asset, die GetOpenOrdersAsync(assetId) zurückgibt.</summary>
|
|
public Dictionary<string, List<(string Id, string Side, decimal Price)>> OpenOrdersByAsset { get; } = new();
|
|
|
|
/// <summary>Alle offenen Orders des Accounts, die GetOpenOrdersAsync() ohne assetId zurückgibt (K2).</summary>
|
|
public List<(string Id, string Side, decimal Price)> AllOpenOrders { get; } = new();
|
|
|
|
public Task<string> PlaceOrderAsync(
|
|
AccountState account, string tokenId, string sideStr, decimal investAmountUsd, decimal limitPrice,
|
|
string orderType = "FOK", bool debugPayloadLog = false, bool isNegRisk = false, int actualFeeBps = 0,
|
|
decimal? overrideTickSize = null, int? overrideMakerDecimals = null, int? overrideTakerDecimals = null)
|
|
{
|
|
Placed.Add(new PlacedOrder(tokenId, sideStr, investAmountUsd, limitPrice, orderType, isNegRisk, actualFeeBps));
|
|
string result = PlaceResults.Count > 0 ? PlaceResults.Dequeue() : PlaceResult;
|
|
return Task.FromResult(result);
|
|
}
|
|
|
|
public Task CancelConflictingOrdersAsync(AccountState acc, string assetId, decimal newPrice, string sideStr)
|
|
{
|
|
ConflictCancels.Add((assetId, newPrice, sideStr));
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task<List<(string Id, string Side, decimal Price)>> GetOpenOrdersAsync(AccountState acc, string assetId = "")
|
|
{
|
|
if (string.IsNullOrEmpty(assetId))
|
|
return Task.FromResult(new List<(string, string, decimal)>(AllOpenOrders));
|
|
if (OpenOrdersByAsset.TryGetValue(assetId, out var list))
|
|
return Task.FromResult(new List<(string, string, decimal)>(list));
|
|
return Task.FromResult(new List<(string, string, decimal)>());
|
|
}
|
|
|
|
public Task<bool> CancelOrderAsync(AccountState acc, string orderId)
|
|
{
|
|
CanceledOrderIds.Add(orderId);
|
|
return Task.FromResult(CancelResult);
|
|
}
|
|
}
|
|
}
|