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

@nonnux/world-swap

v0.4.0

Published

Drop-in token swap card + quote API for World App mini apps (Uniswap V2/V3 on World Chain).

Readme

@nonnux/world-swap

A drop-in token swap for World App mini apps — a ready-made swap card plus the quote API behind it. Routes through Uniswap V2, V3 and cross-version pools on World Chain, with a 1% platform fee.

It's the same swap that powers the nonnux mini apps (UFO PIZZA SLICE, PAU$, REI$ Slots, …), packaged so you can add it to your own mini app in a couple of lines.

┌──────────────────────────┐        ┌──────────────────────────────┐
│  <SwapCard />  (client)   │ ─────▶ │  /api/swap/quote  (server)   │
│  wallet · UI · tx via     │  POST  │  reads Uniswap V2/V3 via RPC │
│  MiniKit.sendTransaction  │ ◀───── │  (ethers, no DB, no secrets) │
└──────────────────────────┘        └──────────────────────────────┘

Requirements

  • A Next.js app (App Router) — it provides the API route.
  • Tailwind CSS v4 — the card is styled with Tailwind utility classes.
  • Peer deps (you almost certainly already have these): react, react-dom, ethers@^6, @worldcoin/minikit-js@>=1.9.

Install

npm install @nonnux/world-swap

The package ships pre-bundled (minified ESM, with React/ethers/MiniKit kept external), so no extra bundler config is needed. If your setup ever fails to resolve it, you can add transpilePackages: ['@nonnux/world-swap'] to next.config.js.

Usage

1. Mount the quote API

Create app/api/swap/quote/route.js:

// Batteries-included: nonnux token list + World Chain contracts.
export { POST, GET } from '@nonnux/world-swap/server';

2. Render the card

'use client';
import { SwapCard } from '@nonnux/world-swap';
import { Button } from '@/components/ui/Button'; // your own button

export default function SwapTab({ user }) {
  return <SwapCard walletUser={user} Button={Button} />;
}

That's it. walletUser is your connected user object ({ address }); pass null to show the "connect your wallet" state. Button is your own button component so the CTA matches your app's look.

Token icons are loaded from /<icon> (e.g. /tokens/slice.gif) in your public/ folder. Copy the icons you need, or point tokens[].icon at a URL.


World App Developer Portal setup (required)

World App rejects any contract or token your mini app hasn't whitelisted — skip this and swaps fail with invalid_contract. In the Developer Portal → your app → Configuration → Advanced, paste these (comma-separated).

Contract Entrypoints — the 3 swap contracts + every tradeable token:

0x4479A14811274D0eEB8Eb8932fA5A49b51F37852,0x4Cf23b3C9BeB48b85bc8F01E3dAB674Ce94E180a,0x380a940524C4cC1829f654B7790B338f676C31b8,0x513530649BAC862c38b65e957E6EA38d3f86F3dc,0x10377A2e9CC81A8822885cd847e577F7F39B5574,0x2e5f6BB8C993e64B3bC1fC9473C8B2CDEd772D06,0xE67Fb81ca7d20eB90bA3a53220018a9A7f870de8,0x9d59Bb9d85Ae4622116Ad11055B5be4349b67dc2,0x3Cb880f7ac84950c369e700deE2778d023b0C52d,0xE977de70dd1F571Aa563E41525C28b4F1eDB69ba,0x03995cE5Ad612a2cC3E4DFBEEb0EeD7BC165749b,0x06B4C6830bb19BF07A88ff96758003074EaE9c52,0x2cFc85d8E48F8EAB294be644d9E25C3030863003,0x4200000000000000000000000000000000000006,0xab09A728E53d3d6BC438BE95eeD46Da0Bbe7FB38

Permit2 Tokens — every tradeable token (same list, minus the 3 contracts):

0x513530649BAC862c38b65e957E6EA38d3f86F3dc,0x10377A2e9CC81A8822885cd847e577F7F39B5574,0x2e5f6BB8C993e64B3bC1fC9473C8B2CDEd772D06,0xE67Fb81ca7d20eB90bA3a53220018a9A7f870de8,0x9d59Bb9d85Ae4622116Ad11055B5be4349b67dc2,0x3Cb880f7ac84950c369e700deE2778d023b0C52d,0xE977de70dd1F571Aa563E41525C28b4F1eDB69ba,0x03995cE5Ad612a2cC3E4DFBEEb0EeD7BC165749b,0x06B4C6830bb19BF07A88ff96758003074EaE9c52,0x2cFc85d8E48F8EAB294be644d9E25C3030863003,0x4200000000000000000000000000000000000006,0xab09A728E53d3d6BC438BE95eeD46Da0Bbe7FB38

The first three entrypoints are the swap contracts (V2 0x4479…, V3 0x4Cf2…, cross-version router 0x380a…); the other twelve are the token contracts. Using a custom tokens list? Whitelist your own token addresses (the 3 swap contracts stay the same).


Customising

Everything is optional and falls back to the nonnux / World Chain defaults.

Your own token list

app/api/swap/quote/route.js:

import { createSwapQuoteHandler } from '@nonnux/world-swap/server';
import { MY_TOKENS } from '@/config/tokens';

export const { POST, GET } = createSwapQuoteHandler({ tokens: MY_TOKENS });

Component:

import { SwapCard } from '@nonnux/world-swap';
import { MY_TOKENS } from '@/config/tokens';

<SwapCard walletUser={user} Button={Button} tokens={MY_TOKENS} />

A token looks like:

{
  symbol: 'SLICE',
  name: 'UFO PIZZA',
  address: '0x...',
  icon: '/tokens/slice.gif',          // path in /public or a URL
  gradient: 'from-orange-500 to-yellow-500', // Tailwind gradient
  decimals: 18,
  emoji: '🍕',                         // fallback if icon fails
  externalTaxPercent: 0,              // token transfer tax, if any
  poolVersion: 'v2',                  // 'v2' | 'v3'
  v3FeeTier: 10000,                   // only for v3 tokens
}

<SwapCard /> props

| Prop | Default | Description | | ---------------- | ------------------------ | ------------------------------------------------------ | | walletUser | — | Connected user { address }. null → connect state. | | Button | — | Your button component for the CTA. | | tokens | nonnux list | Token list to swap between. | | contracts | World Chain | Override any contract address (merged with defaults). | | rpcUrl | Alchemy public | JSON-RPC URL for balance reads. | | apiBasePath | /api/swap | Base path of your quote route (${base}/quote). | | explorerUrl | https://worldscan.org | Block explorer for the "view tx" link. | | ImageComponent | <img> | Pass next/image (or a wrapper) to optimise icons. | | storagePrefix | world_swap | localStorage key prefix (avoid cross-app collisions). | | title | Swap | Header title. |

createSwapQuoteHandler(config) options

tokens, contracts, rpcUrl, directV3Pairs, platformFeeBps, v3FeeTiers.


How it works

  • Quote (/api/swap/quote, server): given a token pair + amount, it reads Uniswap pools on World Chain via ethers and returns the best route (direct V2, V2 multi-hop through WLD, direct V3, or V3↔V2 cross-version), plus price impact and the min-received after fee.
  • Swap (client): builds a 2-step transaction (ERC-20 transfer to the swap contract, then the swap call) and submits it with MiniKit.commandsAsync.sendTransaction. The contract enforces minAmountOut.

No database, no API keys, no env vars required — the quote route only needs a public World Chain RPC.


Add this swap to your own mini app

Building a World App mini app and want a swap tab without writing one? Install @nonnux/world-swap, mount the quote route, and drop in <SwapCard /> — about two lines each (see Usage above). Bring your own token list or use the defaults.

Need a hand? Read the guide: https://paus.nonnux.com/world-swap.html


License

MIT © nonnux