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

@nlofinance/widget

v1.0.2

Published

NLO partner widget — embed an iframe so your users can connect a wallet and deposit into the NLO Ultra-Safe strategy.

Readme

@nlofinance/widget

Embed the NLO deposit widget on your site so your users can connect a wallet and deposit into NLO's Ultra-Safe strategy — without ever leaving your domain. Wallet state, transaction signing, and balances run inside an iframe served by NLO, so they never touch your origin or your code.

📖 Full guide: nlo.finance/widget-docs


Quick start — 3 commands

# 1. Install the SDK
npm install @nlofinance/widget

# 2. Register your partner account (interactive wizard)
npx nlo-init

# 3. Mount the widget in your code
import NLOWidget from "@nlofinance/widget";
import config from "./.nlowidget.json";

NLOWidget.mount("#nlo-widget", {
  partner: config.slug,
  title: config.company_name,
});

That's the entire integration. A fully functional deposit widget renders in the target element.


What npx nlo-init does

The wizard ships with the SDK and runs in your terminal. It prompts for:

| Field | Validation | |---|---| | company_name | 2–64 characters — drives your generated slug | | website_url | Valid http(s):// URL — registered as your allowed origin | | payout_wallet | 0x + 40 hex chars — Ethereum address for commission payouts | | contact_email | Standard email — for payout notifications |

It then POSTs to https://nlo.finance/api/v2/widget/signup, returns your assigned partner slug, and saves it to ./.nlowidget.json in your project root:

{
  "slug": "your-company",
  "company_name": "Your Company",
  "website_url": "https://example.com",
  "payout_wallet": "0x0000000000000000000000000000000000000000",
  "contact_email": "[email protected]",
  "signed_up_at": "2026-01-15T10:00:00.000Z",
  "source": "self-service"
}

Commit .nlowidget.json to git. The slug is public — it ends up in your bundle anyway. Committing it means every developer and CI build uses the same slug without re-running the wizard.

Safe to re-run

  • Existing config — wizard exits with "Already configured".
  • Domain already registered — backend returns the existing slug; no duplicates created. Teammates on the same project share one slug.
  • Non-interactive context (CI / Docker / npm ci / piped stdin) — wizard skips silently. Run it once in a real terminal, commit the result, CI uses the committed config.

Framework integration

Drop one of these components into your project. Slug comes from .nlowidget.json so it's never hard-coded.

React / Next.js

import { useEffect, useRef } from "react";
import NLOWidget from "@nlofinance/widget";
import config from "../.nlowidget.json";

export default function NLODeposit() {
  const hostRef = useRef(null);

  useEffect(() => {
    const handle = NLOWidget.mount(hostRef.current, {
      partner: config.slug,
      title: config.company_name,
      onDepositComplete: (e) => {
        console.log("deposit done:", e.tx_hash);
        // Your post-deposit logic (award XP, mark quest complete, etc.)
      },
    });
    return () => handle.unmount();
  }, []);

  return <div ref={hostRef} style={{ width: 480, maxWidth: "100%" }} />;
}

Next.js app router: add "use client" at the top — the widget needs window and must run client-side.

Vue 3 / Nuxt

<script setup>
import { onBeforeUnmount, onMounted, ref } from "vue";
import NLOWidget from "@nlofinance/widget";
import config from "../../.nlowidget.json";

const hostEl = ref(null);
let handle = null;

onMounted(() => {
  handle = NLOWidget.mount(hostEl.value, {
    partner: config.slug,
    title: config.company_name,
    onDepositComplete: (e) => console.log("deposit done:", e.tx_hash),
  });
});

onBeforeUnmount(() => {
  if (handle) handle.unmount();
});
</script>

<template>
  <div ref="hostEl" style="width: 480px; max-width: 100%"></div>
</template>

Nuxt 3: wrap in <ClientOnly> so SSR doesn't try to render the widget.

Works in CRA, Vite, Next.js, Angular, Svelte, vanilla JS — same package, no framework-specific build required.


What the user sees

  1. Connect wallet → Reown AppKit modal opens with MetaMask, WalletConnect QR, Coinbase Wallet, etc.
  2. After connect, the iframe binds the wallet to your partner account (Tier 2 attribution) and shows live balances for every supported (token, chain) pair you have enabled.
  3. User picks an asset → types an amount → clicks Deposit.
  4. The iframe handles chain switch, ERC-20 approve, the deposit TX, and recording on NLO's backend. Your page receives event callbacks for every step.

API

NLOWidget.mount(target, options) → { unmount }

| Arg | Type | Required | |---|---|---| | target | string \| HTMLElement | yes — CSS selector or element | | options | MountOptions | yes |

MountOptions

| Field | Type | Default | Description | |---|---|---|---| | partner | string \| PartnerSignupInfo | — | Required. Either your slug (string), or a PartnerSignupInfo object — the SDK will sign up the partner on first mount and cache the assigned slug in localStorage. Most apps use the slug string read from .nlowidget.json. | | embedOrigin | string | "https://nlo.finance" | Override the iframe origin. Use for staging or local-backend testing. | | autoResize | boolean | true | Auto-size the iframe to its content. Set false for fixed-height iframes with internal scroll. Your onResize callback still fires either way. | | title | string | registered partner name | Optional display title shown above VIA NLO in the widget header. Display-only; does not affect attribution, routing, fees, or deposits. | | layout | "widget" \| "full" | "widget" | Embed layout. "widget" = compact deposit widget only (current default). "full" = wide two-column page with NLO explainer + trust content on the left and the deposit widget on the right. Attribution, wallet connect, events, and deposit flow are identical in both layouts. Full layout needs a wider container (~1200px × 720px recommended) and stacks to single-column on mobile. | | width | string | "100%" | Iframe width (any CSS value). | | height | string | "620" | Initial iframe height (CSS value or bare number → px). Auto-resize tunes it after first render. | | onReady | (e: ReadyEvent) => void | — | Fires once the iframe has loaded /widget/config and is ready for input. | | onWalletConnect | (e: WalletConnectEvent) => void | — | Fires after the user connects a wallet. | | onWalletDisconnect | () => void | — | Fires on disconnect. | | onAssetSelect | (e: AssetSelectEvent) => void | — | Fires when the user picks a chip on the asset/chain picker. | | onDepositSubmitted | (e: DepositSubmittedEvent) => void | — | Fires after the deposit quote returns, before the user signs. | | onDepositComplete | (e: DepositCompleteEvent) => void | — | Fires after the deposit is fully recorded on NLO's backend. | | onDepositFailed | (e: DepositFailedEvent) => void | — | Fires on any failure in the deposit pipeline. | | onResize | (height_px: number) => void | — | Fires when the iframe's content height changes. Optional — the SDK already auto-resizes unless you opt out via autoResize: false. |

Returns: { unmount: () => void } — call to remove the iframe and detach the message listener.

Event payload types

type ReadyEvent = {
  partner: string;                  // your partner slug
  supported_chains: string[];       // ["bsc", "arbitrum", ...]
};

type WalletConnectEvent = {
  wallet: string;                   // 0x… lowercased
};

type AssetSelectEvent = {
  chain: string;                    // e.g. "bsc"
  token_symbol: string;             // e.g. "USDT"
};

type DepositSubmittedEvent = {
  chain: string;
  token_symbol: string;
  amount_display: string;           // user-typed (e.g. "100")
  amount_raw: string;               // uint256 in token decimals
  wallet: string;
};

type DepositCompleteEvent = {
  chain: string;
  token_symbol: string;
  amount_display: string;
  amount_raw: string;
  tx_hash: string;                  // the on-chain deposit TX
  deposit_uuid: string | null;      // NLO-assigned id
  wallet: string;
};

type DepositFailedEvent = {
  step: string;                     // "chain_switch" | "quote" | "allowance"
                                    // | "approve" | "deposit" | "record" | "unknown"
  message: string;                  // human-readable, often the wallet's error
  chain?: string;
  wallet?: string;
};

TypeScript types are bundled — your editor will autocomplete every option and payload field with no extra @types package needed.


Security

  • Iframe isolation. All wallet interaction lives in the iframe under the nlo.finance origin. Reown AppKit, ethers v6, calldata building, and the network calls all execute there — your page never touches a wallet provider.
  • Origin-pinned messages. postMessage events are origin-pinned to nlo.finance (or your custom embedOrigin). Messages from any other origin are dropped.
  • Allow-list enforcement. Your partner's allowed_origins list (set automatically from website_url during npx nlo-init) is enforced server-side via Content-Security-Policy: frame-ancestors ... — the widget cannot be embedded on unauthorised pages.
  • Server-rendered credentials. The iframe runs Reown AppKit with the project ID served from the backend, not hardcoded in static JS — credentials can be rotated without redeploying assets.

Versioning

Follows Semantic Versioning. Breaking changes never ship inside a major version — pin ^1.0.0 to follow non-breaking updates.


License

Apache-2.0