Fuel
Fuel is a high-performance modular execution layer with its own virtual machine (FuelVM) and Sway programming language.
Core Concepts
Processors
Fuel integration primarily uses one processor type:
FuelProcessor<TContract extends Contract>
: Binds to a specific Fuel contract ID (address) and requires its JSON ABI. It processes transactions involving this contract.- Typical Use Case: Monitoring a specific Sway contract (dApp, token, etc.).
- Binding:
FuelProcessor.bind({ address: 'fuel1...', abi: MyContractAbi, chainId: FuelNetwork.TESTNET, startBlock: 10000n })
- The ABI (
MyContractAbi
) is typically imported from the JSON file generated by theforc build
command. - The
TContract
type parameter can be inferred or explicitly set using the contract type generated byfuels typegen
for enhanced type safety.
Handlers
Handlers are defined within the FuelProcessor
to react to specific activities:
onTransaction(handler(transaction, ctx), fetchConfig?)
: Triggered for every transaction that interacts with the bound contract ID. Thetransaction
object contains decoded information about the transaction, including operations, inputs, outputs, and receipts.onLog<T>(handler(log, ctx), logIdFilter)
: Triggered when a specific log (identified by its ID derived from the ABI) is emitted within a transaction processed by the contract. Thelog
object contains the decoded log data (log.data
).onTransfer(handler(transfer, ctx), filter)
: Triggered when aTransfer
orTransferOut
receipt matches the provided filter criteria (contract ID, asset ID, sender (from
), recipient (to
)). Useful for tracking asset movements involving the bound contract.onBlockInterval(handler(block, ctx), interval?, backfillInterval?)
: Processes blocks based on block height intervals.onTimeInterval(handler(block, ctx), intervalMinutes?, backfillIntervalMinutes?)
: Processes blocks based on time intervals.onCall(handler(call, ctx), nameFilter)
(Currently Internal/Experimental): Aims to trigger on specific function calls within a transaction, similar to EVMonTrace
. Requires the contract ABI.
Context (ctx
)
ctx
)Handler functions receive a FuelContractContext<TContract>
object providing:
- Chain information:
chainId
. - Contract details:
contractAddress
,contractName
,contract
(afuels-ts
Contract instance for on-chain reads). - Block/Transaction details:
block
,transaction
,timestamp
. - Helper methods: Access to the
fuels-ts
provider
(ctx.provider
). - Standard SDK outputs:
ctx.meter.Counter('...')
,ctx.eventLogger.emit('...')
.
Fetch Configuration (fetchConfig
)
fetchConfig
)The onTransaction
handler accepts an optional fetchConfig
(currently focused on call filters for the internal onCall
).
Getting Started Example (Hypothetical Counter Contract)
import { FuelProcessor, FuelContractContext, FuelNetwork } from "@sentio/sdk/fuel";
import { CounterContractAbi } from "./abis/counter-contract-abi"; // ABI from forc build
import { CounterContract } from "./types/CounterContract"; // Types from fuels typegen
import { FuelLog } from "@sentio/sdk/fuel";
// Define the structure of the CountIncremented log based on the ABI
interface CountIncrementedLog {
counter: bigint;
amount: bigint;
}
const CONTRACT_ID = "fuel1qvhrq08r886ua2u6z0j3a5j0z3z5f7k6f7z3q5"; // Replace with your contract ID
FuelProcessor.bind({
address: CONTRACT_ID,
abi: CounterContractAbi,
chainId: FuelNetwork.TESTNET, // Or FuelNetwork.BETA_5
startBlock: 150000n,
})
.onTransaction(async (tx, ctx: FuelContractContext<CounterContract>) => {
// Process every transaction interacting with the contract
ctx.meter.Counter("transaction_cnt").add(1);
// Example: Check transaction status
if (tx.status === "success") {
ctx.meter.Counter("successful_txns").add(1);
} else {
ctx.meter.Counter("failed_txns").add(1);
}
})
.onLog<CountIncrementedLog>(async (log, ctx: FuelContractContext<CounterContract>) => {
// Process CountIncremented logs
ctx.eventLogger.emit("CountIncremented", {
distinctId: log.sender?.address, // Use sender if available in log context
newCounterValue: log.data.counter.toString(),
incrementAmount: log.data.amount.toString(),
});
ctx.meter.Gauge("latest_cnt").record(log.data.counter);
ctx.meter.Counter("total_incremented").add(log.data.amount);
}, "0x0000000000000001") // Replace with the actual Log ID for CountIncremented
.onBlockInterval(async (block, ctx: FuelContractContext<CounterContract>) => {
// Example: Reading contract state periodically
try {
const countResult = await ctx.contract.functions.count().get();
const currentCount = countResult.value.toBigInt();
ctx.meter.Gauge("onchain_count_snapshot").record(currentCount);
} catch (error) {
console.error("Failed to read count from contract:", error);
}
}, 100); // Check every 100 blocks
This overview covers the Fuel integration within the Sentio SDK. Refer to the fuel-processor.ts
, context.ts
, and the fuels-ts
documentation for more detailed information.
Updated 2 days ago