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

@swype-org/checkout

v0.2.7

Published

Lightweight merchant checkout SDK — open a hosted payment flow, handle completion, zero dependencies

Readme

@swype-org/checkout

Lightweight merchant checkout SDK — open a hosted Swype payment flow, handle completion, zero runtime dependencies.

Quick Start

npm install @swype-org/checkout
import { Checkout } from '@swype-org/checkout';

const checkout = new Checkout({ signer: '/api/sign-payment' });

document.getElementById('deposit-btn')!.addEventListener('click', async () => {
  try {
    const { transfer } = await checkout.requestDeposit({
      amount: 50,
      chainId: 8453,
      address: '0x...', // destination wallet
      token: 'USDC',
    });
    console.log('Transfer complete:', transfer.id, transfer.status);
  } catch (error) {
    console.error('Deposit failed:', error);
  }
});

Important: requestDeposit() must be called from a user-gesture handler (click, keypress, etc.) so the browser allows the popup to open.

React Hook

A dedicated React entry point eliminates all boilerplate:

npm install @swype-org/checkout react
import { useSwypeCheckout } from '@swype-org/checkout/react';

function DepositButton() {
  const { status, result, error, displayMessage, requestDeposit } = useSwypeCheckout({
    signer: '/api/sign-payment',
  });

  return (
    <>
      <button
        onClick={() =>
          requestDeposit({ amount: 50, chainId: 8453, address: '0x...', token: 'USDC' })
        }
        disabled={status === 'signer-loading'}
      >
        {status === 'signer-loading' ? 'Preparing…' : 'Deposit'}
      </button>
      {error && <p>{displayMessage}</p>}
      {result && <p>Transfer {result.transfer.id} complete!</p>}
    </>
  );
}

The hook returns reactive status, result, error, displayMessage, and isActive values, plus requestDeposit, focus, and close actions. It manages the Checkout lifecycle and cleans up on unmount.

How It Works

Merchant App / SDK              Merchant Signer                Hosted Flow (popup)
     │                               │                               │
     │  1. requestDeposit(request)    │                               │
     │──────────────────────────────► │                               │
     │                                │  2. signer(data) or POST URL  │
     │                                │  (includes webviewBaseUrl)    │
     │  3. { signature, payload, ...} │                               │
     │◄───────────────────────────────│                               │
     │                                                                │
     │  4. SDK builds URL, opens popup                                │
     │───────────────────────────────────────────────────────────────► │
     │                                                                │
     │  5. User completes payment in hosted flow                      │
     │                                                                │
     │  6. postMessage: swype:transfer-complete                       │
     │◄──────────────────────────────────────────────────────────────  │
     │                                                                │
     │  7. Promise resolves with DepositResult                        │

Signer Contract

The signer config option controls how the SDK obtains a signed payment link. It accepts either a URL string or a custom function, giving you full control over authentication, HTTP method, and request shape.

Using a URL string (simple)

When signer is a string, the SDK sends a POST with a JSON body to that URL and expects a SignerResponse back. This is the simplest integration:

const checkout = new Checkout({ signer: '/api/sign-payment' });

Using a custom function (full control)

When signer is a function, the SDK calls it with a SignerRequest object and expects a Promise<SignerResponse>. Use this when you need control over the HTTP method, authentication, request transformation, or any other aspect of the signing call:

import type { SignerFunction } from '@swype-org/checkout';

const checkout = new Checkout({
  signer: async (data) => {
    const res = await fetch('/api/sign-payment', {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${getToken()}`,
      },
      body: JSON.stringify({ ...data, orderId: 'order-123' }),
    });
    if (!res.ok) throw new Error(`Signer error: ${res.status}`);
    return res.json();
  },
});

SignerRequest (input)

The data the SDK passes to your signer (as the JSON body for URL mode, or as the function argument for function mode):

| Field | Type | Description | | --- | --- | --- | | amount | number | USD amount to deposit (always > 0). | | chainId | number | EVM chain ID for the destination (e.g. 8453 for Base). | | address | string | Destination wallet address (0x-prefixed, 40 hex chars). | | token | string | Token symbol on the destination chain (e.g. "USDC"). | | callbackScheme | string \| null | Custom URL scheme for mobile deep-link callbacks. Always null for web. | | url | string | Base webview URL the SDK will navigate to. Provided for logging/validation — your signer does not construct the final URL. | | version | string | Protocol version (currently "v1"). | | reference | string? | Merchant order or invoice ID for reconciliation. | | metadata | object? | Arbitrary key-value pairs forwarded from the merchant app. |

Example:

{
  "amount": 50,
  "chainId": 8453,
  "address": "0x...",
  "token": "USDC",
  "callbackScheme": null,
  "url": "https://webview-app-staging.staging-swype.network",
  "version": "v1",
  "reference": "order-123",
  "metadata": { "invoiceId": "INV-456" }
}

What the signer must do

  1. Validate the request fields.
  2. Generate an idempotency key (UUID) for this payment.
  3. Build a payload — a base64url-encoded JSON string containing the payment parameters:
{
  "amount": 50,
  "chainId": 8453,
  "address": "0x...",
  "token": "USDC",
  "idempotencyKey": "generated-uuid",
  "callbackScheme": null,
  "expiresAt": "2026-03-07T12:00:00Z",
  "version": "v1"
}
  1. Sign the payload string with your merchant private key (SHA-256) and base64url-encode the signature.

SignerResponse (output)

The response your signer must return (as JSON for URL mode, or as the resolved value for function mode):

| Field | Type | Description | | --- | --- | --- | | merchantId | string | Your merchant UUID. | | payload | string | Base64url-encoded payment payload (see above). | | signature | string | Base64url-encoded signature of the payload string. | | expiresAt | string | ISO 8601 expiration timestamp for this payment link. | | preview | object | Echo of the payment parameters for client-side display. | | preview.amount | number | Deposit amount. | | preview.chainId | number | Destination chain ID. | | preview.address | string | Destination wallet address. | | preview.token | string | Destination token symbol. | | preview.idempotencyKey | string | The generated idempotency key. |

Example:

{
  "merchantId": "uuid",
  "payload": "base64url-encoded-payload",
  "signature": "base64url-encoded-signature",
  "expiresAt": "2026-03-07T12:00:00Z",
  "preview": {
    "amount": 50,
    "chainId": 8453,
    "address": "0x...",
    "token": "USDC",
    "idempotencyKey": "uuid"
  }
}

The SDK constructs the hosted flow URL by appending merchantId, payload, and signature as query parameters to the webviewBaseUrl, then navigates the popup to that URL. When the user completes payment the hosted flow sends a postMessage back and the SDK resolves the promise.

Configuration

const checkout = new Checkout({
  // Required: URL string or custom async function (see "Signer Contract")
  signer: '/api/sign-payment',

  // Optional: base URL of the hosted payment webview app.
  // Default: 'https://webview-app-staging.staging-swype.network'
  webviewBaseUrl: 'https://webview-app-staging.staging-swype.network',

  // Optional: origin of the hosted flow page (for postMessage validation).
  // Derived from webviewBaseUrl when omitted.
  hostedFlowOrigin: 'https://webview-app-staging.staging-swype.network',

  // Optional: window.open feature string
  popupFeatures: 'popup=yes,width=460,height=860',

  // Optional: window name for the popup
  popupWindowName: 'checkout-hosted-flow',

  // Optional: max ms to wait for signer response (default: 15000)
  signerTimeoutMs: 15_000,

  // Optional: max ms for entire flow (signer + user completion)
  flowTimeoutMs: 300_000,

  // Optional: enable debug logging to console
  debug: false,
});

Observable Status

The Checkout instance exposes a reactive status property:

| Status | Meaning | | ---------------- | ------------------------------------------- | | idle | No active flow | | signer-loading | Calling the merchant signer endpoint | | popup-active | Hosted flow is open, waiting for user | | completed | Transfer succeeded | | error | Something failed |

checkout.on('status-change', (status) => {
  console.log('Status:', status);
});

// Also available synchronously:
checkout.status;   // current status
checkout.result;   // last DepositResult (when completed)
checkout.error;    // last CheckoutError (when error)
checkout.isActive; // true during signer-loading or popup-active

Error Handling

Every error is a CheckoutError with a machine-readable code:

| Code | Meaning | | ------------------------ | ----------------------------------------------- | | POPUP_BLOCKED | Browser blocked the popup window | | POPUP_CLOSED | User closed the popup before completing | | SIGNER_REQUEST_FAILED | Signer returned a non-2xx response | | SIGNER_NETWORK_ERROR | Network failure reaching the signer | | SIGNER_RESPONSE_INVALID| Signer response missing required fields | | SIGNER_TIMEOUT | Signer did not respond within signerTimeoutMs | | FLOW_TIMEOUT | Entire flow exceeded flowTimeoutMs | | INVALID_REQUEST | Bad input (amount, address, etc.) |

Use getDisplayMessage() for user-facing strings:

import { CheckoutError, getDisplayMessage } from '@swype-org/checkout';

try {
  await checkout.requestDeposit({ ... });
} catch (err) {
  if (err instanceof CheckoutError) {
    showToast(getDisplayMessage(err));
  }
}

Events

checkout.on('complete', (result) => { /* DepositResult */ });
checkout.on('error', (error) => { /* CheckoutError */ });
checkout.on('close', () => { /* popup closed */ });
checkout.on('status-change', (status) => { /* CheckoutStatus */ });

Lifecycle

// Focus the popup (e.g. when user clicks "Deposit" while flow is active)
checkout.focus();

// Close the popup without waiting for completion
checkout.close();

// Tear down and release all resources (call on unmount)
checkout.destroy();

Metadata / Order Reference

Pass merchant-specific data through the flow for reconciliation:

await checkout.requestDeposit({
  amount: 50,
  chainId: 8453,
  address: '0x...',
  token: 'USDC',
  reference: 'order-123',
  metadata: { invoiceId: 'INV-456' },
});

The reference and metadata are forwarded to your signer endpoint so you can correlate the payment with your internal records.

TypeScript

All types are exported:

import type {
  CheckoutConfig,
  CheckoutStatus,
  DepositRequest,
  DepositResult,
  SignerFunction,
  SignerRequest,
  SignerResponse,
  TransferSummary,
} from '@swype-org/checkout';

import type { CheckoutErrorCode } from '@swype-org/checkout';