Skip to content

fabriziopfannl/act

Repository files navigation

ACT (Actions for Chain Transactions)

npm license downloads

Open-source library to normalize raw blockchain transactions (EVM calldata, Solana instructions, etc.) into a deterministic list of semantic actions. No judgments, no alerts, no AI.

What it does

  • Converts raw inputs (EVM calldata, Solana instructions, logs) into NormalizedAction[].
  • Describes only the real actions that occurred in the transaction.
  • Provides a standard action taxonomy and an extensible plugin framework.

Installation

npm install act-chain

Repo name: act
npm package: act-chain

How it differs from existing tools

  • ABI/log decoders: they decode, but do not produce a standardized action list.
  • Transfer trackers: they cover only a narrow subset (e.g. ERC20/721/1155).
  • Explainers/simulators: often add heuristics or UX layers; ACT stays neutral and deterministic.
  • Chain-specific parsers: ACT targets multi-chain from day one with a shared action schema.

What it does NOT do

  • No risk scoring.
  • No human-readable explanations.
  • No opaque heuristics.
  • No AI.

Quick example (TypeScript)

import {
  normalizeTx,
  registerChainNormalizer,
  registerActionDetector,
  listSupportedActions,
} from "act-chain";

// 1) Register a chain normalizer
registerChainNormalizer("evm", evmNormalizer);

// 2) Register action detectors
registerActionDetector("TOKEN_TRANSFER", erc20TransferDetector);
registerActionDetector("TOKEN_APPROVAL", erc20ApprovalDetector);

// 3) Normalize a transaction
const actions = await normalizeTx(
  {
    chain: "evm",
    txHash: "0x...",
    calldata: "0x...",
    logs: [/* receipt logs */],
  },
  { includeRawRefs: true }
);

console.log(actions);

// 4) List supported actions
console.log(listSupportedActions());

Example input/output

Input:

const tx = {
  chain: "evm",
  txHash: "0xabc...",
  calldata: "0xa9059cbb...",
  logs: [
    {
      address: "0xToken",
      topics: [
        "0xddf252ad...", // Transfer(address,address,uint256)
        "0xFrom",
        "0xTo",
      ],
      data: "0x00000000000000000000000000000000000000000000000000000000000003e8",
      logIndex: 12,
    },
  ],
};

Output:

[
  {
    action_type: "TOKEN_TRANSFER",
    chain: "evm",
    actors: {
      from: "0xFrom",
      to: "0xTo",
      initiator: "0xFrom",
    },
    assets: [
      {
        asset_type: "token",
        token_address: "0xToken",
        token_standard: "ERC20",
      },
    ],
    amounts: [
      {
        asset_index: 0,
        amount: "1000",
      },
    ],
    metadata: {
      method: "transfer",
    },
    raw_refs: {
      txHash: "0xabc...",
      logIndex: 12,
    },
  },
];

Real-world use cases

  • Wallets: show on-chain actions without opinions.
  • Explorers: standardize feeds and filters by action type.
  • Analytics: unify metrics across chains.
  • Simulators: build UIs for multi-action transactions.

How to extend

  • Add an action: implement a detector and register it.
  • Add a chain: implement a chain normalizer.
  • Extend metadata: use metadata with namespaced keys (e.g. protocol.uniswap.pool).
  • Extend metadata post-detection: register metadata extenders for an action type.
  • Provide ABI hints: register an ABI resolver for a chain and decode calldata deterministically.

Philosophy

Neutrality, determinism, extensibility, and great DX. The library only answers: "What real actions occur in this transaction?"

Roadmap

  • v0.1: EVM transfers + approvals
  • v0.2: swaps + multicall
  • v0.3: Solana
  • v1.0: plugin ecosystem

EVM ABI helpers (minimal)

ACT includes a tiny helper for common ERC20 selectors without external deps:

  • decodeErc20Transfer(calldata)
  • decodeErc20Approval(calldata)
  • decodeErc20Calldata(calldata)

ABI resolver (optional)

You can register a resolver that returns known function signatures for a target address:

  • registerAbiResolver("evm", (address) => ["transfer(address,uint256)", ...])

Detectors can use this to gate calldata decoding without relying on external RPCs.

Plugin manifest (optional)

Plugins can expose a lightweight manifest for discovery and compatibility:

  • name, version, actVersion
  • optional actions, chains, metadataExtenders

Why now

  • On-chain activity is multi-chain, but action standards are fragmented.
  • Developers need a neutral, deterministic layer before UI, analytics, or risk.
  • An open, plugin-based action registry enables collaboration and coverage at scale.

Repo structure (proposal)

/core
/chains/evm
/chains/solana
/actions
/plugins
/types
/tests
README.md
CONTRIBUTING.md

## Example input/output
Input:
```ts
const tx = {
  chain: "evm",
  txHash: "0xabc...",
  calldata: "0xa9059cbb...",
  logs: [
    {
      address: "0xToken",
      topics: [
        "0xddf252ad...", // Transfer(address,address,uint256)
        "0xFrom",
        "0xTo",
      ],
      data: "0x00000000000000000000000000000000000000000000000000000000000003e8",
      logIndex: 12,
    },
  ],
};

Output:

[
  {
    action_type: "TOKEN_TRANSFER",
    chain: "evm",
    actors: {
      from: "0xFrom",
      to: "0xTo",
      initiator: "0xFrom",
    },
    assets: [
      {
        asset_type: "token",
        token_address: "0xToken",
        token_standard: "ERC20",
      },
    ],
    amounts: [
      {
        asset_index: 0,
        amount: "1000",
      },
    ],
    metadata: {
      method: "transfer",
    },
    raw_refs: {
      txHash: "0xabc...",
      logIndex: 12,
    },
  },
];

Real-world use cases

  • Wallets: show on-chain actions without opinions.
  • Explorers: standardize feeds and filters by action type.
  • Analytics: unify metrics across chains.
  • Simulators: build UIs for multi-action transactions.

How to extend

  • Add an action: implement a detector and register it.
  • Add a chain: implement a chain normalizer.
  • Extend metadata: use metadata with namespaced keys (e.g. protocol.uniswap.pool).
  • Extend metadata post-detection: register metadata extenders for an action type.
  • Provide ABI hints: register an ABI resolver for a chain and decode calldata deterministically.

Philosophy

Neutrality, determinism, extensibility, and great DX. The library only answers: "What real actions occur in this transaction?"

Roadmap

  • v0.1: EVM transfers + approvals
  • v0.2: swaps + multicall
  • v0.3: Solana
  • v1.0: plugin ecosystem

EVM ABI helpers (minimal)

ACT includes a tiny helper for common ERC20 selectors without external deps:

  • decodeErc20Transfer(calldata)
  • decodeErc20Approval(calldata)
  • decodeErc20Calldata(calldata)

ABI resolver (optional)

You can register a resolver that returns known function signatures for a target address:

  • registerAbiResolver("evm", (address) => ["transfer(address,uint256)", ...])

Detectors can use this to gate calldata decoding without relying on external RPCs.

Plugin manifest (optional)

Plugins can expose a lightweight manifest for discovery and compatibility:

  • name, version, actVersion
  • optional actions, chains, metadataExtenders

Why now

  • On-chain activity is multi-chain, but action standards are fragmented.
  • Developers need a neutral, deterministic layer before UI, analytics, or risk.
  • An open, plugin-based action registry enables collaboration and coverage at scale.

About

Deterministic on‑chain action normalization library for EVM + Solana.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors