Sign In

@zerodust/sdk

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@zerodust/sdk

TypeScript SDK for ZeroDust - sweep native gas tokens to zero

Source
npmnpm
Version
0.1.0
Version published
Weekly downloads
69
-16.87%
Maintainers
1
Weekly downloads
 
Created
Source

@zerodust/sdk

CI npm version npm downloads License: MIT

TypeScript SDK for ZeroDust - sweep native gas tokens to exactly zero.

ZeroDust enables users to completely empty their native token balance (ETH, BNB, MATIC, etc.) from any EVM chain, sending the funds to any address on the same or different chain. This is powered by EIP-7702 sponsored execution.

Installation

npm install @zerodust/sdk viem
yarn add @zerodust/sdk viem
pnpm add @zerodust/sdk viem

Note: viem is a peer dependency and must be installed separately.

Quick Start

import { ZeroDust } from '@zerodust/sdk';
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';

// 1. Initialize the SDK
const zerodust = new ZeroDust({ environment: 'mainnet' });

// 2. Check balances across all chains
const balances = await zerodust.getBalances('0xYourAddress...');
console.log('Sweepable balances:', balances.chains.filter(b => b.canSweep));

// 3. Get a quote for sweeping
const quote = await zerodust.getQuote({
  fromChainId: 8453,        // Base
  toChainId: 8453,          // Same chain (or different for cross-chain)
  userAddress: '0xYourAddress...',
  destination: '0xDestination...',
});

console.log('You will receive:', quote.minReceiveWei);
console.log('Total fees:', quote.fees.totalFeeWei);

// 4. Create authorization for signing
const { typedData, contractAddress } = await zerodust.createAuthorization(quote.quoteId);

// 5. Sign with your wallet (example using viem)
const account = privateKeyToAccount('0x...');
const walletClient = createWalletClient({
  account,
  chain: base,
  transport: http(),
});

// Sign the EIP-712 typed data
const signature = await walletClient.signTypedData(typedData);

// Sign the EIP-7702 authorization
const eip7702Authorization = await walletClient.signAuthorization({
  contractAddress,
});

// 6. Submit the sweep
const sweep = await zerodust.submitSweep({
  quoteId: quote.quoteId,
  signature,
  eip7702Authorization: {
    chainId: eip7702Authorization.chainId,
    contractAddress,
    nonce: Number(eip7702Authorization.nonce),
    yParity: eip7702Authorization.yParity as 0 | 1,
    r: eip7702Authorization.r,
    s: eip7702Authorization.s,
  },
});

// 7. Wait for completion
const result = await zerodust.waitForSweep(sweep.sweepId);
console.log('Sweep completed! TX:', result.txHash);

Configuration

const zerodust = new ZeroDust({
  // Environment: 'mainnet' or 'testnet'
  environment: 'mainnet',

  // Optional: Custom API URL (overrides environment)
  baseUrl: 'https://api.zerodust.xyz',

  // Optional: API key for higher rate limits
  apiKey: 'your-api-key',

  // Optional: Request timeout in ms (default: 30000)
  timeout: 30000,

  // Optional: Number of retries on failure (default: 3)
  retries: 3,
});

API Reference

Chain Methods

getChains(testnet?: boolean): Promise<Chain[]>

Get list of supported chains.

const chains = await zerodust.getChains();

chains.forEach(chain => {
  console.log(`${chain.name} (${chain.chainId})`);
  console.log(`  Contract: ${chain.contractAddress}`);
  console.log(`  Min sweep: ${chain.minSweepWei} wei`);
});

getChain(chainId: number): Promise<Chain>

Get a specific chain by ID.

const base = await zerodust.getChain(8453);
console.log(base.name); // 'Base'

Balance Methods

getBalances(address: string, testnet?: boolean): Promise<BalancesResponse>

Get balances for an address across all supported chains.

const { chains, totalUsd } = await zerodust.getBalances('0x...');

console.log(`Total value: $${totalUsd}`);

chains.forEach(balance => {
  if (balance.canSweep) {
    console.log(`${balance.chainName}: ${balance.balanceFormatted}`);
  }
});

getBalance(address: string, chainId: number): Promise<ChainBalance>

Get balance for a specific chain.

const balance = await zerodust.getBalance('0x...', 8453);

if (balance.canSweep) {
  console.log(`Can sweep ${balance.balanceFormatted} from Base`);
}

Quote Methods

getQuote(params: QuoteRequest): Promise<QuoteResponse>

Get a quote for sweeping. Quotes are valid for 60 seconds.

// Same-chain sweep
const sameChainQuote = await zerodust.getQuote({
  fromChainId: 8453,
  toChainId: 8453,
  userAddress: '0x...',
  destination: '0x...',
});

// Cross-chain sweep (Arbitrum → Base)
const crossChainQuote = await zerodust.getQuote({
  fromChainId: 42161,  // Arbitrum
  toChainId: 8453,     // Base
  userAddress: '0x...',
  destination: '0x...',
});

// Quote response includes fee breakdown
console.log('Balance:', quote.balanceWei);
console.log('You receive:', quote.minReceiveWei);
console.log('Service fee:', quote.fees.serviceFeeWei);
console.log('Gas reimbursement:', quote.fees.gasReimbursementWei);
console.log('Bridge fee:', quote.fees.bridgeFeeWei);
console.log('Total fees:', quote.fees.totalFeeWei);
console.log('Expires:', quote.expiresAt);

Authorization Methods

createAuthorization(quoteId: string): Promise<AuthorizationResponse>

Create EIP-712 typed data for signing.

const { typedData, contractAddress, expiresAt } = await zerodust.createAuthorization(quote.quoteId);

// typedData: EIP-712 typed data to sign (SweepIntent)
// contractAddress: ZeroDust contract to delegate to via EIP-7702
// expiresAt: When the authorization expires

Sweep Methods

submitSweep(request: SweepRequest): Promise<SweepResponse>

Submit a signed sweep for execution.

const sweep = await zerodust.submitSweep({
  quoteId: quote.quoteId,
  signature: '0x...',           // EIP-712 signature
  eip7702Authorization: {
    chainId: 8453,
    contractAddress: '0x...',
    nonce: 0,
    yParity: 0,
    r: '0x...',
    s: '0x...',
  },
  // Optional: For auto-revoke after sweep
  revokeAuthorization: {
    chainId: 8453,
    contractAddress: '0x0000000000000000000000000000000000000000',
    nonce: 1,
    yParity: 0,
    r: '0x...',
    s: '0x...',
  },
});

console.log('Sweep ID:', sweep.sweepId);
console.log('Status:', sweep.status);

getSweepStatus(sweepId: string): Promise<SweepStatusResponse>

Get the current status of a sweep.

const status = await zerodust.getSweepStatus(sweep.sweepId);

switch (status.status) {
  case 'pending':
    console.log('Waiting to be processed...');
    break;
  case 'simulating':
    console.log('Simulating transaction...');
    break;
  case 'executing':
    console.log('Transaction submitted...');
    break;
  case 'bridging':
    console.log('Bridging to destination chain...');
    break;
  case 'completed':
    console.log('Done! TX:', status.txHash);
    break;
  case 'failed':
    console.log('Failed:', status.errorMessage);
    break;
}

getSweeps(address: string, options?: ListSweepsOptions): Promise<SweepsListResponse>

List sweeps for a user address.

const { sweeps, total } = await zerodust.getSweeps('0x...', {
  limit: 10,
  offset: 0,
  status: 'completed',  // Optional filter
});

sweeps.forEach(sweep => {
  console.log(`${sweep.sweepId}: ${sweep.status}`);
});

waitForSweep(sweepId: string, options?): Promise<SweepStatusResponse>

Poll until sweep reaches a terminal state (completed or failed).

const result = await zerodust.waitForSweep(sweep.sweepId, {
  intervalMs: 2000,     // Poll every 2 seconds (default)
  timeoutMs: 120000,    // Timeout after 2 minutes (default)
  onStatusChange: (status) => {
    console.log('Status changed:', status.status);
  },
});

if (result.status === 'completed') {
  console.log('Success! TX:', result.txHash);
} else {
  console.log('Failed:', result.errorMessage);
}

Error Handling

All errors extend ZeroDustError with a machine-readable code:

import { ZeroDustError, isZeroDustError } from '@zerodust/sdk';

try {
  await zerodust.getQuote(params);
} catch (error) {
  if (isZeroDustError(error)) {
    console.log('Error code:', error.code);
    console.log('Message:', error.message);
    console.log('User message:', error.getUserMessage());
    console.log('Details:', error.details);
    console.log('Retryable:', error.isRetryable());

    switch (error.code) {
      case 'BALANCE_TOO_LOW':
        console.log('Balance too low to sweep');
        break;
      case 'QUOTE_EXPIRED':
        console.log('Quote expired, get a new one');
        break;
      case 'CHAIN_NOT_SUPPORTED':
        console.log('Chain not supported');
        break;
      case 'NETWORK_ERROR':
        console.log('Network error, retry');
        break;
      // ... handle other codes
    }
  }
}

Error Codes

CodeDescriptionRetryable
BALANCE_TOO_LOWBalance is below minimum sweep amountNo
QUOTE_EXPIREDQuote has expired (60s lifetime)No
QUOTE_NOT_FOUNDQuote ID not foundNo
CHAIN_NOT_SUPPORTEDChain is not supportedNo
INVALID_ADDRESSInvalid Ethereum addressNo
INVALID_SIGNATURESignature verification failedNo
INVALID_CHAIN_IDInvalid chain IDNo
EIP7702_INVALID_SIGNATUREInvalid EIP-7702 authorizationNo
SIGNATURE_REJECTEDUser rejected signature requestNo
BRIDGE_UNAVAILABLEBridge route not availableNo
SOURCE_CHAIN_DISABLEDSource chain temporarily disabledNo
DEST_CHAIN_DISABLEDDestination chain temporarily disabledNo
SIMULATION_FAILEDTransaction simulation failedNo
NETWORK_ERRORNetwork connectivity issueYes
TIMEOUTRequest timed outYes
RPC_ERRORRPC node errorYes
SERVICE_UNAVAILABLEService temporarily unavailableYes
INTERNAL_ERRORInternal server errorYes

Specific Error Classes

import {
  BalanceTooLowError,
  QuoteExpiredError,
  NetworkError,
  TimeoutError,
  ChainNotSupportedError,
  InvalidAddressError,
  SignatureError,
  BridgeError,
} from '@zerodust/sdk';

try {
  await zerodust.getBalance('invalid', 8453);
} catch (error) {
  if (error instanceof InvalidAddressError) {
    console.log('Invalid address:', error.details?.address);
  }
}

Utilities

The SDK exports utility functions for advanced use cases:

Validation

import {
  validateAddress,
  validateChainId,
  validateSignature,
  validateUuid,
  validateAmount,
  validateHex,
  validateQuoteRequest,
  validateEIP7702Authorization,
} from '@zerodust/sdk';

// Validate and normalize address (returns checksummed)
const address = validateAddress('0x...', 'userAddress');

// Validate chain ID (must be positive integer)
const chainId = validateChainId(8453);

// Validate signature (64 or 65 bytes)
const sig = validateSignature('0x...');

// Validate UUID format
const id = validateUuid('550e8400-e29b-41d4-a716-446655440000', 'quoteId');

// Validate amount (string or bigint, non-negative)
const amount = validateAmount('1000000000000000000', 'balance');

EIP-712 Signature Helpers

import {
  DOMAIN_NAME,
  DOMAIN_VERSION,
  MODE_TRANSFER,
  MODE_CALL,
  ZERO_ADDRESS,
  ZERO_ROUTE_HASH,
  SWEEP_INTENT_TYPES,
  computeRouteHash,
  buildSweepIntentTypedData,
  buildSweepIntentFromQuote,
  validateSweepIntentParams,
} from '@zerodust/sdk';

// Constants
console.log(DOMAIN_NAME);    // 'ZeroDustSweep'
console.log(DOMAIN_VERSION); // '1'
console.log(MODE_TRANSFER);  // 0 (same-chain)
console.log(MODE_CALL);      // 1 (cross-chain)

// Compute route hash for cross-chain sweeps
const routeHash = computeRouteHash('0x...');

// Build EIP-712 typed data manually
const typedData = buildSweepIntentTypedData(8453, userAddress, {
  mode: MODE_TRANSFER,
  user: userAddress,
  destination: destinationAddress,
  destinationChainId: 8453n,
  callTarget: ZERO_ADDRESS,
  routeHash: ZERO_ROUTE_HASH,
  minReceive: 900000000000000n,
  maxTotalFeeWei: 100000000000000n,
  overheadGasUnits: 100000n,
  protocolFeeGasUnits: 0n,
  extraFeeWei: 50000000000000n,
  reimbGasPriceCapWei: 1000000000n,
  deadline: BigInt(Math.floor(Date.now() / 1000) + 60),
  nonce: 0n,
});

TypeScript Types

All types are exported for use in your application:

import type {
  // Configuration
  Environment,
  ZeroDustConfig,

  // Chain types
  Chain,
  ChainsResponse,

  // Balance types
  ChainBalance,
  BalancesResponse,

  // Quote types
  QuoteRequest,
  QuoteResponse,
  FeeBreakdown,
  SweepIntentFields,

  // Authorization types
  AuthorizationResponse,
  EIP712TypedData,
  EIP7702Authorization,

  // Sweep types
  SweepRequest,
  SweepResponse,
  SweepStatus,
  RevokeStatus,
  SweepStatusResponse,
  SweepSummary,
  ListSweepsOptions,
  SweepsListResponse,

  // Error types
  ZeroDustErrorCode,
  ApiErrorResponse,
} from '@zerodust/sdk';

AI Agent Integration

ZeroDust provides a specialized module for autonomous AI agents that control their own wallets:

import { createAgentFromPrivateKey } from '@zerodust/sdk';

// Create an agent that handles all signing automatically
const agent = await createAgentFromPrivateKey('0x...', {
  environment: 'mainnet',
  apiKey: 'zd_...', // Optional: for higher rate limits
});

// Single sweep
await agent.sweep({
  fromChainId: 42161, // Arbitrum
  toChainId: 8453,    // Base
});

// Batch sweep multiple chains
await agent.batchSweep({
  sweeps: [
    { fromChainId: 42161 },
    { fromChainId: 10 },
    { fromChainId: 137 },
  ],
  toChainId: 8453,
});

// Sweep all chains with balance
await agent.sweepAll({ toChainId: 8453 });

For detailed AI agent integration guide, see AGENT_INTEGRATION.md.

Supported Chains

ZeroDust supports all EVM chains with EIP-7702 support. Current mainnet chains include:

  • Base (8453)
  • Arbitrum (42161)
  • Optimism (10)
  • Polygon (137)
  • BSC (56)
  • Gnosis (100)
  • And 20+ more...

Use getChains() to get the current list of supported chains.

Fee Structure

ZeroDust charges a small service fee for sweeps:

  • Minimum fee: $0.05 equivalent
  • Maximum fee: $0.50 equivalent
  • Standard fee: 1% of transferred value (between min/max)
  • Free tier: No service fee for sweeps under $1

Additionally:

  • Gas reimbursement: Actual gas cost paid by the relayer
  • Bridge fee: Near-zero (only destination gas for cross-chain)

Example: Sweeping $5 worth of ETH → ~$0.05 service fee + gas

Browser Support

The SDK works in both Node.js and browser environments. For browsers, ensure your bundler handles the viem peer dependency correctly.

<script type="module">
  import { ZeroDust } from '@zerodust/sdk';

  const zerodust = new ZeroDust({ environment: 'mainnet' });
  // ...
</script>

License

MIT

Keywords

zerodust

FAQs

Package last updated on 12 Feb 2026

Related posts