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

@smoothsend/sdk

v1.0.0-beta.14

Published

Multi-chain gasless transaction SDK for seamless dApp integration

Downloads

55

Readme

SmoothSend SDK

A powerful multi-chain SDK for seamless gasless transaction integration in your dApps. Currently supporting Avalanche and Aptos with a unified developer experience and dynamic configuration system.

npm version TypeScript License: MIT

🚀 Features

  • Multi-Chain Ready: Currently supporting Avalanche and Aptos, with architecture ready for additional chains
  • Gasless Transactions: Users pay fees in tokens, not native gas
  • Dynamic Configuration: Chain configurations fetched dynamically from relayers
  • Type-Safe: Full TypeScript support with comprehensive type definitions
  • Event System: Real-time transaction status updates
  • Unified API: Consistent interface across all supported chains
  • Batch Transfers: Execute multiple transfers in a single transaction (Avalanche)
  • Wallet Integration: Easy integration with popular wallets
  • Caching: Intelligent caching of chain configurations for optimal performance

📦 Installation

npm install @smoothsend/sdk

⚠️ Important Security Update

For Aptos transactions, the SDK now uses a secure serialized transaction approach that requires proper wallet integration. The transaction flow differs from EVM chains:

  • Aptos: Requires transaction serialization using Aptos SDK
  • EVM (Avalanche): Uses EIP-712 typed data signing

See the Chain-Specific Examples section for proper implementation.

🏁 Quick Start

import { SmoothSendSDK } from '@smoothsend/sdk';

// Initialize the SDK
const smoothSend = new SmoothSendSDK({
  timeout: 30000,
  retries: 3
});

// Create a transfer request
const transferRequest = {
  from: '0x742d35cc6634c0532925a3b8d2d2d2d2d2d2d2d2',
  to: '0x742d35cc6634c0532925a3b8d2d2d2d2d2d2d2d3',
  token: 'USDC',
  amount: '1000000', // 1 USDC (6 decimals)
  chain: 'avalanche' as const
};

// Execute transfer (with wallet signer)
try {
  const result = await smoothSend.transfer(transferRequest, walletSigner);
  console.log('Transfer successful:', result.txHash);
} catch (error) {
  console.error('Transfer failed:', error.message);
}

🔧 Supported Chains

| Chain | Network | Status | Features | |-------|---------|--------|----------| | Avalanche | Fuji Testnet | ✅ Active | EIP-712 signatures, Batch transfers, Dynamic config | | Aptos | Testnet | ✅ Active | Ed25519 signatures, Gasless transactions, Secure serialization |

📚 API Reference

Core Methods

getQuote(request: TransferRequest): Promise<TransferQuote>

Get a quote for a transfer including fees and gas estimates.

const quote = await smoothSend.getQuote({
  from: '0x...',
  to: '0x...',
  token: 'USDC',
  amount: '1000000',
  chain: 'avalanche'
});

console.log('Fee:', quote.relayerFee);
console.log('Total:', quote.total);

transfer(request: TransferRequest, signer: any): Promise<TransferResult>

Execute a complete gasless transfer.

const result = await smoothSend.transfer(transferRequest, signer);
console.log('Transaction:', result.txHash);
console.log('Explorer:', result.explorerUrl);

batchTransfer(request: BatchTransferRequest, signer: any): Promise<TransferResult[]>

Execute multiple transfers in a single transaction (Avalanche only).

const batchRequest = {
  transfers: [
    { from: '0x...', to: '0x...', token: 'USDC', amount: '1000000', chain: 'avalanche' },
    { from: '0x...', to: '0x...', token: 'USDT', amount: '2000000', chain: 'avalanche' }
  ],
  chain: 'avalanche' as const
};

const results = await smoothSend.batchTransfer(batchRequest, signer);

Configuration Methods

getChainConfig(chain: SupportedChain): ChainConfig

Get static chain configuration.

const config = smoothSend.getChainConfig('avalanche');
console.log('Chain ID:', config.chainId);
console.log('Relayer URL:', config.relayerUrl);

getSupportedChains(): SupportedChain[]

Get list of supported chains.

const chains = smoothSend.getSupportedChains();
console.log('Supported chains:', chains); // ['avalanche']

Utility Methods

getBalance(chain: SupportedChain, address: string, token?: string): Promise<TokenBalance[]>

Get token balances for an address.

const balances = await smoothSend.getBalance('avalanche', '0x...');
const usdcBalance = await smoothSend.getBalance('avalanche', '0x...', 'USDC');

validateAddress(chain: SupportedChain, address: string): boolean

Validate an address format for a specific chain.

const isValid = smoothSend.validateAddress('avalanche', '0x742d35...');

Configuration Utilities

getChainConfig(chain: SupportedChain): ChainConfig

Get static chain configuration from the SDK.

import { getChainConfig, getAllChainConfigs } from '@smoothsend/sdk';

const avalancheConfig = getChainConfig('avalanche');
const allConfigs = getAllChainConfigs();

getTokenDecimals(token: string): number

Get token decimals for formatting.

import { getTokenDecimals } from '@smoothsend/sdk';

const usdcDecimals = getTokenDecimals('USDC'); // 6
const avaxDecimals = getTokenDecimals('AVAX'); // 18

Dynamic Configuration Service

chainConfigService.fetchChainConfig(relayerUrl: string): Promise<DynamicChainConfig[]>

Fetch dynamic chain configurations from relayers.

import { chainConfigService } from '@smoothsend/sdk';

const dynamicConfigs = await chainConfigService.fetchChainConfig('https://smoothsendevm.onrender.com');
console.log('Available chains:', dynamicConfigs.map(c => c.name));

Event Handling

Listen to transfer events for real-time updates:

smoothSend.addEventListener((event) => {
  switch (event.type) {
    case 'transfer_initiated':
      console.log('Transfer started');
      break;
    case 'transfer_signed':
      console.log('Transaction signed');
      break;
    case 'transfer_submitted':
      console.log('Transaction submitted');
      break;
    case 'transfer_confirmed':
      console.log('Transfer confirmed:', event.data.result);
      break;
    case 'transfer_failed':
      console.error('Transfer failed:', event.data.error);
      break;
  }
});

🌐 Chain-Specific Examples

Avalanche (EVM)

import { ethers } from 'ethers';
import { SmoothSendSDK, getChainConfig } from '@smoothsend/sdk';

// Initialize SDK
const smoothSend = new SmoothSendSDK();

// Connect to wallet
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();

// Get chain configuration
const chainConfig = getChainConfig('avalanche');
console.log('Using relayer:', chainConfig.relayerUrl);

// Transfer USDC on Avalanche
const result = await smoothSend.transfer({
  from: await signer.getAddress(),
  to: '0x742d35cc6634c0532925a3b8d2d2d2d2d2d2d2d3',
  token: 'USDC',
  amount: ethers.parseUnits('10', 6).toString(), // 10 USDC
  chain: 'avalanche'
}, signer);

console.log('Transfer successful:', result.txHash);
console.log('Explorer URL:', result.explorerUrl);

Aptos (Ed25519 with Secure Serialization)

import { SmoothSendSDK } from '@smoothsend/sdk';
import { Account, Aptos, AptosConfig, Network } from '@aptos-labs/ts-sdk';

// Initialize SDK
const smoothSend = new SmoothSendSDK();

// Connect to Aptos wallet (e.g., Petra)
// Note: This requires proper wallet integration that provides serialized transactions
const aptosWallet = window.aptos; // Petra wallet
await aptosWallet.connect();

// Get user address
const userAddress = await aptosWallet.account();

// Step 1: Get quote
const quote = await smoothSend.getQuote({
  from: userAddress.address,
  to: '0x742d35cc6634c0532925a3b8d2d2d2d2d2d2d2d3',
  token: 'USDC',
  amount: '1000000', // 1 USDC (6 decimals)
  chain: 'aptos-testnet'
});

// Step 2: Prepare transaction for signing
const signatureData = await smoothSend.prepareTransfer({
  from: userAddress.address,
  to: '0x742d35cc6634c0532925a3b8d2d2d2d2d2d2d2d3',
  token: 'USDC',
  amount: '1000000',
  chain: 'aptos-testnet'
}, quote);

// Step 3: Sign transaction with wallet
// IMPORTANT: Wallet must return serialized transaction bytes
const signedTransaction = await aptosWallet.signTransaction(signatureData.message);

// Ensure wallet provides required serialization
if (!signedTransaction.transactionBytes || !signedTransaction.authenticatorBytes) {
  throw new Error('Wallet must provide serialized transactionBytes and authenticatorBytes');
}

// Step 4: Execute transfer with serialized data
const result = await smoothSend.executeTransfer({
  signature: 'serialized', // Signature embedded in authenticatorBytes
  transferData: {
    transactionBytes: signedTransaction.transactionBytes,
    authenticatorBytes: signedTransaction.authenticatorBytes,
    functionName: 'smoothsend_transfer'
  }
}, 'aptos-testnet');

console.log('Aptos transfer successful:', result.txHash);
console.log('Explorer URL:', result.explorerUrl);
console.log('Gas paid by:', result.gasFeePaidBy); // 'relayer'

Important Notes for Aptos Integration:

  • Wallet must support transaction serialization
  • SDK expects transactionBytes and authenticatorBytes as number arrays
  • Relayer pays all gas fees (true gasless experience)
  • User only pays USDC fees to relayer

🔧 Configuration

SDK Configuration

const smoothSend = new SmoothSendSDK({
  timeout: 30000,        // Request timeout in milliseconds
  retries: 3,            // Number of retry attempts
  customChainConfigs: {
    avalanche: {
      relayerUrl: 'https://custom-avax-relayer.com'
    }
  }
});

Dynamic Configuration

The SDK now supports dynamic configuration fetching from relayers:

import { chainConfigService } from '@smoothsend/sdk';

// Fetch dynamic configurations
const dynamicConfigs = await chainConfigService.getAllChainConfigs();

// Get specific chain config with fallback
const avalancheConfig = await chainConfigService.getChainConfig('avalanche');

Static Configuration

For offline scenarios or when you need guaranteed configuration:

import { getChainConfig, getAllChainConfigs } from '@smoothsend/sdk';

// Get static configuration
const staticConfig = getChainConfig('avalanche');
const allStaticConfigs = getAllChainConfigs();

🎯 Example dApps

1. Token Sender dApp

A simple token transfer interface showcasing the SDK:

// examples/token-sender/src/App.tsx
import React, { useState } from 'react';
import { SmoothSendSDK, getChainConfig, getTokenDecimals } from '@smoothsend/sdk';
import { ethers } from 'ethers';

function TokenSender() {
  const [sdk] = useState(new SmoothSendSDK());
  const [loading, setLoading] = useState(false);

  const handleTransfer = async () => {
    setLoading(true);
    try {
      const provider = new ethers.BrowserProvider(window.ethereum);
      const signer = await provider.getSigner();
      
      // Get chain configuration
      const chainConfig = getChainConfig('avalanche');
      
      // Format amount with proper decimals
      const decimals = getTokenDecimals(selectedToken);
      const formattedAmount = ethers.parseUnits(amount, decimals).toString();
      
      const result = await sdk.transfer({
        from: await signer.getAddress(),
        to: recipientAddress,
        token: selectedToken,
        amount: formattedAmount,
        chain: 'avalanche'
      }, signer);
      
      alert(`Transfer successful! Tx: ${result.txHash}`);
    } catch (error) {
      alert(`Transfer failed: ${error.message}`);
    }
    setLoading(false);
  };

  return (
    <div className="token-sender">
      {/* UI components */}
      <button onClick={handleTransfer} disabled={loading}>
        {loading ? 'Sending...' : 'Send Tokens'}
      </button>
    </div>
  );
}

2. NFT Marketplace with Gasless Payments

// examples/nft-marketplace/src/components/BuyNFT.tsx
import { SmoothSendSDK, getChainConfig } from '@smoothsend/sdk';

class NFTMarketplace {
  private sdk = new SmoothSendSDK();

  async purchaseNFT(nftId: string, price: string, paymentToken: string) {
    // Get quote first
    const quote = await this.sdk.getQuote({
      from: buyerAddress,
      to: marketplaceAddress,
      token: paymentToken,
      amount: price,
      chain: 'avalanche'
    });

    console.log(`Fee: ${quote.relayerFee}, Total: ${quote.total}`);

    // Execute payment
    const result = await this.sdk.transfer({
      from: buyerAddress,
      to: marketplaceAddress,
      token: paymentToken,
      amount: price,
      chain: 'avalanche'
    }, signer);

    // Trigger NFT transfer after payment confirmation
    return result;
  }
}

3. DeFi Yield Farming dApp

// examples/defi-farming/src/services/FarmingService.ts
import { SmoothSendSDK } from '@smoothsend/sdk';

class FarmingService {
  private sdk = new SmoothSendSDK();

  async stakeLPTokens(amount: string, farmAddress: string) {
    // Batch transfer: approve + stake
    const results = await this.sdk.batchTransfer({
      transfers: [
        {
          from: userAddress,
          to: lpTokenAddress, // Approval
          token: 'USDC', // Use supported token
          amount: amount,
          chain: 'avalanche'
        },
        {
          from: userAddress,
          to: farmAddress, // Stake
          token: 'USDC',
          amount: amount,
          chain: 'avalanche'
        }
      ],
      chain: 'avalanche'
    }, signer);

    return results;
  }
}

🔐 Security

  • All transactions require user signature approval
  • Private keys never leave the client
  • Rate limiting and validation on relayer endpoints
  • Comprehensive input validation

Built with ❤️ by the SmoothSend team