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

avax-warp-pay

v2.3.1

Published

Cross-chain payment receipt SDK for Avalanche Subnets using Teleporter

Readme

avax-warp-pay

Cross-chain payment SDK for Avalanche implementing HTTP 402 Payment Required.
Send payments on Chain A, verify them on Chain B — powered by Avalanche Teleporter.

NPM License


Installation

npm install avax-warp-pay ethers@^6

Quick Start

import { Warp402 } from "avax-warp-pay";
import { ethers } from "ethers";

const warp = new Warp402({
  privateKey: process.env.PRIVATE_KEY!,
  senderChain: {
    rpc: process.env.SENDER_RPC!,
    chainId: +process.env.SENDER_CHAIN_ID!,
    blockchainId: process.env.SENDER_BLOCKCHAIN_ID!,
    messenger: "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf",
    sender: process.env.SENDER_ADDRESS!
  },
  receiverChain: {
    rpc: process.env.RECEIVER_RPC!,
    chainId: +process.env.RECEIVER_CHAIN_ID!,
    blockchainId: process.env.RECEIVER_BLOCKCHAIN_ID!,
    messenger: "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf",
    receiver: process.env.RECEIVER_ADDRESS!
  }
});

// Send payment
const paymentId = await warp.pay(ethers.parseEther("0.1"));

// Wait for ICM Relayer to deliver message (~10-30s)
await new Promise(r => setTimeout(r, 15000));

// Verify on receiver chain
const verified = await warp.verify(paymentId);
console.log("Verified:", verified); // true ✅

⚠️ Important: ICM Relayer Required

Cross-chain messages need the ICM Relayer to work!

The SDK sends messages from Chain A → Chain B, but you need the Avalanche ICM Relayer running to actually deliver these messages.

Quick Setup (Local Development)

# 1. Start your Avalanche network
avalanche network start

# 2. Start the ICM Relayer (in a separate terminal)
avalanche interchain relayer start --local

# 3. Now use the SDK - verify() will return true! ✅

For Production (Fuji/Mainnet)

# Configure relayer for your subnets
avalanche interchain relayer configure

# Start relayer
avalanche interchain relayer start

Checking Relayer Status

# View recent relayer activity
avalanche interchain relayer logs --local --last 10

# Check if relayer is running
ps aux | grep relayer

Without the relayer:

  • pay() works (sends transaction on sender chain)
  • verify() returns false (message never reaches receiver)

With the relayer:

  • pay() works
  • verify() returns true (after 10-30 seconds) 🎉

Basic API

warp.pay(amount)

Send a payment from the sender chain.

const paymentId = await warp.pay(ethers.parseEther("1"));
// Returns the secure payment ID (different from input ID for security)

warp.verify(paymentId)

Check if the payment has been delivered to the receiver chain.

const verified = await warp.verify(paymentId);
// Returns true after ICM Relayer delivers the message (~10-30 seconds)

warp.consume(paymentId)

Mark a verified payment as consumed (prevents replay).

await warp.consume(paymentId);
// Only works after verify() returns true

Configuration

These values must point to your deployed WarpSender & WarpReceiver contracts:

PRIVATE_KEY=0x...
SENDER_RPC=...
SENDER_CHAIN_ID=...
SENDER_BLOCKCHAIN_ID=...
SENDER_ADDRESS=0x...

RECEIVER_RPC=...
RECEIVER_CHAIN_ID=...
RECEIVER_BLOCKCHAIN_ID=...
RECEIVER_ADDRESS=0x...

Teleporter Messenger (Fuji): 0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf


Contract Deployment

Warp-402 requires two contracts:

  • WarpSender — deployed on the payment chain
  • WarpReceiver — deployed on the verification chain

Option 1: CLI Deployment (Easiest - 30 seconds)

Deploy contracts with a single command:

npx avax-warp-pay deploy \
  --sender-rpc http://127.0.0.1:9650/ext/bc/C/rpc \
  --sender-chain-id 43112 \
  --sender-blockchain-id 0x7fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d5 \
  --receiver-rpc http://127.0.0.1:9650/ext/bc/subnet/rpc \
  --receiver-chain-id 99999 \
  --receiver-blockchain-id 0xc063de20d9e6e3b3e5b0f5e1e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5 \
  --private-key $PRIVATE_KEY

CLI Options Explained:

| Option | Required | Description | Example | |--------|----------|-------------|---------| | --sender-rpc | ✅ Yes | RPC URL for payment chain | http://localhost:9650/ext/bc/C/rpc | | --sender-chain-id | ✅ Yes | Chain ID of payment chain | 43112 (Fuji) or 43114 (Mainnet) | | --sender-blockchain-id | ✅ Yes | Blockchain ID (hex with 0x) | 0x7fc93d85c6d62c5b... | | --receiver-rpc | ✅ Yes | RPC URL for verification chain | http://localhost:9650/ext/bc/subnet/rpc | | --receiver-chain-id | ✅ Yes | Chain ID of verification chain | 99999 | | --receiver-blockchain-id | ✅ Yes | Blockchain ID (hex with 0x) | 0xc063de20d9e6e3b3... | | --private-key | ✅ Yes | Deployer private key | 0x... or $PRIVATE_KEY | | --messenger | ❌ No | Custom Teleporter Messenger | Defaults to Fuji messenger |

Example Output:

🚀 Deploying Warp-402 contracts...

📍 Deploying WarpSender on Chain 43112...
   ✅ Deployed at: 0x5aa01B3b5877255cE50cc55e8986a7a5fe29C70e

📍 Deploying WarpReceiver on Chain 99999...
   ✅ Deployed at: 0x52C84043CD9c865236f11d9Fc9F56aa003c1f922

🔗 Configuring cross-chain handshake...
   ✅ Configured successfully!

╔════════════════════════════════════════════════════════════════╗
║                  ✅ DEPLOYMENT SUCCESSFUL!                     ║
╚════════════════════════════════════════════════════════════════╝

💾 Add these to your .env file:

SENDER_ADDRESS=0x5aa01B3b5877255cE50cc55e8986a7a5fe29C70e
RECEIVER_ADDRESS=0x52C84043CD9c865236f11d9Fc9F56aa003c1f922

Using Environment Variables:

# Set in your .env file
PRIVATE_KEY=0x...
SENDER_RPC=http://127.0.0.1:9650/ext/bc/C/rpc
SENDER_CHAIN_ID=43112
SENDER_BLOCKCHAIN_ID=0x7fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d5
RECEIVER_RPC=http://127.0.0.1:9650/ext/bc/subnet/rpc
RECEIVER_CHAIN_ID=99999
RECEIVER_BLOCKCHAIN_ID=0xc063de20d9e6e3b3e5b0f5e1e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5

# Then deploy (no flags needed!)
npx avax-warp-pay deploy

Option 2: SDK Code Deployment (Programmatic)

Deploy contracts directly from your TypeScript code:

import { Warp402Factory } from "avax-warp-pay";

// Automated deployment with configuration
const warp = await Warp402Factory.quickSetup({
  privateKey: process.env.PRIVATE_KEY!,
  
  // Payment chain (where users pay)
  senderChain: {
    rpc: "http://127.0.0.1:9650/ext/bc/C/rpc",
    chainId: 43112,
    blockchainId: "0x7fc93d85c6d62c5b2ac0b519c87010ea5294012d1e407030d6acd0021cac10d5",
    messenger: "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf" // Optional
  },
  
  // Verification chain (where you verify)
  receiverChain: {
    rpc: "http://127.0.0.1:9650/ext/bc/subnet/rpc",
    chainId: 99999,
    blockchainId: "0xc063de20d9e6e3b3e5b0f5e1e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5",
    messenger: "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf" // Optional
  }
});

// ✅ Contracts deployed and configured!
// ✅ SDK ready to use immediately

// Access deployed addresses
const senderAddress = warp.sender.address;
const receiverAddress = warp.receiver.address;

console.log("✅ WarpSender deployed at:", senderAddress);
console.log("✅ WarpReceiver deployed at:", receiverAddress);

// Save these addresses to your .env file
console.log("\n💾 Add to .env:");
console.log(`SENDER_ADDRESS=${senderAddress}`);
console.log(`RECEIVER_ADDRESS=${receiverAddress}`);

// Start using immediately
const paymentId = await warp.pay(ethers.parseEther("0.1"));

Alternative: Deploy Only (Get Addresses Without SDK Init):

import { Warp402Factory } from "avax-warp-pay";

// Just deploy contracts, don't initialize SDK
const result = await Warp402Factory.deployOnly({
  privateKey: process.env.PRIVATE_KEY!,
  senderChain: {
    rpc: "http://127.0.0.1:9650/ext/bc/C/rpc",
    chainId: 43112,
    blockchainId: "0x7fc93d85..."
  },
  receiverChain: {
    rpc: "http://127.0.0.1:9650/ext/bc/subnet/rpc",
    chainId: 99999,
    blockchainId: "0xc063de20..."
  }
});

// Get deployment info
console.log("Sender Address:", result.senderAddress);
console.log("Receiver Address:", result.receiverAddress);
console.log("Sender TX Hash:", result.senderTxHash);
console.log("Receiver TX Hash:", result.receiverTxHash);

Option 3: Manual Foundry Deployment

Full deployment guide: https://github.com/jayasurya0007/wrap-x402/tree/main/wrapx402


SDK Features

✅ Core Payment Methods

  • warp.pay(amount) - Send cross-chain payment
  • warp.verify(paymentId) - Verify payment receipt
  • warp.consume(paymentId) - Mark payment as used
  • warp.getPayment(paymentId) - Get payment details

✅ Automated Deployment

  • CLI Tool: npx avax-warp-pay deploy - One-command deployment
  • SDK Factory: Warp402Factory.quickSetup() - Programmatic deployment
  • Manual Option: Full Foundry support for custom setups

✅ Contract Interaction

  • Sender Contract: warp.sender.contract - Access WarpSender methods
  • Receiver Contract: warp.receiver.contract - Access WarpReceiver methods
  • Configuration: warp.sender.getConfiguration() - Read contract settings

✅ TypeScript Support

  • Full TypeScript definitions included
  • Typed interfaces for all methods
  • Auto-completion in IDEs

Examples

Complete Payment Flow

// 1. Send payment on sender chain
const paymentId = await warp.pay(ethers.parseEther("0.1"));
console.log("Payment sent:", paymentId);

// 2. Wait for ICM Relayer to deliver message
console.log("Waiting for cross-chain delivery...");
await new Promise(r => setTimeout(r, 15000)); // 15 seconds

// 3. Verify payment on receiver chain
const verified = await warp.verify(paymentId);
console.log("Verified:", verified); // true ✅

// 4. Consume payment (mark as used)
if (verified) {
  await warp.consume(paymentId);
  console.log("Payment consumed!");
}

Production Usage Pattern

// Send payment immediately
const paymentId = await warp.pay(amount);

// Poll for verification (recommended for production)
async function waitForVerification(paymentId: string, timeout = 60000) {
  const startTime = Date.now();
  
  while (Date.now() - startTime < timeout) {
    const verified = await warp.verify(paymentId);
    
    if (verified) {
      return true; // ✅ Payment verified!
    }
    
    // Wait 2 seconds before checking again
    await new Promise(r => setTimeout(r, 2000));
  }
  
  return false; // ❌ Timeout
}

// Usage
const verified = await waitForVerification(paymentId);
if (verified) {
  // Grant access, deliver content, etc.
  await warp.consume(paymentId);
}

Troubleshooting

Problem: verify() always returns false

# Check if ICM Relayer is running
avalanche interchain relayer logs --local --last 5

# If not running, start it:
avalanche interchain relayer start --local

Problem: Relayer shows "message delivered" but verify() still false

This was a bug in v2.2.0 and earlier. Update to v2.3.0+:

npm install avax-warp-pay@latest

Problem: Want to see what's happening

Enable debug logging:

import { setLogLevel, LogLevel } from 'avax-warp-pay';

setLogLevel(LogLevel.DEBUG); // See all SDK operations

License

MIT © 2025 Warp-402 Team


Links