Aptos

Aptos is a Layer 1 blockchain utilizing the Move language and its resource-based model.

Core Concepts

Processors

Aptos integration offers several processor types, listed in order of common usage:

User-Defined Processors

Generate type-safe processors from your smart contract ABIs using Sentio's code generation tools. These provide the best developer experience with full type safety and auto-completion.

// Example: Generated from PancakeSwap contract
import { pancakeswap } from './types/aptos/0xc7efb4076dbe143cbcd98cfaaa929ecfc8f299203dfff63b95ccb6bfe19850fa.js'

pancakeswap.bind({
  network: AptosNetwork.MAINNET,
  startVersion: 1000000n
}).onEventSwapEvent(async (evt, ctx) => {
  // Fully typed event data
  const { amount_x_in, amount_x_out } = evt.data_decoded
  // Process swap...
})

Built-in System Processors

Sentio SDK pre-generates type-safe processors from Aptos core system modules, providing ready-to-use bindings for system-level monitoring:

// Aptos coin module
import { aptos_coin } from '@sentio/sdk/aptos/builtin/0x1'

// Staking module
import { staking_contract } from '@sentio/sdk/aptos/builtin/0x1'

// Account module
import { account } from '@sentio/sdk/aptos/builtin/0x1'

These processors are generated by Sentio SDK from Aptos's system packages and provide fully-typed interfaces for monitoring token transfers, staking operations, and account activities.

AptosResourcesProcessor

Periodically fetches and processes Aptos resources associated with one or more accounts. Ideal for tracking account state changes over time or by block version.

  • Use Case: Monitoring account balances, tracking NFT ownership changes stored in resources
  • Binding: AptosResourcesProcessor.bind({ address: '0x...', network: AptosNetwork.MAINNET, startVersion: 123456n })

AptosModulesProcessor

Binds to a specific Aptos module (smart contract) address for manual event and function call processing.

  • Note: Consider using code generation for type-safe processors instead
  • Binding: AptosModulesProcessor.bind({ address: '0x...', network: AptosNetwork.MAINNET, startVersion: 123456n })
  • Advanced Use: Rarely needed as user-defined processors handle most use cases better

AptosGlobalProcessor

Processes transactions across the entire Aptos network with optional filtering.

  • Warning: Can be resource-intensive; use specific processors when possible
  • Binding: AptosGlobalProcessor.bind({ network: AptosNetwork.MAINNET, startVersion: 123456n })
  • Advanced Use: Only for chain-wide analytics like tracking gas usage patterns or monitoring whale wallets

Handlers

Processors define handlers to react to specific blockchain activities:

  • Transaction-Based (forAptosModulesProcessor, AptosGlobalProcessor):

    • onMoveEvent(handler(event, ctx), filter): Triggered when a specific Move event matching the filter is emitted within a transaction. The event object is automatically decoded based on the module's ABI if available.
    • onEntryFunctionCall(handler(call, ctx), filter): Triggered when an entry function matching the filter is called within a transaction. The call payload is automatically decoded.
    • onTransaction(handler(tx, ctx), filter?): Triggered for every transaction processed by the processor (optionally filtered by sender or includeFailed). Provides the raw UserTransactionResponse.
    • onTimeInterval(handler(txns, ctx), intervalMinutes?, backfillIntervalMinutes?): Processes transactions in time-based batches.
    • onVersionInterval(handler(txns, ctx), interval?, backfillInterval?): Processes transactions in version-based batches.
  • Resource-Based (forAptosResourcesProcessor):

    • onTimeInterval(handler(resources, ctx), intervalMinutes?, backfillIntervalMinutes?, type?, fetchConfig?): Periodically fetches resources based on time.
    • onVersionInterval(handler(resources, ctx), interval?, backfillInterval?, type?, fetchConfig?): Periodically fetches resources based on block versions.
    • onResourceChange(handler(changes, ctx), typeDescriptor): Processes detailed changes (write, delete, create) to specific resource types within transactions included by the bound module (Note: Requires AptosModulesProcessor and appropriate fetch config).

Context (ctx)

Each handler receives a Context object (AptosContext for transaction-based handlers, AptosResourcesContext for resource-based handlers) providing:

  • Chain-specific information: network, version.
  • Transaction details: transaction (for AptosContext).
  • Timestamp: timestampInMicros or getTimestamp().
  • Helper methods: client.getAccountResource(...), coder.decodeEvent(...), etc.
  • Standard SDK outputs: ctx.meter.Counter('...'), ctx.eventLogger.emit('...'), ctx.exporter.aptos_Account(...).

Fetch Configuration

Handlers can optionally include a fetchConfig parameter to specify what additional data should be fetched for the transaction being processed. This optimizes data fetching. The configuration is defined by the MoveFetchConfig interface:

interface MoveFetchConfig {
    allEvents: boolean;            // Fetch all events for the transaction
    includeFailedTransaction?: boolean; // Include failed transactions
    inputs: boolean;               // Fetch transaction input arguments
    resourceChanges: boolean;      // Fetch resource changes
    resourceConfig?: ResourceConfig; // Specific configuration for resource fetching
    supportMultisigFunc?: boolean;   // Support for multisig functions
}

For example, to fetch resource changes for transactions that emit a specific event:

processor.onEvent(..., { fetchConfig: { resourceChanges: true } }); // Fetch resource changes for transactions with this event

Getting Started Example

First, create an Aptos processor project: yarn sentio create -c aptos <project-name>. You can refer to the CLI Reference to learn details.

import { AptosModulesProcessor, AptosContext, AptosNetwork } from "@sentio/sdk/aptos";
import { pancakeswap } from './types/aptos/0xc7efb4076dbe143cbcd98cfaaa929ecfc8f299203dfff63b95ccb6bfe19850fa.js'; // Generated types

AptosModulesProcessor.bind({
  address: pancakeswap.DEFAULT_OPTIONS.address,
  network: AptosNetwork.MAINNET,
  startVersion: 1000000n // Start processing from version 1,000,000
})
.onEvent(async (event: pancakeswap.SwapEvent, ctx: AptosContext) => {
  ctx.meter.Counter("swap_volume").add(event.data_decoded.amount_x_in + event.data_decoded.amount_y_in);
  ctx.eventLogger.emit("Swap", {
    distinctId: ctx.transaction.sender,
    pair: event.type_arguments[0], // Assuming type argument represents the pair
    amountXIn: event.data_decoded.amount_x_in,
    amountYIn: event.data_decoded.amount_y_in,
    amountXOut: event.data_decoded.amount_x_out,
    amountYOut: event.data_decoded.amount_y_out,
  });
}, { type: `${pancakeswap.DEFAULT_OPTIONS.address}::swap::SwapEvent` }) // Filter for SwapEvent
.onEntryFunctionCall(async (call: pancakeswap.Add_liquidityPayload, ctx: AptosContext) => {
  if (!ctx.transaction.success) return; // Skip failed transactions
  ctx.meter.Counter("liquidity_adds").add(1);
  ctx.eventLogger.emit("AddLiquidity", {
    distinctId: ctx.transaction.sender,
    amountX: call.arguments_decoded[0],
    amountY: call.arguments_decoded[1],
  });
}, { function: `${pancakeswap.DEFAULT_OPTIONS.address}::swap::add_liquidity` }); // Filter for add_liquidity function