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

@tapforce/pod-bridge-sdk

v2.0.1

Published

SDK for interacting with Bridges between pod and other chains

Readme

Pod Bridge SDK

TypeScript SDK for bridging tokens between POD and EVM chains (e.g., ETH Mainnet).

Architecture

ETH -> Pod: Deposit on ETH, AUTO-CLAIM on Pod (no claim TX needed)
Pod -> ETH: Deposit on Pod, claim on ETH with proof from pod_getBridgeClaimProof RPC

Key points:

  • ERC20 and native token bridging supported
  • Token addresses differ between chains (e.g., USDC on ETH maps to native 0xEeee...EEeE on Pod)
  • Use ETH-side decimals for amounts (e.g., 1e6 for 1 USDC, not 1e18)
  • Pod transactions require EIP-1559 (type 2) gas params, not legacy gasPrice

Features

  • Bridge Deposits: Deposit ERC20 or native tokens to the bridge
  • Claim with Proof: Claim on ETH using pod_getBridgeClaimProof RPC
  • Track Bridge Requests: Query deposits sent/received by any address
  • Claim Status Tracking: Monitor claim status and finality
  • Transaction Building: Generate unsigned transactions ready for signing

Installation

npm install @tapforce/pod-bridge-sdk
# or
yarn add @tapforce/pod-bridge-sdk
# or
pnpm add @tapforce/pod-bridge-sdk

Quick Start

import {
  SourceChainToPodActionClient,
  PodToSourceChainActionClient,
  PodBridgeTrackerClient,
  getBridgeClaimProof,
  SOURCE_CHAIN_BRIDGE_ABI,
  POD_BRIDGE_ABI,
} from '@tapforce/pod-bridge-sdk';

Configuration

For Action Clients (creating transactions)

import { PodBridgeActionsClientConfig } from '@tapforce/pod-bridge-sdk';

const actionConfig: PodBridgeActionsClientConfig = {
  sourceChain: {
    contractAddress: '0x...' // BridgeDepositWithdraw on ETH
  },
  pod: {
    contractAddress: '0x0000000000000000000000000000000000B41D9E' // BridgeMintBurn on Pod
  }
};

For Tracker Client (querying events)

import { PodBridgeConfig } from '@tapforce/pod-bridge-sdk';
import { ethers } from 'ethers';

const trackerConfig: PodBridgeConfig = {
  sourceChain: {
    provider: new ethers.JsonRpcProvider('https://eth-mainnet.rpc.example'),
    contractAddress: '0x...',
    deploymentBlock: 12345678 // Optional: avoids indexing empty blocks
  },
  pod: {
    provider: new ethers.JsonRpcProvider('https://rpc.pod.network'),
    contractAddress: '0x0000000000000000000000000000000000B41D9E',
    deploymentBlock: 0
  }
};

Usage

ETH -> Pod (Auto-claim)

Deposits on ETH are automatically claimed on Pod after block finalization.

const client = new SourceChainToPodActionClient(actionConfig);

// Create deposit transaction (with optional permit for gasless approval)
const depositTx = client.deposit({
  token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on ETH
  amount: ethers.parseUnits('1', 6),  // 1 USDC (use ETH-side decimals)
  destinationWalletAddress: '0x...',
  from: '0x...',
  // permit: '0x...' // Optional: ERC20 permit bytes
});

// Don't forget to approve the bridge contract first for ERC20 tokens
const tx = await signer.sendTransaction(depositTx);
const receipt = await tx.wait();

// No claim needed - balance auto-credited on Pod after finalization

Pod -> ETH (Claim with proof)

Deposits on Pod require claiming on ETH with a proof from pod_getBridgeClaimProof.

import {
  PodToSourceChainActionClient,
  getBridgeClaimProof,
  ClaimProofData,
} from '@tapforce/pod-bridge-sdk';

const client = new PodToSourceChainActionClient(actionConfig);

// Step 1: Deposit on Pod
const depositTx = client.deposit({
  token: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // Native token on Pod
  amount: ethers.parseUnits('1', 6),  // Use ETH-side decimals (1 USDC = 1e6)
  destinationWalletAddress: '0x...',
  from: '0x...',
});

// Pod requires EIP-1559 gas params (all zeros for free transactions)
const tx = await podSigner.sendTransaction({
  ...depositTx,
  maxFeePerGas: 0n,
  maxPriorityFeePerGas: 0n,
  gasLimit: 0n,
});

// Step 2: Get claim proof from Pod RPC
const { proof, auxTxSuffix } = await getBridgeClaimProof(podProvider, tx.hash);

// Step 3: Claim on ETH
const claimData: ClaimProofData = {
  ethTokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on ETH
  amount: ethers.parseUnits('1', 6),  // Must match deposited amount
  to: '0x...',
  proof,
  auxTxSuffix,
};

const claimTx = client.claim({ claimData, from: '0x...' });
const claim = await ethSigner.sendTransaction(claimTx);

Tracking Deposits

const tracker = new PodBridgeTrackerClient(trackerConfig);

// Get all deposits for an address
const deposits = await tracker.getAllDepositsFor('0x...');

for (const deposit of deposits) {
  console.log('Request ID:', deposit.requestId);
  console.log('Direction:', deposit.deposit.chain === 'sourceChain' ? 'ETH -> Pod' : 'Pod -> ETH');
  console.log('Token:', deposit.deposit.token);
  console.log('Amount:', deposit.deposit.amount);
  console.log('Timestamp:', new Date(deposit.deposit.timestamp * 1000).toISOString());
  console.log('Status:', deposit.isClaimed ? 'Claimed' : (deposit.isClaimable ? 'Claimable' : 'Pending'));
}

// Get deposits sent/received by address
const sent = await tracker.getDepositsSentBy('0x...');
const received = await tracker.getDepositsReceivedBy('0x...');

// Check if deposit can be claimed
const canClaim = await tracker.canBeClaimed(deposit);

// Batch check processed status
const statuses = await tracker.areRequestsProcessed(deposits);

API Reference

SourceChainToPodActionClient

For ETH -> Pod deposits (auto-claim on Pod).

deposit(args: {
  token: string;
  amount: string | bigint;
  destinationWalletAddress: string;
  from?: string;
  permit?: string;          // Optional ERC20 permit bytes (default: '0x')
}): UnsignedTransaction

PodToSourceChainActionClient

For Pod -> ETH deposits and claims.

// Deposit tokens on Pod
deposit(args: {
  token: string;            // Use 0xEeee...EEeE for native token
  amount: string | bigint;  // Use ETH-side decimals
  destinationWalletAddress: string;
  from?: string;
}): UnsignedTransaction

// Claim on ETH with proof
claim(args: {
  claimData: ClaimProofData;
  from?: string;
}): UnsignedTransaction

getBridgeClaimProof

Helper to call pod_getBridgeClaimProof RPC and format the result.

import { getBridgeClaimProof } from '@tapforce/pod-bridge-sdk';

const { proof, committeeEpoch, auxTxSuffix } = await getBridgeClaimProof(
  podProvider,      // ethers.JsonRpcProvider connected to Pod RPC
  depositTxHash     // TX hash of the deposit on Pod
);

PodBridgeTrackerClient

getDepositsSentBy(address: string, fromBlock?: number): Promise<BridgeRequest[]>
getDepositsReceivedBy(address: string, fromBlock?: number): Promise<BridgeRequest[]>
getAllDepositsFor(address: string, fromBlock?: number): Promise<BridgeRequestWithType[]>
canBeClaimed(deposit: BridgeRequest): Promise<boolean>
areRequestsProcessed(deposits: BridgeRequest[]): Promise<boolean[]>

Types

ClaimProofData

interface ClaimProofData {
  ethTokenAddress: string;  // Token address on ETH (different from Pod)
  amount: string | bigint;  // Must match deposited amount
  to: string;               // Recipient address
  proof: string;            // Hex bytes from pod_getBridgeClaimProof
  auxTxSuffix: string;      // Hex bytes from pod_getBridgeClaimProof
}

BridgeRequest

interface BridgeRequest {
  requestId: string;

  deposit: {
    chain: 'sourceChain' | 'pod';
    txHash: string;
    depositor: string;
    destination: string;
    token: string;
    amount: string;
    chainId: number;
    blockNumber: number;
    timestamp: number;       // Unix timestamp (seconds)
  };

  claim?: {
    chain: 'sourceChain' | 'pod';
    txHash: string;
    claimer: string;
    chainId: number;
    blockNumber: number;
    timestamp: number;
  };

  isClaimed: boolean;
  isClaimable: boolean;
}

Events

The bridge contracts emit different events per chain:

// ETH (Source Chain)
event Deposit(uint256 indexed id, address indexed from, address indexed to, address token, uint256 amount);
event Claim(bytes32 indexed txHash, address token, address mirrorToken, uint256 amount, address indexed to);

// Pod
event Deposit(bytes32 indexed id, address indexed from, address indexed to, address token, uint256 amount);

ABIs

The SDK exports separate ABIs for each chain:

  • SOURCE_CHAIN_BRIDGE_ABI - ETH bridge (deposit with permit, claim with proof)
  • POD_BRIDGE_ABI - Pod bridge (3-param deposit)
  • BRIDGE_ABI - Alias for SOURCE_CHAIN_BRIDGE_ABI

Pod-specific Notes

  • Pod system contract address: 0x0000000000000000000000000000000000B41D9E
  • Pod transactions are free: use maxFeePerGas: 0, maxPriorityFeePerGas: 0, gasLimit: 0
  • Must use EIP-1559 (type 2) transactions, not legacy gasPrice
  • Pod does NOT need value set for native token deposits - the system contract handles balance internally
  • Pod returns blockNumber as a Unix timestamp in receipts

Development

npm run build   # Build
npm run clean   # Clean

Dependencies

  • ethers: ^6.15.0

License

ISC

Repository