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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@onchainfi/uplink

v2.2.0

Published

Access Point to the Onchain Aggregator - JavaScript/TypeScript SDK

Readme

Onchain Uplink

Quickstart

1. Install

npm install @onchainfi/uplink

2. Get API Key

Visit onchain.fi/get-api-key

3. Make a Payment

import { Uplink } from '@onchainfi/uplink';

const uplink = new Uplink({
  apiKey: process.env.ONCHAIN_API_KEY!,
  privateKey: process.env.UPLINK_PRIVATE_KEY!,
  network: 'base',  // or 'solana'
  createAtaFeeAcceptance: true,
  minimumCrosschainFeeAcceptance: true,
});

const txHash = await uplink.pay({
  to: '0xRecipient...',
  amount: '$10'
});

console.log(`Paid! TX: ${txHash}`);

That's it! Same-chain payments on Base and Solana.


📚 Examples

New to Uplink? Check out our comprehensive examples:

Both include detailed READMEs with patterns, best practices, and real-world use cases.


Installation

npm install @onchainfi/uplink
# or
yarn add @onchainfi/uplink
# or
pnpm add @onchainfi/uplink

Full Example

import { Uplink } from '@onchainfi/uplink';

// Initialize
const uplink = new Uplink({
  apiKey: process.env.ONCHAIN_API_KEY!,
  privateKey: process.env.UPLINK_PRIVATE_KEY!,
  network: 'base',
  createAtaFeeAcceptance: true,
  minimumCrosschainFeeAcceptance: true,
});

// Make a payment
const txHash = await uplink.pay({
  to: '0xRecipient...',
  amount: '$10.50'
});
console.log(`Payment sent: ${txHash}`);

Two Modes

Mode A: SDK Signs (Convenience)

SDK handles signing with your private key:

const uplink = new Uplink({
  apiKey: process.env.ONCHAIN_API_KEY!,
  privateKey: process.env.UPLINK_PRIVATE_KEY!,
  createAtaFeeAcceptance: true,
  minimumCrosschainFeeAcceptance: true,
});

const txHash = await uplink.pay({
  to: '0xRecipient...',
  amount: '$10'
});

Mode B: Pre-Signed (Advanced/Secure)

You sign externally (hardware wallet, custom signer, etc.):

const uplink = new Uplink({
  apiKey: process.env.ONCHAIN_API_KEY!,
  createAtaFeeAcceptance: true,
  minimumCrosschainFeeAcceptance: true,
});

// Sign with your external signer (hardware wallet, etc.)
// For Base (EVM) - Complete EIP-712 signing:
import { ethers } from 'ethers';

const wallet = new ethers.Wallet(privateKey); // Or hardware wallet

// EIP-712 signature for USDC Transfer with Authorization
const domain = {
  name: 'USD Coin',
  version: '2',
  chainId: 8453, // Base
  verifyingContract: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
};

const types = {
  TransferWithAuthorization: [
    { name: 'from', type: 'address' },
    { name: 'to', type: 'address' },
    { name: 'value', type: 'uint256' },
    { name: 'validAfter', type: 'uint256' },
    { name: 'validBefore', type: 'uint256' },
    { name: 'nonce', type: 'bytes32' },
  ],
};

const nonce = '0x' + Array.from(crypto.getRandomValues(new Uint8Array(32)))
  .map(b => b.toString(16).padStart(2, '0'))
  .join('');

const value = {
  from: wallet.address,
  to: '0xRecipient...',
  value: BigInt(10_000_000), // 10 USDC (6 decimals)
  validAfter: BigInt(0),
  validBefore: BigInt(Math.floor(Date.now() / 1000) + 3600), // 1 hour
  nonce,
};

const signature = await wallet.signTypedData(domain, types, value);

// Create x402 payment header
const paymentHeader = Buffer.from(JSON.stringify({
  x402Version: 1,
  scheme: 'exact',
  network: 'base',
  payload: {
    signature,
    authorization: {
      from: wallet.address,
      to: value.to,
      value: value.value.toString(),
      validAfter: value.validAfter.toString(),
      validBefore: value.validBefore.toString(),
      nonce,
    },
  },
})).toString('base64');

// Pass pre-signed header to Uplink
const txHash = await uplink.pay({
  to: '0xRecipient...',
  amount: '$10',
  paymentHeader
});

Amount Formats

All these work:

await uplink.pay({ to: '0x...', amount: '$10' });      // Dollar sign
await uplink.pay({ to: '0x...', amount: '10.50' });    // Plain number
await uplink.pay({ to: '0x...', amount: '10 USDC' });  // With token

Advanced Features

Idempotency (Safe Retries)

const txHash = await uplink.pay({
  to: '0x...',
  amount: '$10',
  idempotencyKey: 'unique-payment-id-123'
});

// Retry safe - same key returns same tx_hash
const txHash2 = await uplink.pay({
  to: '0x...',
  amount: '$10',
  idempotencyKey: 'unique-payment-id-123'
});

// txHash === txHash2

Metadata Tracking

const txHash = await uplink.pay({
  to: '0x...',
  amount: '$10',
  metadata: {
    agent_id: 'gpt-4-assistant',
    task_id: 'abc-123',
    purpose: 'API credits'
  }
});

Routing Priority

// Optimize for speed
await uplink.pay({ to: '0x...', amount: '$10', priority: 'speed' });

// Optimize for cost
await uplink.pay({ to: '0x...', amount: '$10', priority: 'cost' });

// Optimize for reliability
await uplink.pay({ to: '0x...', amount: '$10', priority: 'reliability' });

// Balanced (default)
await uplink.pay({ to: '0x...', amount: '$10', priority: 'balanced' });

Error Handling

import {
  SamechainClient,
  PaymentError,
  AuthenticationError,
  NetworkError
} from '@onchainfi/uplink';

try {
  const txHash = await uplink.pay({ to: '0x...', amount: '$10' });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key');
  } else if (error instanceof PaymentError) {
    console.error(`Payment failed: ${error.reason}`);
  } else if (error instanceof NetworkError) {
    console.error('Network request failed');
  }
}

Configuration

const uplink = new Uplink({
  apiKey: 'onchain_xxx',
  privateKey: '0x...',
  network: 'base',                      // Default: 'base'
  apiUrl: 'https://api.onchain.fi',     // Default: 'https://api.onchain.fi' (production)
  maxRetries: 3,                        // Default: 3
  retryDelay: 1.0,                      // Default: 1.0 (seconds)
  timeout: 120.0,                       // Default: 120.0 (seconds)
  solanaRpcUrl: 'https://api.mainnet-beta.solana.com',  // Default: Solana mainnet RPC
  createAtaFeeAcceptance: true,         // Required: Acknowledge ATA fees
  minimumCrosschainFeeAcceptance: true, // Required: Acknowledge cross-chain minimums
});

Environment Configuration

Production (Default):

const uplink = new Uplink({
  apiKey: process.env.ONCHAIN_API_KEY!,
  privateKey: process.env.UPLINK_PRIVATE_KEY!,
  createAtaFeeAcceptance: true,
  minimumCrosschainFeeAcceptance: true,
  // Uses production API: https://api.onchain.fi
});

Staging/Testing:

const uplink = new Uplink({
  apiKey: process.env.ONCHAIN_API_KEY!,
  privateKey: process.env.UPLINK_PRIVATE_KEY!,
  apiUrl: 'https://staging.onchain.fi',  // Override for testing
  createAtaFeeAcceptance: true,
  minimumCrosschainFeeAcceptance: true,
});

Or via environment variable:

export UPLINK_API_URL=https://staging.onchain.fi

Security Best Practices

✅ DO: Use Environment Variables

import { Uplink } from '@onchainfi/uplink';

const uplink = new Uplink({
  apiKey: process.env.ONCHAIN_API_KEY!,
  privateKey: process.env.UPLINK_PRIVATE_KEY!,
  createAtaFeeAcceptance: true,
  minimumCrosschainFeeAcceptance: true,
});

❌ DON'T: Hardcode Keys

// BAD - Will trigger security warning
const uplink = new Uplink({
  apiKey: 'onchain_abc123...',
  privateKey: '0x1234567...'
});

Getting API Keys

  1. Onchain API Key: Visit onchain.fi/get-api-key
  2. Private Key: Use your wallet's export function (store securely!)

Requirements

  • Node.js >= 18.0.0 (for native fetch)
  • TypeScript (optional, but recommended)

License

AGPL-3.0

Links