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

@synfin/widget

v0.1.3

Published

The Synfin widget: an embeddable, framework-agnostic quote-and-fee widget (a <synfin-widget> custom element, plus a React wrapper) built on @synfin/client. Live best-execution quotes across Canton venues with the partner's disclosed fees. Non-custodial: i

Readme

@synfin/widget

An embeddable quote-and-fee widget for Canton, built on @synfin/client. Drop it into any site to show a live best-execution quote across venues with your disclosed fees. Non-custodial: it holds no keys and signs nothing.

  • Docs: https://synfin.xyz/docs/sdk
  • Status: v0, the surface may evolve with design partners. Pin a version.

What the widget shows today: a live quote across the Canton venues with your disclosed fees (the 15 bps Synfin service fee + your integrator split). Tradecraft is the executable venue today. The fees are DISCLOSED for display; on-ledger fee collection is flag-gated off today (FEE_COLLECTION_ENABLED = false) and is wallet-dependent when it flips (see @synfin/client). The widget holds no keys and signs nothing — execution is your wallet's, via @synfin/client.

Install

Two paths, pick one. Both register the same <synfin-widget> custom element.

1. Script tag (no build step, no bundler)

For any site (plain HTML, Vue, Svelte, Angular, Rails, WordPress). One <script> loads a self-contained bundle (@synfin/client is inlined, so there is no import map and nothing else to fetch) and registers the element:

<script src="https://unpkg.com/@synfin/widget"></script>
<synfin-widget
  api-key="sk_live_..."
  fee-bps="30"
  fee-recipient="you::1220..."
  from="CC" to="USDCx" amount="100"
></synfin-widget>

Pin a version in production (the CDN caches it and the API stays stable):

<script src="https://unpkg.com/@synfin/[email protected]"></script>
<!-- or jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/@synfin/[email protected]"></script>

The bare unpkg.com/@synfin/widget URL resolves to the IIFE bundle (dist/synfin-widget.global.js) through the package unpkg/jsdelivr fields, so you never spell the path. The bundle is browser-only and minified.

2. npm (with a bundler: Vite, Next.js, Webpack)

npm install @synfin/widget
import '@synfin/widget'; // registers <synfin-widget>

@synfin/client comes in as a normal dependency (the real range ^0.1.0, not a workspace reference), so the package installs cleanly outside this repo.

React:

import { SynfinWidget } from '@synfin/widget/react';

<SynfinWidget apiKey="sk_live_..." feeBps={30} feeRecipient="you::1220..."
  onQuote={(e) => console.log(e.detail)} />

What it does (v1)

A live quote across Canton venues for your pair and amount, ranked best net receive first. We recommend the best, and mark it, but the user can select any available venue (a radio group: click, tap, or arrow keys); the receive figure, the fee breakdown, and the plan all follow their choice. The widget is shown to your END USER, so by default it shows only what they care about: what they pay, what they receive (net of all fees, read verbatim from the live quote and never recomputed in the browser), and a single neutral fee line for the total taken. The fee attribution (the Synfin service fee, your integrator fee, and the partner / Synfin split) is partner information, hidden from the end user by default; set show-fee-breakdown to reveal it for your own integration testing. Every state is designed: loading skeletons, an auto-refresh countdown, a venue shown honestly as unavailable (never breaking the widget), no-route, and errors.

Creating a plan emits synfin:plan for your app to execute through the WalletAdapter it owns. In-widget wallet execution is deferred until a standard Canton browser wallet adapter exists (see docs/WIDGET.md); the widget never holds keys.

Configuration

| attribute / prop | meaning | | --- | --- | | api-key / apiKey | your partner key (unlocks the fee breakdown) | | fee-bps / feeBps | your integrator fee, 0 to the cap (needs a recipient) | | fee-recipient / feeRecipient | the Canton party your fee settles to | | from to amount | default pair and amount | | appearance | dark (default) or light | | base-url / baseUrl | API origin (default https://synfin.xyz) | | show-fee-breakdown / showFeeBreakdown | show the full partner fee attribution (off by default; end users see the net and one neutral fee line) | | show-attribution / showAttribution | the subtle "Powered by Synfin" footer link (on by default; set off to white-label) |

On the API key: in a browser widget the key is client-side visible by nature. Synfin keys are free, rate-limited, and non-custodial: a leaked key can only fetch quotes at that key's rate limit, and is revocable in one click. Use a dedicated widget key. A per-key origin allowlist is a roadmap item.

Theming

Override any of these CSS custom properties (they pierce the Shadow DOM) to match your site; the Synfin cream/ember dark system is the default, appearance="light" a warm off-white:

synfin-widget {
  --synfin-accent: #6c5cff;
  --synfin-bg: #0c0c14;
  --synfin-surface: #17172a;
  --synfin-ink: #eef;
  --synfin-radius: 20px;
  --synfin-font: 'Inter', sans-serif;
}

Events

DOM CustomEvents on the element (and on* props in the React wrapper):

  • synfin:quote - a fresh QuoteResponse loaded
  • synfin:venue - the user selected a venue ({ venueId, net, isBest, pair })
  • synfin:plan - an ExecutionPlan created (execute it from your wallet)
  • synfin:asset - the pair changed
  • synfin:error - a SynfinApiError surfaced

Demo

  • example/index.html: the full embed against live production (https://synfin.xyz) by default, with a control panel, the event log, and theming. Add your API key to unlock the fee breakdown; keyless shows the venue net only.
  • example/cdn.html: the script-tag path in isolation. It loads the self-contained bundle with a plain <script src> (no import map), proving the CDN embed a partner uses.

The widget reads the public API cross-origin, so the API sends permissive CORS headers on /api/*; see the /api/* CORS middleware.

License

MIT. Copyright Cayvox Labs.