Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 51 additions & 3 deletions csharp/src/StationAPI/Endpoints/OrderEndpoints.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using Train.Solver.StationAPI.Configuration;
using Train.Solver.StationAPI.Helpers;
using Train.Solver.StationAPI.Models;
Expand Down Expand Up @@ -59,6 +60,8 @@ private static async Task<IResult> GetOrderAsync(
});
}

var enrichedOrder = EnrichTransactionNetworks(orderJson.Value);

var response = new OrderStatusResponse
{
Solver = new SolverProfileResponse
Expand All @@ -68,7 +71,7 @@ private static async Task<IResult> GetOrderAsync(
Description = solver.Description,
LogoUrl = solver.LogoUrl
},
Order = orderJson
Order = enrichedOrder
};

return Results.Ok(new ApiResponse<OrderStatusResponse> { Data = response });
Expand Down Expand Up @@ -149,7 +152,8 @@ await SseWriter.WriteEventAsync(context.Response, "error",
var orderJson = await solverClient.GetOrderAsync(solverId, hashlock, ct);
if (orderJson is not null)
{
var orderResponse = new OrderStatusResponse { Solver = profile, Order = orderJson };
var enrichedOrder = EnrichTransactionNetworks(orderJson.Value);
var orderResponse = new OrderStatusResponse { Solver = profile, Order = enrichedOrder };
var jsonOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
var json = JsonSerializer.Serialize(orderResponse, jsonOptions);
await SseWriter.WriteEventRawAsync(context.Response, "order", json, ct);
Expand Down Expand Up @@ -227,4 +231,48 @@ private static bool IsTerminalEventType(string eventType, JsonElement data)
return statusProp.GetString();
return null;
}
}

/// <summary>
/// Replaces transaction network slugs with caip2Id values derived from
/// the order's source/destination network fields (which are already caip2Id).
/// </summary>
private static JsonElement? EnrichTransactionNetworks(JsonElement orderElement)
{
var node = JsonNode.Parse(orderElement.GetRawText());
if (node is not JsonObject order) return orderElement;

var sourceCaip2Id = order["source"]?["network"]?.GetValue<string>();
var destCaip2Id = order["destination"]?["network"]?.GetValue<string>();

if (order["transactions"] is not JsonArray transactions)
return orderElement;

// Build slug → caip2Id map using unambiguous transaction types
var slugToCaip2Id = new Dictionary<string, string>();
foreach (var tx in transactions)
{
if (tx is not JsonObject txObj) continue;
var type = txObj["type"]?.GetValue<string>();
var slug = txObj["network"]?.GetValue<string>();
if (slug is null) continue;

if (type is "UserHTLCLock" or "UserHTLCRefund" && sourceCaip2Id is not null)
slugToCaip2Id.TryAdd(slug, sourceCaip2Id);
else if (type is "HTLCLock" or "HTLCRefund" or "CloseSolverLock" && destCaip2Id is not null)
slugToCaip2Id.TryAdd(slug, destCaip2Id);
}

// Replace network slugs with caip2Id
foreach (var tx in transactions)
{
if (tx is not JsonObject txObj) continue;
var slug = txObj["network"]?.GetValue<string>();
if (slug is not null && slugToCaip2Id.TryGetValue(slug, out var caip2Id))
{
txObj["network"] = caip2Id;
}
}

return JsonSerializer.Deserialize<JsonElement>(node.ToJsonString());
}
}
51 changes: 51 additions & 0 deletions csharp/src/StationAPI/station-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,57 @@
"logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png"
}
]
},
{
"caip2Id": "starknet:SN_SEPOLIA",
"displayName": "Starknet Sepolia",
"chainId": "SN_SEPOLIA",
"networkType": "starknet",
"logoUrl": "https://raw.githubusercontent.com/TrainProtocol/icons/main/networks/starknet.png",
"nativeTokenAddress": "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
"tokens": [
{
"symbol": "ETH",
"contract": "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
"decimals": 18,
"priceSymbol": "ETHUSDT",
"logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png"
}
]
},
{
"caip2Id": "aztec:devnet",
"displayName": "Aztec Devnet",
"chainId": "devnet",
"networkType": "aztec",
"logoUrl": "https://raw.githubusercontent.com/TrainProtocol/icons/main/networks/aztec.png",
"nativeTokenAddress": "0x02c31306cad429e0a00d3a4ee8ba251853099f835101ee2c637e9b3b9351a056",
"tokens": [
{
"symbol": "ETH",
"contract": "0x02c31306cad429e0a00d3a4ee8ba251853099f835101ee2c637e9b3b9351a056",
"decimals": 18,
"priceSymbol": "ETHUSDT",
"logoUrl": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png"
}
]
},
{
"caip2Id": "solana:devnet",
"displayName": "Solana Devnet",
"chainId": "devnet",
"networkType": "solana",
"logoUrl": "https://raw.githubusercontent.com/TrainProtocol/icons/main/networks/solana.png",
"nativeTokenAddress": "11111111111111111111111111111111",
"tokens": [
{
"symbol": "SOL",
"contract": "11111111111111111111111111111111",
"decimals": 9,
"priceSymbol": "SOLUSDT",
"logoUrl": "https://raw.githubusercontent.com/TrainProtocol/icons/main/networks/solana.png"
}
]
}
],
"solvers": [
Expand Down
Loading