Follow the Money: Token Transfer Processor Makes Tracking a Breeze

Author

Karthik Iyer

Publishing date

Have you ever tried tracking token movements on Stellar and felt like you were playing detective with a blindfold on? One minute you're parsing operation results, the next you're diving into ledger entry changes, and somehow you still missed that DEX swap that happened three operations ago.

Sound familiar? Yeah, we've all been there.

The Old Way: Detective Work Nobody Asked For

Before the Token Transfer Processor (TTP), tracking token movements on Stellar was like trying to follow breadcrumbs in a hurricane. Sure, you could use Horizon's /payments or /effects endpoints, but good luck with that inconsistent schema and missing half the story. Maybe you got the basic payments, but what about SEP-41 tokens, fees, or that complex path payment that touched three different assets?

For complete tracking, you'd need to:

  • Parse operations manually (payments, path payments, DEX operations...)
  • Analyze operation results to see what actually happened
  • Cross-reference ledger entry changes to catch the edge cases
  • Write custom logic for every operation type
  • ​​Realize that Horizon's endpoints were only giving you part of the picture
  • Pray you didn't miss anything important (spoiler: you probably did)

And that's just for one token! Multiply that by every asset you care about, and you've got yourself a full-time job just figuring out where the money went.

The New Way:Track Everything, Effortlessly (Like, Literally)

Enter the Token Transfer Processor – your new best friend for following token movements on Stellar. TTP is a Go package that does all the heavy lifting for you, automatically generating clean, standardized events for every token movement on the network.

Here's what TTP catches for you:

  • Simple payments and path payments
  • DEX trades and liquidity pool operations
  • Smart contract token events
  • Network fees (because those matter too!)

and many more…

Instead of writing hundreds of lines of parsing logic, you get nice, clean events like:


// Fee Event
{
  "meta": {
    "ledgerSequence": 58155263,
    "closedAt": "2025-07-24T23:42:31Z",
    "txHash": "ca36fdc5d786c31ccf484e1b2a7d6c55d91aae256c0abb2ef7276f4dff055db8",
    "transactionIndex": 280,
    "contractAddress": "CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA"
  },
  "fee": {
    "from": "GBGWQFSJSOMJ2BTOH5RLZUTZPV544YR2DF5CGYL7WDZ2Y6OSRHR6TUBE",
    "asset": {
      "native": true
    },
    "amount": "192133"
  }
}


// Transfer event
{
  "meta": {
    "ledgerSequence": 58155263,
    "closedAt": "2025-07-24T23:42:31Z",
    "txHash": "d3df6d42d92830d2f1b57e2f15cfe07dd22e58e1b06e5a7451ae9b1fa96813e0",
    "transactionIndex": 213,
    "operationIndex": 1,
    "contractAddress": "CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75"
  },
  "transfer": {
    "from": "GDQOIHLHKQ7T47TSTGOICGFSAVVQOHP5YU4LIHVIMVI56NO2TV3GKVBU",
    "to": "GDQOIHLHKQ7T47TSTGOICGFSAVVQOHP5YU4LIHVIMVI56NO2TV3GKVBU",
    "asset": {
      "issuedAsset": {
        "assetCode": "USDC",
        "issuer": "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN"
      }
    },
    "amount": "1911"
  }
}


// Mint event  
{
  "meta": {
    "ledgerSequence": 58155263,
    "closedAt": "2025-07-24T23:42:31Z",
    "txHash": "53f947137e8993b8cd9e3e03f79e81c33ec3a3ce17abf566f6f8cbfc9df1d794",
    "transactionIndex": 259,
    "operationIndex": 1,
    "contractAddress": "CB23WRDQWGSP6YPMY4UV5C4OW5CBTXKYN3XEATG7KJEZCXMJBYEHOUOV"
  },
  "mint": {
    "to": "GBASYT7Y7RKB2WNHU3BQOEFW4F6Y5E5PMQ2VTDFZG5PKAKA2IVPMXRIN",
    "asset": {
      "issuedAsset": {
        "assetCode": "KALE",
        "issuer": "GBDVX4VELCDSQ54KQJYTNHXAHFLBCA77ZY2USQBM4CSHTTV7DME7KALE"
      }
    },
    "amount": "291399795"
  }
}

And here's a bonus for asset issuers: tracking your token's circulating supply becomes trivial. Just sum up all your mint events and subtract all your burn events – boom, you've got real-time circulating supply without breaking a sweat. No more manually tracking every payment to and from your issuing account.

CAP-67 Powered

TTP plays nicely with CAP-67 Unified Events, giving you a consistent format whether you're dealing with native Stellar operations or smart contract interactions. It's like having a universal translator for token movements – everything speaks the same language.

Getting Started

Want to start tracking token movements without the headache? TTP has you covered:

Go
// Initialize the processor
processor := token_transfer.NewEventsProcessor(networkPassphrase)

// Process a ledger and get all token events
events, err := processor.EventsFromLedger(ledgerCloseMeta)
if err != nil {
    // Handle error
}

// Now you have clean events for every token movement!
for _, event := range events {
    fmt.Printf("Event: %s, ContractAddress: %s, Asset: %s, Amount: %s\n", event.GetEventType(), event.GetMeta().ContractAddress, event.GetAsset(), event.GetAmount())
}

That's it. No more custom parsers, no more missed transactions, no more pulling your hair out trying to figure out where that USDC went.

The Bottom Line

Token Transfer Processor turns the chaotic world of Stellar token tracking into something actually manageable. Whether you're building an indexer, a wallet, an exchange, a DeFi protocol, or just trying to understand what's happening on the network, TTP gives you the clean, reliable events you need.

Because let's be honest – life's too short to manually parse ledger entry changes.

Ready to simplify your token tracking? Check out the Token Transfer Processor docs and start following the money the easy way.

Recommended Reading:

  1. Stellar Events: Track All the Things
  2. Stellar Events: Retroactive Events