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

sweep-external-sdk

v0.1.1

Published

Official TypeScript SDK for the Sweep External API: signed backend client, webhook verification and browser wallet execution helpers

Readme

sweep-external-sdk

TypeScript SDK for the Sweep External API: signed backend client, webhook verification and browser wallet execution helpers. Zero runtime dependencies.

npm install sweep-external-sdk

Access to the API requires partner registration — see Become an integrator for credentials (SWEEP_API_URL, SWEEP_PARTNER_ID, SWEEP_PARTNER_SECRET).

Entry points

| Import | Runs on | Contains | | --- | --- | --- | | sweep-external-sdk/server | Backend only | SweepExternalClient, buildCanonicalSignature, verifyWebhook — everything touching the partner secret | | sweep-external-sdk/browser | Browser | readWalletCapabilities, ensureChain, signAuthorization, executeChainAction, waitForReceipt over a raw EIP-1193 provider | | sweep-external-sdk/shared | Anywhere | API types, decimalToRawUnits, sumSettledTargetRaw, status constants |

The partner secret must never enter a browser or mobile bundle; only /server accepts it.

There is deliberately no root import — import ... from 'sweep-external-sdk' fails with ERR_PACKAGE_PATH_NOT_EXPORTED. Always pick the entry point for the environment the code runs in: the split exists so that secret-touching server code cannot end up in a browser bundle by accident.

TypeScript must use moduleResolution: "bundler", "node16" or "nodenext" — the legacy "node" (node10) mode cannot resolve subpath exports, so imports and their types will not be found.

The snippets below are sketches: provider (an EIP-1193 provider), address, quoteRequest, prepared (a PrepareResponse), CHAINS, rpc, store, persistAndReport and onAttemptEvent stand for objects your application supplies. For complete versions where every identifier is defined — a full one-file backend and the whole browser flow — see examples/.

Backend

import crypto from 'node:crypto'
import { SweepExternalClient } from 'sweep-external-sdk/server'

const client = new SweepExternalClient({
  sweepApiUrl: process.env.SWEEP_API_URL!,
  partnerId: process.env.SWEEP_PARTNER_ID!,
  secret: process.env.SWEEP_PARTNER_SECRET!,
})

// Verify credentials and signature implementation:
const ping = await client.ping()

// Quote (persist the idempotency key and body BEFORE transmission):
const key = `quote-${crypto.randomUUID()}`
const result = await client.quote(quoteRequest, key)

if (!result.reachable) {
  // Timeout or network failure — the outcome is UNKNOWN:
  // retry the SAME body with the SAME idempotency key.
} else if (!result.ok) {
  // Sweep answered with an error. result.response is a SweepErrorBody:
  // `error` is the stable failure family, `code` the stable detail,
  // `message` (when present) is safe to render.
  //   401/400 → fix the request or signing; do not blind-retry
  //   429     → back off per the RateLimit-* headers
  //   5xx     → retry the SAME body with the SAME key
  // Full code tables: https://docs.trysweep.finance/errors
} else {
  // Typed success body:
  const quote = result.response // QuoteResponse
}

prepare, submitted and status follow the same shape. Every result is a discriminated union. reachable: false means the outcome is unknown and the identical request must be retried with the same idempotency key — and so does reachable: true with an upstreamStatus of 5xx, which may or may not have been applied. A 4xx is the only definitive rejection: it is the common case in production and is handled per the tables at docs.trysweep.finance/errors, never by replaying the request. examples/backend.js implements exactly this rule in outcomeIsUnknown.

Each HTTP result also carries debug.signingString — the canonical string that was signed, for comparing against the envelope in the authentication docs when debugging 401s. It contains no secret, but it does expose your partner id, nonces and request paths — don't dump whole result objects into long-lived logs; log identifiers you chose deliberately.

Webhooks

import { verifyWebhook } from 'sweep-external-sdk/server'

app.post('/webhooks/sweep', express.raw({ type: '*/*' }), async (req, res) => {
  const result = verifyWebhook(
    { partnerId: process.env.SWEEP_PARTNER_ID!, secret: process.env.SWEEP_PARTNER_SECRET! },
    { rawBody: req.body, headers: req.headers },
  )
  if (!result.ok) return res.status(result.status).json({ error: result.error })
  const isNew = await store.recordEventOnce(result.payload.eventId, result.payload)
  if (isNew) await onAttemptEvent(result.payload)
  return res.status(200).end()
})

Browser

import {
  readWalletCapabilities,
  ensureChain,
  signAuthorization,
  executeChainAction,
  waitForReceipt,
} from 'sweep-external-sdk/browser'

const walletCapabilities = await readWalletCapabilities(provider, address)
// ... backend calls prepare with walletContext.walletCapabilities ...

const { signature } = await signAuthorization(provider, address, prepared.walletAuthorization)

for (const action of prepared.chainActions) {
  await ensureChain(provider, action.chainId, CHAINS)
  const evidence = await executeChainAction(provider, address, action, {
    waitForReceipt: (chainId, hash) => waitForReceipt(rpc, chainId, hash),
    onEvidence: (e) => persistAndReport(action.chainId, e), // report as soon as it exists
  })
}

Settled amounts

import { decimalToRawUnits, sumSettledTargetRaw } from 'sweep-external-sdk/shared'

// settledOutputs[].amount is a padded decimal string — never parseUnits() it directly.
const totalRaw = sumSettledTargetRaw(status.settledOutputs, {
  chainId: 42161,
  symbol: 'USDC',
  decimals: 6,
})

Auto-spend the total only when every included output has amountBasis: "actual"; resolve and confirm estimated amounts against the recipient's balance.

Documentation

Full API reference, request/response examples, error and retry semantics: docs.trysweep.finance.

Development

npm ci
npm test
npm run build

License

MIT