Catalog npm
PACKAGE EXPLORERView in registry

@0takuc0mrade/swiftrail-sdk

npm

SwiftRail gasless checkout SDK for Arbitrum

arbitrumcheckoutgaslesssdkusdc
Versions collected2
Direct dependencies0From release 0.1.1
Last observed20 Oct, 22:15 UTC

README

Current package documentation

SDK Integration Guide

This guide shows how to integrate the checkout SDK into your own app (React, Vite, Next.js).

Published npm package:

  1. @0takuc0mrade/swiftrail-sdk
  2. https://www.npmjs.com/package/@0takuc0mrade/swiftrail-sdk

Install from npm

npm i @0takuc0mrade/swiftrail-sdk

What the SDK handles

  1. Wallet connect (connect_wallet)
  2. Arbitrum Sepolia network guard/switch (421614)
  3. USDC permit signing (eth_signTypedData_v4)
  4. Relayer submission (POST /submit-payment)

Prerequisites

  1. Running relayer (production URL, or local dev URL such as http://127.0.0.1:3000)
  2. Deployed payment contract address
  3. Correct USDC token address for your chain
  4. Browser wallet provider (window.ethereum, MetaMask)

Build the SDK package

From repo root:

wasm-pack build sdk --target web --out-dir ./frontend/pkg

For another app/repo, set --out-dir to a folder inside that app and import from that path.

Shared integration pattern

import init, { ArbitrumCheckout } from "@0takuc0mrade/swiftrail-sdk";

await init();

const sdk = new ArbitrumCheckout(
  "https://your-relayer.example.com", // relayer URL
  "0xYourPaymentContractAddress",   // payment contract
  "0xYourUsdcAddress"               // USDC token
);

const user = await sdk.connect_wallet();

const merchant = "0xMerchantAddress";
const amount = "20000000"; // 20 USDC in base units (6 decimals)
const resultJson = await sdk.checkout(user, merchant, amount);
const result = JSON.parse(resultJson);

React example

import { useEffect, useState } from "react";
import init, { ArbitrumCheckout } from "@0takuc0mrade/swiftrail-sdk";

export default function CheckoutWidget() {
  const [sdk, setSdk] = useState(null);
  const [user, setUser] = useState("");
  const [status, setStatus] = useState("");

  useEffect(() => {
    let mounted = true;
    (async () => {
      await init();
      if (!mounted) return;
      setSdk(
        new ArbitrumCheckout(
          "https://your-relayer.example.com",
          "0xYourPaymentContractAddress",
          "0xYourUsdcAddress"
        )
      );
    })().catch((e) => setStatus(String(e)));

    return () => {
      mounted = false;
    };
  }, []);

  async function connect() {
    if (!sdk) return;
    try {
      const addr = await sdk.connect_wallet();
      setUser(String(addr));
      setStatus(`Connected: ${String(addr)}`);
    } catch (e) {
      setStatus(`Connect failed: ${String(e)}`);
    }
  }

  async function pay() {
    if (!sdk || !user) return;
    try {
      const res = await sdk.checkout(user, "0xMerchantAddress", "20000000");
      const parsed = JSON.parse(String(res));
      setStatus(`Payment tx: ${parsed.payment_tx_hash}`);
    } catch (e) {
      setStatus(`Payment failed: ${String(e)}`);
    }
  }

  return (
    <div>
      <button onClick={connect}>Connect</button>
      <button onClick={pay}>Pay</button>
      <pre>{status}</pre>
    </div>
  );
}

Vite example

Use the same React example above. For plain Vite JS:

import init, { ArbitrumCheckout } from "@0takuc0mrade/swiftrail-sdk";

const status = document.querySelector("#status");
const connectBtn = document.querySelector("#connect");
const payBtn = document.querySelector("#pay");

await init();
const sdk = new ArbitrumCheckout(
  "https://your-relayer.example.com",
  "0xYourPaymentContractAddress",
  "0xYourUsdcAddress"
);

let user = "";

connectBtn.onclick = async () => {
  try {
    user = String(await sdk.connect_wallet());
    status.textContent = `Connected: ${user}`;
  } catch (e) {
    status.textContent = `Connect failed: ${String(e)}`;
  }
};

payBtn.onclick = async () => {
  try {
    const res = await sdk.checkout(user, "0xMerchantAddress", "20000000");
    const parsed = JSON.parse(String(res));
    status.textContent = `Payment tx: ${parsed.payment_tx_hash}`;
  } catch (e) {
    status.textContent = `Payment failed: ${String(e)}`;
  }
};

Next.js example (App Router)

Create a client component (important):

"use client";

import { useEffect, useState } from "react";
import init, { ArbitrumCheckout } from "@0takuc0mrade/swiftrail-sdk";

export default function CheckoutClient() {
  const [sdk, setSdk] = useState<ArbitrumCheckout | null>(null);
  const [user, setUser] = useState("");
  const [status, setStatus] = useState("");

  useEffect(() => {
    (async () => {
      await init();
      setSdk(
        new ArbitrumCheckout(
          "https://your-relayer.example.com",
          "0xYourPaymentContractAddress",
          "0xYourUsdcAddress"
        )
      );
    })().catch((e) => setStatus(String(e)));
  }, []);

  async function connect() {
    if (!sdk) return;
    try {
      setUser(String(await sdk.connect_wallet()));
    } catch (e) {
      setStatus(String(e));
    }
  }

  async function pay() {
    if (!sdk || !user) return;
    try {
      const raw = await sdk.checkout(user, "0xMerchantAddress", "20000000");
      const parsed = JSON.parse(String(raw));
      setStatus(`Payment tx: ${parsed.payment_tx_hash}`);
    } catch (e) {
      setStatus(`Payment failed: ${String(e)}`);
    }
  }

  return (
    <div>
      <button onClick={connect}>Connect</button>
      <button onClick={pay}>Pay</button>
      <p>{status}</p>
    </div>
  );
}

Common mistakes

  1. Passing human-readable amount ("20") instead of base units ("20000000").
  2. Wrong USDC address for current chain.
  3. Calling SDK on server side (no window.ethereum).
  4. Not running relayer, or using wrong relayer URL.
  5. Not parsing SDK checkout response with JSON.parse.

Response fields

On success:

  1. payment_tx_hash
  2. settlement_tx_hash
  3. gross_amount
  4. fee_amount
  5. net_amount
  6. fee_bps
  7. fee_model_notes

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 2

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.1Registry latest17 Feb 20260
0.1.017 Feb 20260

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 22:15 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:c6194156558ead21026eb92e4edf2997eadf6424000ec02f1b1f7bacbc49e273