Skip to content

BE — Support multi-operation transactions with per-operation explanations #509

@Tinna23

Description

@Tinna23

Description

A single Stellar transaction can contain up to 100 operations of mixed types. The current backend only explains payment operations and skips everything else with a skipped_operations counter. This means most real-world transactions — which often combine create_account, change_trust, set_options, and payments — are only partially explained.

This issue makes the backend explain every operation in a transaction, returning a structured explanation for each one in order.

Current Behaviour

{
  "payment_explanations": [...],
  "skipped_operations": 3
}

Target Behaviour

{
  "operations": [
    {
      "index": 0,
      "type": "create_account",
      "summary": "GABC… funded and activated a new Stellar account GDST… with 1.5 XLM",
      "details": {
        "funder": "GABC...",
        "account": "GDST...",
        "starting_balance": "1.5"
      }
    },
    {
      "index": 1,
      "type": "payment",
      "summary": "GABC… sent 100 USDC to GDST…",
      "details": {
        "from": "GABC...",
        "to": "GDST...",
        "amount": "100",
        "asset": "USDC"
      }
    },
    {
      "index": 2,
      "type": "change_trust",
      "summary": "GDST… opted in to hold up to 10,000 USDC issued by GBBB…",
      "details": {
        "account": "GDST...",
        "asset": "USDC",
        "issuer": "GBBB...",
        "limit": "10000"
      }
    }
  ],
  "skipped_operations": 0
}

Operation Types to Support

Type Plain-English pattern
payment Already implemented — keep as-is
create_account "{funder} funded and activated a new Stellar account {account} with {starting_balance} XLM"
change_trust (add) "{account} opted in to hold up to {limit} {asset} issued by {issuer}"
change_trust (remove) "{account} removed their trust line for {asset}"
set_options "{account} updated account settings: {list of changes}"
account_merge "{source} merged their account into {destination}, transferring all remaining XLM"
manage_sell_offer (new) "{account} placed a sell order for {amount} {asset} at {price}"
manage_sell_offer (cancel) "{account} cancelled sell order #{offer_id}"
manage_buy_offer "{account} placed a buy order for {amount} {asset} at {price}"
path_payment_strict_send "{from} sent {send_amount} {send_asset}, {to} received {dest_asset}"
path_payment_strict_receive "{from} sent {src_asset}, {to} received exactly {dest_amount} {dest_asset}"
All others "{type} operation — full support coming soon" (never skip silently)

Key Files

  • packages/core/src/explain/operation/ — add one file per new operation type
  • packages/core/src/explain/operation/mod.rs — register all new modules
  • packages/core/src/models/operation.rs — add new variants to Operation enum
  • packages/core/src/services/horizon.rs — ensure all operation fields are mapped
  • packages/core/src/explain/transaction.rs — update to return operations[] instead of payment_explanations[]

Backward Compatibility

The response must remain backward compatible:

  • Keep payment_explanations field populated (for existing frontend consumers)
  • Add new operations[] field alongside it
  • Update skipped_operations to only count truly unsupported types

Acceptance Criteria

  • All 10 operation types listed above return a proper explanation
  • Multi-operation transactions return one explanation per operation in order
  • operations[] array present in response with correct index and type fields
  • payment_explanations still populated for backward compatibility
  • skipped_operations is 0 for transactions using only supported types
  • Unknown types return a graceful fallback (not empty/null)
  • Unit tests for each new operation type with at least 2 test cases each
  • cargo test passes with no regressions

Complexity: High · 200 pts

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official CampaignRustA language empowering everyone to build reliable and efficient software.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions