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/swap-terminal-v6

v0.0.2

Published

A Juicebox terminal that accepts payments in any token, swaps them via Uniswap V3, and forwards the proceeds to another terminal that accepts the output token.

Readme

nana-swap-terminal-v5

A Juicebox terminal that accepts payments in any token, swaps them via Uniswap V3, and forwards the proceeds to another terminal that accepts the output token.

If you're having trouble understanding this contract, take a look at the core protocol contracts and the documentation first. If you have questions, reach out on Discord.

Architecture

| Contract | Description | |----------|-------------| | JBSwapTerminal | Core terminal. Accepts any token via pay or addToBalanceOf, swaps through a Uniswap V3 pool to a configured TOKEN_OUT, then forwards the output to the project's primary terminal. Uses TWAP oracle for automatic slippage protection when the caller doesn't provide a quote. | | JBSwapTerminalRegistry | A proxy terminal that delegates pay and addToBalanceOf to a per-project or default JBSwapTerminal instance. Allows project owners to choose (and lock) which swap terminal implementation they use. |

How It Works

  1. A payer calls pay(projectId, token, amount, ...) with any token.
  2. The terminal accepts the token (supports ERC-20 approvals and Permit2).
  3. If token != TOKEN_OUT, it swaps via the project's configured Uniswap V3 pool.
  4. Slippage protection: the caller can pass a minimum output quote in metadata (quoteForSwap key), or the terminal calculates one from the pool's TWAP oracle with dynamic slippage tolerance.
  5. The output tokens are forwarded to the project's primary terminal for TOKEN_OUT via terminal.pay(...) or terminal.addToBalanceOf(...).
sequenceDiagram
    participant Frontend client
    participant JBDirectory
    participant Uniswap pool
    participant JBSwapTerminal
    participant JBMultiTerminal
    Note left of Frontend client: User attempts to pay project with USDC
    Frontend client->>JBDirectory: Checks project's primary USDC terminal
    JBDirectory->>Frontend client: Returns JBSwapTerminal if a USDC pool is available
    Frontend client->>JBSwapTerminal: Calls pay(...) with USDC payment data (and optional Uniswap quote)
    JBSwapTerminal->>JBDirectory: Checks project's primary ETH terminal
    JBDirectory->>JBSwapTerminal: Returns JBMultiTerminal for ETH
    JBSwapTerminal->>Uniswap pool: Swaps USDC for ETH
    JBSwapTerminal->>JBMultiTerminal: Pays ETH to JBMultiTerminal
    Note right of JBMultiTerminal: Mint tokens for original beneficiary

Install

For projects using npm to manage dependencies (recommended):

npm install @bananapus/swap-terminal

For projects using forge to manage dependencies:

forge install Bananapus/nana-swap-terminal

If you're using forge, add @bananapus/swap-terminal/=lib/nana-swap-terminal/ to remappings.txt.

Develop

nana-swap-terminal uses npm (version >=20.0.0) for package management and Foundry for builds and tests.

npm ci && forge install

| Command | Description | |---------|-------------| | forge build | Compile the contracts and write artifacts to out. | | forge test | Run the tests. | | forge fmt | Lint. | | forge build --sizes | Get contract sizes. | | forge coverage | Generate a test coverage report. | | forge clean | Remove the build artifacts and cache directories. |

Scripts

| Command | Description | |---------|-------------| | npm test | Run local tests. | | npm run test:fork | Run fork tests (for use in CI). | | npm run coverage | Generate an LCOV test coverage report. |

Configuration

Key foundry.toml settings:

  • solc = '0.8.23'
  • evm_version = 'paris' (L2-compatible)
  • optimizer_runs = 100000000

Repository Layout

nana-swap-terminal-v5/
├── src/
│   ├── JBSwapTerminal.sol          # Core swap terminal
│   ├── JBSwapTerminalRegistry.sol  # Per-project terminal routing
│   └── interfaces/
│       ├── IJBSwapTerminal.sol     # Swap terminal interface
│       ├── IJBSwapTerminalRegistry.sol # Registry interface
│       └── IWETH9.sol              # WETH wrapper interface
├── script/
│   └── Deploy.s.sol                # Deployment script
└── test/
    ├── Fork/                       # Fork tests
    └── helper/                     # Test helpers

Payment Metadata

The JBSwapTerminal accepts encoded metadata in its pay(...) function. Metadata is decoded using JBMetadataResolver:

(bool exists, bytes memory quote) =
    JBMetadataResolver.getDataFor(JBMetadataResolver.getId("quoteForSwap"), metadata);

if (exists) {
    (minAmountOut) = abi.decode(quote, (uint256));
}

If no quote is provided, the terminal calculates one from the pool's TWAP oracle with a dynamic slippage tolerance based on the estimated price impact of the swap.

The terminal also supports Permit2 metadata (key: "permit2") for gasless token approvals.

Risks

  • The terminal never holds a token balance. After every swap, all output tokens are forwarded and leftover input tokens are returned to the payer.
  • Pool validation uses FACTORY.getPool() rather than create2, so the terminal works on chains where Uniswap V3 factory bytecode may differ.
  • TWAP fallback: when no observations exist, the terminal falls back to the pool's current spot tick rather than reverting.
  • addDefaultPool calls pool.increaseObservationCardinalityNext(10) to proactively set up TWAP history. _getQuote also reverts if observations are missing as a safety net.