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

@bananapus/721-hook-v6

v1.1.0

Published

`@bananapus/721-hook-v6` is the tiered NFT issuance layer for Juicebox V6. It lets a project mint ERC-721s on payment, attach tier-specific pricing and supply rules, mint reserves, and integrate custom token URI resolvers.

Readme

Juicebox 721 Hook

@bananapus/721-hook-v6 is the tiered NFT issuance layer for Juicebox V6. It lets a project mint ERC-721s on payment, attach tier-specific pricing and supply rules, mint reserves, and integrate custom token URI resolvers.

  • ARCHITECTURE.md — module layout, data flow, and the hook-store accounting model.
  • INVARIANTS.md — per-contract operation inventory and the guarantees the hook makes to projects and integrators.
  • ADMINISTRATION.md — admin surfaces, role matrix, immutable decisions, and recovery posture.
  • RISKS.md — threat model, accepted risks, and invariants to verify.
  • USER_JOURNEYS.md — example end-to-end flows for launching, paying, minting, and cashing out tiers.
  • AUDIT_INSTRUCTIONS.md — what to focus on for a security audit and how to start.
  • SKILLS.md — implementation nuances, gotchas, and reading order for working on this codebase.
  • STYLE_GUIDE.md — Solidity conventions and repo layout used across the V6 ecosystem.
  • CHANGELOG.md - V5 to V6 ABI and behavior deltas.
  • references/runtime.md — contract roles, the runtime pay and cash-out path, and high-risk areas.
  • references/operations.md — deployment surface, change checklist, and common failure modes.

Overview

This package is the main shared tiered NFT hook used across the V6 ecosystem. Projects use it to:

  • sell fixed-price NFT tiers through Juicebox payments
  • apply tier supply, reserve frequency, voting units, and discount rules
  • cash out tiers through the Juicebox terminal surface
  • plug in custom metadata resolvers such as Banny or Defifa

The deployer helps clone hooks for existing projects, and the project deployer helps launch new projects with a hook already attached.

Use this repo when a project's NFT logic should be part of its payment and cash-out flow. Do not use it for collection-specific rendering or game logic. Those belong in higher-level packages like Banny or Defifa.

This repo does more than "mint NFTs on pay." It changes how payment value, tier state, reserves, and cash-out behavior interact.

Key contracts

| Contract | Role | | --- | --- | | JB721TiersHook | Main ERC-721 tiers hook that manages minting, cash outs, metadata, and ruleset-aware behavior. | | JB721TiersHookStore | Shared storage contract for tier data and accounting. | | JB721TiersHookDeployer | Clone factory for deploying a hook for an existing project. | | JB721TiersHookProjectDeployer | Convenience deployer for launching a project with a hook already wired in. | | JB721Hook | Abstract base for 721 pay and cash-out hook behavior. | | JB721Checkpoints | Per-hook IVotes checkpoint module. Tracks historical owner checkpoints, per-tier owner-tracked voting units (getPastTierVotingUnits), global active vote totals (getPastTotalActiveVotes), per-tier active vote totals (getPastTotalTierActiveVotes), and per-account active tier voting units (getPastAccountTierActiveVotes). |

Mental model

Think about the repo in three pieces:

  1. JB721TiersHook defines behavior at the project edge
  2. JB721TiersHookStore is the tier accounting backend
  3. deployers package the hook into reusable launch and clone flows

If a bug affects supply, reserve minting, or tier lookup, it usually lives in the hook-store interaction. If it affects project wiring, it usually lives in the deployer path or in how the hook is attached to rulesets.

Read these files first

  1. src/JB721TiersHook.sol
  2. src/JB721TiersHookStore.sol
  3. src/libraries/JB721TiersHookLib.sol
  4. src/JB721TiersHookDeployer.sol or src/JB721TiersHookProjectDeployer.sol
  5. the resolver contract in the downstream repo, if present

Integration traps

  • this hook participates in treasury-facing execution, not only metadata
  • custom token URI resolvers should be treated as part of the trusted surface
  • adding a 721 hook through a deployer is easy; carrying the right ruleset behavior forward is where mistakes happen
  • JB721TiersHookProjectDeployer forwards the creation fee on a project launch and advertises the resolved fee payer via IJBPayerTracker.originalPayer, so a pay-routing fee receiver credits the launching user rather than the deployer. The deployer reads the payer from _msgSender() (ERC-2771), so a trusted forwarder still attributes the fee to the relayed user.
  • projects should be explicit about whether the hook affects pay, cash out, or only metadata-facing paths
  • reserve beneficiary defaults are mutable hook state, so operators should not rely on later same-batch updates when computing who receives reserve NFTs
  • future token-URI resolver slots are metadata authority; treat resolver changes like collection-facing admin actions
  • per-tier owner-tracked voting units are queryable via getPastTierVotingUnits(tierId, blockNumber): mints, transfers, and burns write ownership history, so the trace follows owned units regardless of delegation
  • active delegated vote totals are queryable globally via getPastTotalActiveVotes(blockNumber) / getTotalActiveVotes() and per tier via getPastTotalTierActiveVotes(tierId, blockNumber) / getTotalTierActiveVotes(tierId). These totals include only voting units held by accounts with a nonzero delegate, so a token in undelegated custody does not count and returned tokens become active again if the holder's delegation is still set.
  • per-account active tier voting units are queryable via getPastAccountTierActiveVotes(account, tierId, blockNumber). This follows the account holding the tier units, not the delegate receiving voting power, so reward distributors can cap tier-scoped claims against the holder's active units even when votes are delegated to another address.
  • current and historical tier membership is queryable via hasTiersOfAt(account, tierIds, matchMode, blockNumber), using checkpointed per-account tier balances with Any and All match modes. Empty tier arrays fail closed, and future blocks revert.
  • voting-unit reads and delegation activation use each owner's nonzero held-tier bitmap, not every tier in the catalog. This scans one storage word per 256 tier IDs (at most 256 words at the uint16 tier cap) plus the owner's held tiers, and updates one bitmap word when an account first enters or fully exits a tier.

Where state lives

  • tier definitions and accounting: JB721TiersHookStore
  • project-facing execution and permission checks: JB721TiersHook
  • collection-specific presentation: usually outside this repo in a resolver contract

That split is why UI bugs, economic bugs, and deployment bugs often land in different repos even when users describe them all as "721 hook issues."

High-signal tests

  1. test/E2E/Pay_Mint_Redeem_E2E.t.sol
  2. test/invariants/TierLifecycleInvariant.t.sol
  3. test/invariants/TieredHookStoreInvariant.t.sol
  4. test/regression/SplitCreditsMismatch.t.sol
  5. test/regression/ProjectDeployerRulesets.t.sol

Install

npm install @bananapus/721-hook-v6

Development

npm install
forge build
forge test

Useful scripts:

  • npm run deploy:mainnets
  • npm run deploy:testnets

Deployment notes

Hooks are deployed as clones and typically registered in the address registry. The package is designed to compose with Omnichain, Croptop, Defifa, Banny, and other packages that rely on tier-aware NFT issuance.

Repository layout

src/
  JB721TiersHook.sol
  JB721TiersHookStore.sol
  JB721TiersHookDeployer.sol
  JB721TiersHookProjectDeployer.sol
  abstract/
  interfaces/
  libraries/
  structs/
test/
  unit, E2E, fork, invariant, review, and regression coverage
script/
  Deploy.s.sol
  helpers/

Risks and notes

  • tier accounting is sensitive to reserve minting, split routing, and cross-currency normalization
  • tiny split allocations can round down to zero recipient amounts
  • custom token URI resolvers are part of the security surface
  • projects need to be deliberate about whether the hook participates in pay, cash out, or both paths
  • tier mutations after launch are powerful and should be permissioned carefully
  • distributors and curated drops that depend on historical 721 ownership should pre-warm checkpoints before relying on snapshot-based eligibility

When people say "the 721 hook," they often mean three different things: the hook contract, the store, and the metadata resolver plugged into it.

For AI agents

  • Separate hook behavior, store behavior, and resolver behavior in your explanation.
  • Read the store invariants and end-to-end pay/mint/redeem tests before summarizing lifecycle guarantees.
  • If metadata or rendering behavior is project-specific, move to the downstream resolver repo.