New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

stream402-sdk

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

stream402-sdk

Stream402 SDK - Integrate x402 payment protocol into your applications

latest
npmnpm
Version
0.1.0
Version published
Maintainers
1
Created
Source

Stream402 SDK

A TypeScript SDK for integrating Stream402 payment protocol into your applications. Stream402 enables monetization of digital content using Solana payments via the x402 protocol.

Installation

npm install @stream402/sdk

Quick Start

1. Discover an Asset

Check if an asset requires payment:

import { discover } from "@stream402/sdk";

const result = await discover("https://example.com/api/asset/123");

if (result.type === "free") {
  // Asset is free, use the URL directly
  console.log("Free asset:", result.url);
} else {
  // Payment required
  console.log("Payment required:", result.challenge);
  console.log("Amount:", result.challenge.amount, result.challenge.currency);
}

2. Pay and Fetch

Complete payment flow and get access to the resource:

import { payAndFetch } from "@stream402/sdk";
import { useWallet } from "@solana/wallet-adapter-react";

function MyComponent() {
  const wallet = useWallet();

  const handlePayAndFetch = async () => {
    try {
      const result = await payAndFetch(
        "https://example.com/api/asset/123",
        wallet
      );

      console.log("Download URL:", result.downloadUrl);
      console.log("Expires at:", new Date(result.expiresAt));

      // Use the download URL to access the resource
      window.open(result.downloadUrl, "_blank");
    } catch (error) {
      console.error("Payment failed:", error);
    }
  };

  return <button onClick={handlePayAndFetch}>Pay & Download</button>;
}

3. Upload Asset

Upload an asset as a content provider:

import { uploadAsset } from "@stream402/sdk";
import { useWallet } from "@solana/wallet-adapter-react";

function UploadComponent() {
  const wallet = useWallet();

  const handleUpload = async (file: File) => {
    try {
      const result = await uploadAsset(
        file,
        {
          title: "My Image",
          price: 0.01, // USDC
          tags: ["nature", "landscape"],
          description: "A beautiful landscape image",
        },
        wallet
      );

      console.log("Asset uploaded:", result.assetId);
      console.log("Asset URL:", result.url);
    } catch (error) {
      console.error("Upload failed:", error);
    }
  };

  return (
    <input
      type="file"
      onChange={(e) => {
        const file = e.target.files?.[0];
        if (file) handleUpload(file);
      }}
    />
  );
}

API Reference

discover(assetUrl: string): Promise<DiscoverResult>

Fetches an asset URL and returns either free access or a payment challenge.

Parameters:

  • assetUrl - Full URL to the asset (e.g., "https://example.com/api/asset/123")

Returns:

  • { type: "free", url: string } - Asset is free to access
  • { type: "payment_required", challenge: PaymentChallenge } - Payment required

Example:

const result = await discover("https://example.com/api/asset/123");

payAndFetch(assetUrl: string, walletAdapter: WalletAdapter, connection?: Connection): Promise<PaymentResult>

Completes the full payment flow and returns the resource.

Parameters:

  • assetUrl - Full URL to the asset
  • walletAdapter - Solana wallet adapter from @solana/wallet-adapter-react
  • connection - Optional Solana connection (defaults to devnet/mainnet based on challenge)

Returns:

  • { accessToken: string, downloadUrl: string, expiresAt: number }

Example:

const result = await payAndFetch(assetUrl, wallet);
// Use result.downloadUrl to access the resource

uploadAsset(file: File, meta: AssetMetadata, walletAdapter?: WalletAdapter, baseUrl?: string): Promise<UploadResponse>

Uploads an asset to Stream402.

Parameters:

  • file - File to upload
  • meta - Asset metadata:
    • title: string - Asset title
    • price: number | string - Price in USDC
    • recipient?: string - Recipient wallet address (optional, uses wallet if not provided)
    • tags?: string[] - Tags for searchability
    • description?: string - Asset description
  • walletAdapter - Optional wallet adapter (used for recipient if not provided)
  • baseUrl - Optional base URL of Stream402 API (defaults to current origin)

Returns:

  • { assetId: string, title: string, price: number, url: string, thumbnailUrl?: string }

Example:

const result = await uploadAsset(file, {
  title: "My Image",
  price: 0.01,
  tags: ["nature"],
}, wallet);

Types

PaymentChallenge

interface PaymentChallenge {
  version: string;
  network: string;
  currency: string;
  decimals: number;
  amount: number;
  mint: string;
  recipient: string;
  expiresAt: number;
  assetId: string;
  paymentRequestToken: string;
  description?: string;
  metadata?: Record<string, unknown>;
}

PaymentResult

interface PaymentResult {
  accessToken: string;
  downloadUrl: string;
  expiresAt: number;
}

AssetMetadata

interface AssetMetadata {
  title: string;
  price: number | string;
  recipient?: string;
  tags?: string[];
  description?: string;
}

Examples

React Component Example

import React, { useState } from "react";
import { useWallet } from "@solana/wallet-adapter-react";
import { discover, payAndFetch } from "@stream402/sdk";

function AssetViewer({ assetUrl }: { assetUrl: string }) {
  const wallet = useWallet();
  const [status, setStatus] = useState<"loading" | "free" | "payment_required" | "paid">("loading");
  const [downloadUrl, setDownloadUrl] = useState<string>("");

  useEffect(() => {
    checkAsset();
  }, [assetUrl]);

  const checkAsset = async () => {
    try {
      const result = await discover(assetUrl);
      if (result.type === "free") {
        setStatus("free");
        setDownloadUrl(result.url);
      } else {
        setStatus("payment_required");
      }
    } catch (error) {
      console.error("Failed to discover asset:", error);
    }
  };

  const handlePay = async () => {
    if (!wallet.connected) {
      await wallet.connect();
    }

    try {
      const result = await payAndFetch(assetUrl, wallet);
      setStatus("paid");
      setDownloadUrl(result.downloadUrl);
    } catch (error) {
      console.error("Payment failed:", error);
    }
  };

  return (
    <div>
      {status === "loading" && <p>Loading...</p>}
      {status === "free" && <a href={downloadUrl}>Download</a>}
      {status === "payment_required" && (
        <button onClick={handlePay}>Pay to Access</button>
      )}
      {status === "paid" && <a href={downloadUrl}>Download</a>}
    </div>
  );
}

Node.js Example

import { discover, payAndFetch } from "@stream402/sdk";
import { Connection, Keypair } from "@solana/web3.js";
import { NodeWalletAdapter } from "@solana/wallet-adapter-wallets";

// Create a wallet adapter from a keypair
const keypair = Keypair.fromSecretKey(/* your secret key */);
const wallet = new NodeWalletAdapter(keypair);
const connection = new Connection("https://api.devnet.solana.com");

// Discover and pay
const result = await discover("https://example.com/api/asset/123");
if (result.type === "payment_required") {
  const paymentResult = await payAndFetch(
    "https://example.com/api/asset/123",
    wallet,
    connection
  );
  console.log("Download URL:", paymentResult.downloadUrl);
}

Requirements

  • Node.js 18+
  • TypeScript 5+
  • Solana wallet adapter (for payment functionality)

License

MIT

Support

For issues and questions, please visit Stream402 GitHub.

Keywords

stream402

FAQs

Package last updated on 10 Nov 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts