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

@decentrys/ui-sdk

v0.1.2

Published

Drop-in React components for rendering Decentrys risk assessments, built so a new project can never be shown as dangerous for being new.

Readme

@decentrys/ui-sdk

Drop-in React components that render a Decentrys assessment — built so a new project can never be shown as dangerous for being new.

Install

npm install @decentrys/ui-sdk @decentrys/protect

React 18 or 19, as a peer dependency alongside react-dom. Never bundled — two copies of React in one app is a real breakage. No styling dependency, no font fetch, no network calls of its own.

Quick start

import { useEffect, useState } from 'react';
import { Decentrys, type ProtectResult, type TransactionRequest } from '@decentrys/protect';
import { DecentrysUiProvider, TransactionRiskBanner, RiskDetailsModal } from '@decentrys/ui-sdk';

const decentrys = new Decentrys({ apiKey: 'dk_pub_live_...' });

export function SigningScreen({ tx, onSign, onCancel }: {
  tx: TransactionRequest;
  onSign: () => void;
  onCancel: () => void;
}) {
  const [result, setResult] = useState<ProtectResult | null>(null);
  const [detailsOpen, setDetailsOpen] = useState(false);

  useEffect(() => {
    let live = true;
    decentrys.assessTransaction(tx).then((r) => { if (live) setResult(r); });
    return () => { live = false; };
  }, [tx]);

  if (!result) return null;

  return (
    <DecentrysUiProvider theme={{ surface: '#0b0d10', text: '#e8ebef', radius: '12px' }}>
      <TransactionRiskBanner
        result={result}
        onViewDetails={() => setDetailsOpen(true)}
        actions={
          <>
            {/* Your buttons, your policy. This package never disables them. */}
            <button onClick={onSign}>Confirm</button>
            <button onClick={onCancel}>Cancel</button>
          </>
        }
      />
      <RiskDetailsModal result={result} open={detailsOpen} onClose={() => setDetailsOpen(false)} />
    </DecentrysUiProvider>
  );
}

DecentrysUiProvider sets theme and copy once for everything beneath it and emits the stylesheet a single time. Without a provider every component emits its own — so a single <AddressRiskBadge> dropped into a page still renders correctly.

Placing the CSS yourself instead — in a <head>, a bundled stylesheet or a shadow root — is <DecentrysUiProvider injectStyles={false}>, or export the string directly:

import { DECENTRYS_UI_CSS } from '@decentrys/ui-sdk';
<style>{DECENTRYS_UI_CSS}</style>

Components

Note which prop each one takes — some want the whole ProtectResult, some want a piece of it.

| Component | Required props | Use it when | |---|---|---| | TransactionRiskBanner | result | A user is about to sign. The main one. | | ApprovalWarning | result, approval | A token approval — leads with what is being granted, not a score. | | ContractFacts | assessment | Showing what a contract can do (upgrade, mint, pause). | | TokenSecurityPanel | result | A token detail screen. | | ThreatSignalList | signals | You want signals only, in your own layout. | | AddressRiskBadge | assessment or level | Compact inline badge beside an address. | | RiskDetailsModal | result, open, onClose | "Why?" — every fact, signal, evidence item and score component. |

// An approval. `approval` describes what is being granted; the SDK does not
// infer it from the assessment.
<ApprovalWarning
  result={approvalResult}          // from decentrys.screenApproval(...)
  approval={{
    token: '0xa0b8…',
    symbol: 'USDC',
    decimals: 6,
    spender: '0x1111…',
    spenderLabel: '1inch Router',
    amount: 'unlimited',           // base units, or the literal 'unlimited'
  }}
/>
// "This grants 1inch Router permission to spend an unlimited amount of your USDC,
//  now and at any time in the future, until it is revoked."
//
// Omit `amount` and it says the allowance could not be decoded — never that it
// is small. Omit `decimals` and the figure is labelled as base units rather
// than silently shown 10^18 times too small.

<ContractFacts assessment={result.assessment} demotedSignals={result.demotedSignals} />

<TokenSecurityPanel result={result} tokenSymbol="USDC" showComponents />

<ThreatSignalList signals={result.assessment.threatSignals} />

<AddressRiskBadge assessment={result.assessment} address="0x1111…" />
<AddressRiskBadge level="CAUTION" />   {/* when you only have the level */}

Every component also accepts className, style, theme, copy and levelLabels. AddressRiskBadge takes exactly one of assessment or level, enforced by the type rather than a runtime throw — a component that throws inside a wallet's render tree takes that wallet's screen down.

What these will not do

Nothing blocks. DecisionPresentation.blocksUi is typed as the literal false, including for a block policy action. No control here is ever rendered disabled — the decision belongs to your application, and you wire your own buttons through actions.

LIMITED history is never a warning. HistoryPresentation types tone as the literal 'neutral' and isWarning as the literal false, so rendering it as an alert doesn't compile. It's the correct, expected state for anything recently deployed.

Facts never look like threat signals. fact, capability and unknown are separate tone families from the risk tones, each row carries its kind as a word and its own non-colour glyph, and a stale or low-confidence signal that did not raise the level is toned inactive. Colour is the third carrier of meaning, not the first — a colour-blind user still has to be able to tell "deployed three days ago" from "attributed to a drainer family".

Anything above zero hops says so in a sentence, not just a badge. A hop is an inference about a counterparty, and a badge reading "2" tells nobody that.

Theming

31 CSS custom properties. Pass them by their bare token name — the --dcy- prefix is added for you:

<TransactionRiskBanner
  result={result}
  theme={{ surface: '#1a1a2e', radius: '12px', 'tone-caution': '#ab9ff2' }}
  className="my-wallet-card"
/>

The tokens (THEME_TOKENS is exported, and DecentrysTheme is Partial<Record<ThemeToken, string>>):

  • Layout and type — font, font-mono, radius, gap
  • Surfaces and text — surface, surface-raised, border, text, text-muted, text-faint, focus
  • A foreground and a -bg wash for each of ten tones — tone-neutral, tone-info, tone-caution, tone-elevated, tone-high, tone-critical, tone-fact, tone-capability, tone-unknown, tone-inactive

Inline theme is applied on the component's own root, so it beats both the defaults and the prefers-color-scheme dark block — a fixed brand palette doesn't flip on a user's OS setting. Props win over the provider, so one banner can be re-themed inside an otherwise uniform tree.

Every meaningful element also carries a data-dcy-* attribute (data-dcy-level, data-dcy-kind, data-dcy-tone) if you'd rather style from your own CSS.

Copy and translation

Every string is overridable, on the provider or per component:

<DecentrysUiProvider copy={{ /* Partial<UiCopy> */ }}>
<TransactionRiskBanner result={result} levelLabels={{ CAUTION: 'Attention' }} />

DEFAULT_COPY and resolveCopy are exported.

Building your own presentation

The presentation logic is pure, React-free and separately exported, so a renderer you write yourself cannot drift from the one here:

import {
  levelPresentation, factPresentation, capabilityPresentation, signalPresentation,
  historyPresentation, unknownPresentation, approvalPresentation, assessmentSections,
  componentRows, decisionPresentation, evidencePresentation, availabilityPresentation,
  hopPresentation, formatConfidence, formatTokenAmount, shortenAddress,
  MIN_RAISING_CONFIDENCE, RISK_LEVEL_LABEL,
} from '@decentrys/ui-sdk';

MIN_RAISING_CONFIDENCE is re-exported from @decentrys/protect rather than copied, so a renderer cannot put a signal in the "did not raise the level" list while the classifier was in fact raising it.

React Native

These render React DOM and won't work in RN. The presentation logic above is React-free and reusable as-is.

The rest of the SDK

| Package | For | |---|---| | @decentrys/protect | Pre-sign risk assessment for wallets and dapps | | @decentrys/ui-sdk | React components that render Protect results | | @decentrys/sentinel-sdk | Monitoring deployed contracts and treasuries | | @decentrys/risk-sdk | Screening for exchanges and custodians | | @decentrys/dri-sdk | Fund tracing and recovery intelligence | | @decentrys/agent | Policy enforcement for autonomous agents |

Licence

MIT © Decentrys Labs

decentrys.com · SDK overview · Developer API · Source