Skip to content

Store failed operations along with the specific result codes#474

Merged
aditya1702 merged 416 commits intomainfrom
store-failed-ops
Feb 4, 2026
Merged

Store failed operations along with the specific result codes#474
aditya1702 merged 416 commits intomainfrom
store-failed-ops

Conversation

@aditya1702
Copy link
Contributor

@aditya1702 aditya1702 commented Jan 30, 2026

What

  • Added ResultCode (string) and Successful (boolean) fields to the Operation type across all layers (database, GraphQL schema, data models, and client types)
  • Implemented comprehensive result code extraction logic for all Stellar operation types in codes.go with extensive test coverage
  • Updated database schema with new required fields and a partial index on failed operations
  • Modified participant processing to handle operations from both successful and failed transactions

Why

  • We were skipping failed operations and their state changes. However, freighter needs to show history for all failed txns/ops.
  • We were not storing result code and the specific inner result code for each operation

Known limitations

N/A

Issue that this PR addresses

Closes #475

aditya1702 and others added 30 commits January 14, 2026 13:21
Adds AccountChange struct and AccountOpType constants (CREATE/UPDATE/REMOVE)
to track native XLM balance changes during ingestion.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Processes xdr.LedgerEntryTypeAccount ledger changes to extract native XLM
balance modifications. Skips signer-only changes using AccountChangedExceptSigners().

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds accountChanges slice to IndexerBuffer with Push/Get methods.
Updates Merge() and Clear() to handle account changes.
Extends IndexerBufferInterface with account change methods.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replaces TrustLinesProcessorInterface with generic LedgerChangeProcessor[T]
that works for both trustline and account processors. Processes both in
same loop for efficiency.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds NativeBalance struct and implements:
- GetNativeBalance: query native balance for an account
- BatchUpsertNativeBalances: upsert/delete for live ingestion
- BulkInsertNativeBalances: COPY protocol for checkpoint population

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updates ingest_live.go to get account changes directly from buffer
(not filtered data) since native balances should be tracked for all
accounts regardless of participant filtering.

Updates ingest_backfill.go to include AccountChanges in BatchTokenChanges
struct and aggregate them during catchup mode for proper ordering.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replaces RPC calls for native XLM balance with PostgreSQL queries:
- BalancesByAccountAddress now fetches native balance from DB
- BalancesByAccountAddresses fetches native balance in parallel Phase 1
- Adds buildNativeBalanceFromDB helper function
- Updates accountKeyInfo struct to include nativeBalance field
- Removes native XLM ledger key building (SAC contracts only now)

This eliminates RPC round-trips for native balance queries.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…layer

- Delete TrustlineWithBalance struct (redundant with Trustline)
- Replace BatchAddContracts + BulkInsertContracts with BatchInsertContractTokens
- Replace BulkInsertTrustlines with BatchInsertTrustlines using []Trustline signature
- Update interface to reflect new consolidated methods

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace trustlineEntry with wbdata.Trustline in trustlineBatch
- Update batch.add to include ledger parameter
- Change batch.count field to batch.count() method
- Update ProcessTokenChanges to use BatchInsertContractTokens
- Update storeContractsInPostgres to use BatchInsertContractTokens
- Simplify flushTrustlineBatch to use BatchInsertTrustlines directly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rename TestAccountTokensModel_BulkInsertTrustlines to TestAccountTokensModel_BatchInsertTrustlines
- Rename TestAccountTokensModel_BatchAddContracts to TestAccountTokensModel_BatchInsertContractTokens
- Remove TestAccountTokensModel_BulkInsertContracts (merged into BatchInsertContractTokens tests)
- Update all TrustlineWithBalance usages to Trustline struct
- Update metrics mock expectations to new function names

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update BulkInsertTrustlines to BatchInsertTrustlines with []Trustline
- Update BulkInsertContracts to BatchInsertContractTokens

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create migration for account_sac_balances table to store SAC balances
  for contract addresses (C...)
- Add SACBalanceChange type and SACBalanceOp enum to indexer types
- Follows TrustlinesProcessor pattern for processing ledger changes
- Extracts absolute balance values from SAC contract data entries
- Only processes contract addresses (C...) - G-addresses use trustlines
- Extracts amount, authorized, and clawback fields from SAC balance map
- Add sacBalancesProcessor field to Indexer struct
- Initialize processor in NewIndexer constructor
- Call processor in processTransaction and push results to buffer
- Add PushSACBalanceChange and GetSACBalanceChanges buffer methods
- Update Merge and Clear to handle SAC balance changes
- Add SACBalance struct with balance, is_authorized, is_clawback_enabled fields
- Add GetSACBalances for reading SAC balances from DB
- Add BatchUpsertSACBalances for live ingestion upserts/deletes
- Add BulkInsertSACBalances for checkpoint population via COPY
- Add sacBalanceChanges parameter to ProcessTokenChanges interface
- Implement SAC balance processing with deduplication and sorting
- Update all callers in ingest_live.go and ingest_backfill.go
- Update BatchTokenChanges struct to include SACBalanceChanges
- Update mock and all test files
- Add SACBalances field to checkpointData struct
- Add sacBalanceEntry struct to hold extracted balance data
- Extract SAC balance values during checkpoint scanning for C-addresses
- Add extractSACBalanceFromValue helper to parse balance map
- Add storeSACBalancesInPostgres to insert verified SAC balances
- Use strkey.IsValidContract for proper address validation
- Add GetSACBalances to TokenCacheReader interface
- Implement GetSACBalances in tokenCacheService
- Add buildSACBalanceFromDB helper function
- Add sacBalances field to accountKeyInfo struct
- Fetch SAC balances from DB for contract addresses (C...)
- Skip RPC calls for SAC contracts when address is contract
- Update mock with GetSACBalances method
- Add result_code TEXT NOT NULL and successful BOOLEAN NOT NULL columns to migration
- Add partial index on successful column for failed operations
- Add ResultCode and Successful fields to Operation struct
- Create ForOperationResult function to extract result codes from XDR
- Handle outer codes (op_bad_auth, op_no_source_account, etc.)
- Handle inner codes via switch on all operation types
- Based on Horizon's codes implementation
- Add opIndex and opResults parameters
- Call ForOperationResult to get result code and success status
- Set ResultCode and Successful fields on Operation
- Remove early return for failed transactions in GetOperationsParticipants
- Skip Soroban participants for failed txs (they don't have ledger changes)
- Get operation results using tx.Result.OperationResults()
- Pass opIndex and opResults to ConvertOperation
- Update BatchInsert to include result_code and successful columns
- Update BatchCopy to include result_code and successful columns
- Add resultCode: String! field
- Add successful: Boolean! field
- Regenerate GraphQL code
- Add codes_test.go with unit tests for ForOperationResult
- Update utils_test.go Test_ConvertOperation with new signature
- Update all SQL INSERT statements in test files to include result_code and successful columns
@aditya1702 aditya1702 marked this pull request as ready for review January 30, 2026 17:37
@aditya1702 aditya1702 requested a review from Copilot January 30, 2026 17:37
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds support for storing operation result codes and success status alongside operation data. The changes enable the system to track both successful and failed operations with their specific result codes, providing more granular information about operation outcomes.

Changes:

  • Added ResultCode (string) and Successful (boolean) fields to the Operation type across all layers (database, GraphQL schema, data models, and client types)
  • Implemented comprehensive result code extraction logic for all Stellar operation types in codes.go with extensive test coverage
  • Updated database schema with new required fields and a partial index on failed operations
  • Modified participant processing to handle operations from both successful and failed transactions

Reviewed changes

Copilot reviewed 17 out of 18 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
internal/db/migrations/2025-06-10.3-create_indexer_table_operations.sql Added result_code and successful columns to operations table with partial index on failed operations
pkg/wbclient/types/types.go Added ResultCode and Successful fields to Operation type for client API
internal/indexer/types/types.go Added ResultCode and Successful fields to Operation type for indexer
internal/serve/graphql/schema/operation.graphqls Exposed resultCode and successful fields in GraphQL schema
internal/indexer/processors/codes.go New file implementing result code extraction for all operation types
internal/indexer/processors/codes_test.go Comprehensive unit tests for result code extraction
internal/indexer/processors/utils.go Updated ConvertOperation to extract and populate result codes
internal/indexer/processors/participants.go Removed early return for failed transactions to process all operations
internal/data/operations.go Updated batch insert and copy operations to include new fields
internal/integrationtests/data_validation_test.go Added validation for operation result codes in integration tests

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

case xdr.ManageBuyOfferResultCodeManageBuyOfferSellNoIssuer:
return "op_sell_no_issuer", nil
case xdr.ManageBuyOfferResultCodeManageBuyOfferBuyNoIssuer:
return "buy_no_issuer", nil
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent naming convention: The result code "buy_no_issuer" is missing the "op_" prefix, unlike the similar code "op_sell_no_issuer" on line 226. For consistency with the naming convention used throughout this file, this should be "op_buy_no_issuer".

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolved this

aditya1702 and others added 5 commits January 30, 2026 13:09
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Base automatically changed from result-xdr to main February 4, 2026 14:33
@aditya1702 aditya1702 merged commit 13c0444 into main Feb 4, 2026
9 checks passed
@aditya1702 aditya1702 deleted the store-failed-ops branch February 4, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Extract operation result code and store them

2 participants