npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@clayno-club/asset-flow

v0.2.2

Published

Shared asset-flow classification and normalization for supported chains

Readme

@clayno-club/asset-flow

Deterministic asset-flow classification and normalization for supported chains.

This package turns transaction data into a canonical ownership history for a tracked asset. It is designed for consumers that want consistent classification results across services, codebases, or audit pipelines.

Current support:

  • Solana NFT asset-flow normalization via the root convenience exports such as classify, buildFlows, and buildOwnershipPeriods
  • Sui Popkins classification via explicit Sui exports such as classifySuiTransactionForAsset

What it does

  • classify supported chain transactions for a tracked asset
  • merge raw ownership evidence into enhanced Solana transactions when needed
  • normalize an asset's transaction history into canonical flows
  • derive ownership periods from normalized flows
  • explain why a transaction matched a given classification path
  • analyze provided transaction sets for review candidates

What it does not do

  • fetch transaction history from RPC providers or indexers
  • persist results to a database
  • manage queues, jobs, or orchestration

You provide the transaction data. The package provides deterministic interpretation.

Supported entrypoints

  • Root exports: Solana-oriented convenience API such as classify, buildMintHistory, buildFlows, buildValueMovements, and augmentWithRaw
  • Sui exports: explicit helpers such as classifySuiTransactionForAsset and the Sui transaction/type definitions

Install

pnpm add @clayno-club/asset-flow

Core API

Classification:

  • classify(tx, mint) — classify a single transaction for a tracked mint
  • explain(tx, mint) — same as classify, but returns the full decision trace

Raw augmentation:

  • shouldFetchRaw(tx, mint) — check if raw data would improve classification
  • augmentWithRaw(tx, rawTx) — merge raw ownership evidence into enhanced tx

History normalization:

  • buildMintHistory(transactions, mint) — full pipeline: flows + value movements + ownership periods
  • buildFlows(transactions, mint) — just the canonical flows
  • buildValueMovements(transactions, mint) — just the value movements
  • buildOwnershipPeriods(flows) — ownership periods from flows
  • extractMints(tx) — extract candidate mint addresses from a transaction

Example: classify one transaction

import { classify } from "@clayno-club/asset-flow";

const classification = classify(tx, mint);

console.log(classification.family);
console.log(classification.derivedType);
console.log(classification.materialization);

Example: augment enhanced data with raw ownership evidence

import { augmentWithRaw } from "@clayno-club/asset-flow";

const augmented = augmentWithRaw(enhancedTx, rawTx);

Example: normalize mint history

import { buildMintHistory } from "@clayno-club/asset-flow";

const normalized = buildMintHistory(transactions, mint);

console.log(normalized.flows);
console.log(normalized.valueMovements);
console.log(normalized.periods);

Example: explain a classification decision

import { explain } from "@clayno-club/asset-flow";

const explanation = explain(tx, mint);

console.log(explanation.facts);
console.log(explanation.candidates);
console.log(explanation.selection);

Concepts

The package is structured around three steps:

  1. Facts Convert transaction evidence into normalized facts about ownership change, settlement, program signals, and participants.

  2. Classification Match the transaction to a known family and determine whether it should materialize as a canonical flow, be skipped as non-settlement activity, or remain review-worthy.

  3. Normalization Turn classified transaction history into canonical mint flows, value movements, and ownership periods.

Output model

The normalized history contains:

  • flows Canonical mint ownership events such as MINT, SALE, TRANSFER, SWAP, LIST, DELIST, LOCK, UNLOCK, and FORECLOSURE

  • valueMovements Associated native or fungible settlement movements with roles such as SALE_GROSS, SELLER_PROCEEDS, ROYALTY, MARKETPLACE_FEE, RENT, and SWAP_CONSIDERATION

  • periods Reconstructed ownership periods derived from normalized beneficial flows

When to use raw data

Some Solana transactions do not expose enough ownership detail in enhanced/indexed form alone. When raw transaction data is available, use:

  • shouldFetchRaw()
  • augmentWithRaw()

This lets you keep the classification path deterministic while improving owner resolution for custody-heavy or protocol-heavy transactions.

Review analysis helpers

If you already have a set of transactions and want to identify unresolved patterns:

  • collectCoverageReviewCandidates() returns review-worthy transactions
  • clusterCoverageReviewCandidates() groups them into stable fingerprints
  • scanTransactionsForCoverage() combines both into a mint-scoped summary

These helpers are pure over provided transactions and do not fetch data.

Extending the matcher set

When adding support for a new marketplace or protocol family:

  1. identify the reusable evidence
  2. add or reuse fact-building signals
  3. add a narrow matcher for the family
  4. register it with the appropriate priority
  5. add fixture coverage and regression tests

Prefer adding a matcher for a real transaction family over expanding generic fallback behavior.

Testing

Typical verification:

pnpm --filter @clayno-club/asset-flow test
pnpm --filter @clayno-club/asset-flow build
pnpm --filter @clayno-club/asset-flow type-check