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

hustle-incognito

v0.2.4

Published

SDK for interacting with the Emblem Vault Hustle Incognito Agent API

Readme

Emblem Vault Hustle Incognito SDK

Power your applications with EmblemVault's AI Agent Hustle API – the secure, intelligent assistant for crypto & web3.

npm version License TypeScript Maintainer

✨ Build an AI-powered CLI in 10 lines

import { HustleIncognitoClient } from 'hustle-incognito';

// Create client with your API key
const client = new HustleIncognitoClient({
  apiKey: process.env.HUSTLE_API_KEY
});

// Get a response from the AI
const response = await client.chat([
  { role: 'user', content: 'What can you tell me about the current trending tokens on Solana?' }
], { vaultId: process.env.VAULT_ID });

console.log(response.content);

🚀 Features

  • Three Flexible Modes: Simple request/response, processed streaming, or raw API output
  • Intelligent AI Agent: Access to 20+ built-in crypto & web3 tools
  • Both Browser & Node.js: Works seamlessly in any JavaScript environment
  • Minimal Setup: Production-ready with sensible defaults
  • Highly Configurable: Advanced options when you need them
  • Built for Testing: Override pattern allows easy mocking

📝 Examples

Looking for complete, working examples? Check out the examples/ directory:

See the Examples README for setup instructions and usage details.

📦 Installation

# Using npm
npm install hustle-incognito

# Using yarn
yarn add hustle-incognito

# Using pnpm
pnpm add hustle-incognito

🔑 Authentication

Authentication is simple - just provide your API key when initializing the client:

const client = new HustleIncognitoClient({
  apiKey: 'your-api-key-here',
  // Optional configuration
  hustleApiUrl: 'https://agenthustle.ai', // Defaults to https://agenthustle.ai
  debug: true // Enable verbose logging
});

🔍 Usage Modes

1️⃣ Simple Request/Response

Perfect for CLI tools or simple applications - send a message, get back a complete response:

// Get a complete response
const response = await client.chat([
  { role: 'user', content: 'Show me the top Solana Tokens this week' }
], { vaultId: 'my-vault' });

console.log(response.content);
console.log(`Used ${response.usage?.total_tokens} tokens`);

// Tool calls are also available
if (response.toolCalls?.length > 0) {
  console.log('Agent used these tools:', response.toolCalls);
}

2️⃣ Processed Streaming (for interactive UIs)

Receive typed, structured chunks for building interactive experiences:

// For UIs with streaming responses
for await (const chunk of client.chatStream({ 
  messages: [{ role: 'user', content: 'Show me the top Solana tokens this week' }],
  vaultId: 'my-vault',
  processChunks: true 
})) {
  switch (chunk.type) {
    case 'text':
      ui.appendText(chunk.value);
      break;
    case 'tool_call':
      ui.showToolInProgress(chunk.value);
      break;
    case 'tool_result':
      ui.showToolResult(chunk.value);
      break;
    case 'finish':
      ui.complete(chunk.value);
      break;
  }
}

3️⃣ Raw API Streaming (maximum control)

Direct access to the raw API stream format:

// For maximum control and custom processing
for await (const rawChunk of client.rawStream({
  messages: [{ role: 'user', content: 'Find transactions for address 0x123...' }],
  vaultId: 'my-vault'
})) {
  // Raw chunks have prefix character and data
  console.log(`Received ${rawChunk.prefix}: ${rawChunk.raw}`);
  
  // Process different prefix types
  switch (rawChunk.prefix) {
    case '0': // Text chunk
      console.log('Text:', rawChunk.data);
      break;
    case '9': // Tool call
      console.log('Tool call:', rawChunk.data);
      break;
    case 'a': // Tool result
      console.log('Tool result:', rawChunk.data);
      break;
    case 'f': // Message ID
      console.log('Message ID:', rawChunk.data.messageId);
      break;
    case '2': // Path info
      console.log('Path info:', rawChunk.data);
      break;
    case 'e': // Completion event
    case 'd': // Final data
      console.log('Finished:', rawChunk.data);
      break;
  }
}

🛠 Tools

The Agent Hustle API has access to 25+ powerful tool categories for comprehensive crypto trading, analysis, and DeFi operations.

Available Tools

This list might not be exhaustive, use the getTools method to get the latest tools

Core Trading Tools

  • Standard Tools: Core trading toolbox with token research, contract addresses, strategic pricing, swaps, transfers, and persistent memory for end-to-end trading workflow management
  • PumpFun: Discover trending memecoins, buy/sell tokens, create new tokens, and track graduation status across the complete PumpFun lifecycle
  • Meteora DBC (Premium): Management for Meteora's premier token launchpad with trending launches and position management
  • Launch Lab: Complete Raydium LaunchLab project lifecycle management with trending launches, token verification, trading, and professional token creation
  • Conditional Trading: Sophisticated automated buy/sell orders with stop-losses, take-profits, staged entries/exits, and professional order management
  • Liquidity Pools: Professional yield farming across Orca, Meteora, Raydium with standard and concentrated liquidity strategies and position optimization

Analysis & Research Tools (Premium)

  • Solana Token Ecosystem: Comprehensive token research combining security audits, holder analysis, real-time trading data, trending insights, and rugpull detection
  • Advanced Search: Data extraction from any website, report, or online content transformed into structured, actionable intelligence
  • InfoFI: Social intelligence with influencer credibility scoring, sentiment analysis, narrative tracking, and signal filtering
  • TVL Analysis: DeFi protocol analytics with health metrics, capital flow tracking, cross-chain analysis, and token deployment insights
  • Stablecoins: Market intelligence on stablecoin ecosystems with market cap dominance, growth trends, compliance profiles, and arbitrage opportunities
  • Companies & Protocols: Protocol intelligence with security histories, fundraising data, treasury health, token unlocks, and institutional backing
  • Yield: Comprehensive yield farming with APY comparisons, performance tracking, borrowing rates, perpetual funding, and liquid staking analysis
  • Perps: Derivatives analytics with market overviews, protocol performance, volume tracking, growth analysis, and risk assessment
  • Users: User analytics with active user tracking, growth momentum, retention metrics, and ecosystem maturity assessment
  • Narratives: Crypto theme trading with narrative identification, lifecycle tracking, rotation patterns, and emerging theme discovery
  • Bridges: Cross-chain bridge analytics with volume tracking, protocol performance, and liquidity trend analysis
  • Fees & Revenue: Protocol financial intelligence with fee generation tracking, sustainability metrics, and fee-sharing opportunities
  • Coin Prices: Real-time multi-chain price data and performance tracking across any tokens with arbitrage detection
  • DEX Volumes: Comprehensive DEX analytics with market-wide volumes, chain competition data, and protocol performance metrics
  • Bitcoin Tools: Complete Bitcoin assets analysis for Inscriptions, Runes, BRC-20s, Stamps, Alkanes, and rare sats
  • ETF Data: Institutional crypto intelligence tracking Bitcoin/Ethereum ETF assets, flows, market share, and Grayscale holdings
  • Indices Data: Advanced derivatives intelligence with futures basis analysis, whale positioning, and market health indicators
  • Spot Data: Margin and premium analytics with Coinbase institutional premium, Bitfinex positioning, and cross-exchange rates
  • Options Data: Comprehensive options analytics with open interest tracking, implied volatility analysis, and cross-exchange comparisons
  • On-Chain Data: Exchange flow analytics with asset holdings, balance distributions, and transfer pattern analysis
  • Whale Analytics: Hyperliquid whale intelligence with real-time alerts on million-dollar positions and smart money tracking
  • Platform Features: Visual feedback, technical analysis visualization, and miscellaneous platform features

Get tools list

To get a list of available tools, you can use the following API endpoint:

const tools = await client.getTools();
console.log('Available tools:', tools);

ToolCategory Type

The getTools() method returns an array of ToolCategory objects. Each tool category represents a collection of related functionality:

interface ToolCategory {
  /** Unique identifier for the tool category */
  id: string;
  /** Human-readable name of the tool category */
  title: string;
  /** Detailed description of what this tool category provides */
  description: string;
  /** Example use cases or queries that would trigger this tool category */
  examples: string[];
  /** UI color theme for this category */
  type: "analyst" | "trader";
  /** Whether this tool category requires a premium subscription */
  premium?: boolean;
}

Example Response

const tools = await client.getTools();
// Example tool categories you might receive:

[
  {
    id: "standard-tools",
    title: "Standard Tools",
    description: "Core trading toolbox with token research, contract addresses, strategic pricing, swaps, transfers, and persistent memory",
    examples: [
      "What's the contract address for SOL?",
      "Help me swap 1 SOL for USDC",
      "Remember my preferred slippage settings"
    ],
    type: "trader"
  },
  {
    id: "solana-token-ecosystem",
    title: "Solana Token Ecosystem",
    description: "Comprehensive token research combining security audits, holder analysis, real-time trading data, trending insights, and rugpull detection",
    examples: [
      "Analyze the security of this token",
      "Show me holder distribution for BONK",
      "Is this token a potential rugpull?"
    ],
    type: "analyst",
    premium: true
  },
  {
    id: "info-fi",
    title: "InfoFI",
    description: "Social intelligence with influencer credibility scoring, sentiment analysis, narrative tracking, and signal filtering",
    examples: [
      "What are crypto influencers saying about Bitcoin?",
      "Track sentiment around this narrative",
      "Score this influencer's credibility"
    ],
    type: "analyst",
    premium: true
  }
]

Using Tool Categories

You can filter and select specific tool categories when making requests:

// Get all available tool categories
const allTools = await client.getTools();

// Filter for trader-focused tools
const traderTools = allTools.filter(tool => tool.type === "trader");

// Filter for free tools only
const freeTools = allTools.filter(tool => !tool.premium);

// Use specific tool categories in your chat requests
const response = await client.chat([
  { role: 'user', content: 'Analyze trending Solana tokens' }
], { 
  vaultId: 'my-vault',
  selectedToolCategories: ['solana-token-ecosystem', 'standard-tools']
});

Multiple Tool Execution

The API can execute multiple tools in a single conversation. For example, you can ask for trending tokens and a rugcheck in the same request:

// Request that uses multiple tools
const response = await client.chat([
  { role: 'user', content: 'Check trending tokens and get token details for the top one' }
], { 
  vaultId: 'my-vault',
  selectedToolCategories: ['standard-tools']
});

// All tool calls are available in the response
console.log(`Number of tools used: ${response.toolCalls.length}`);

// Access individual tool calls by index or filter by tool name
const rugcheckCalls = response.toolCalls.filter(tool => tool.name === 'rugcheck');
const trendingCalls = response.toolCalls.filter(tool => tool.name === 'birdeye-trending');

// Tool results are also available
console.log('Tool results:', response.toolResults);

For streaming interfaces, you can observe multiple tool calls in real-time:

for await (const chunk of client.chatStream({ 
  messages: [{ role: 'user', content: 'Check trending tokens and get token details for the top one' }],
  vaultId: 'my-vault',
  selectedToolCategories: ['standard-tools'],
  processChunks: true 
})) {
  if (chunk.type === 'tool_call') {
    console.log(`Tool called: ${chunk.value.toolCallId} (${chunk.value.toolName})`);
    // You can track which tools are being used
  } else if (chunk.type === 'tool_result') {
    console.log(`Tool result received for: ${chunk.value.toolCallId}`);
    // Match results to their corresponding tool calls
  }
}

Accessing Tool Data

// Get a complete response with tool calls and results
const response = await client.chat([
  { role: 'user', content: 'What is the current price of SOL in USD?' }
], {
  vaultId: 'my-vault',
  selectedToolCategories: ['standard-tools']
});

// Tool calls and results are available in the response
console.log('Tools called:', response.toolCalls);
console.log('Tool results:', response.toolResults);

For streaming interfaces, you can observe tool activity in real-time:****

for await (const chunk of client.chatStream({ 
  messages: [{ role: 'user', content: 'Check the price of SOL in USD' }],
  vaultId: 'my-vault',
  selectedToolCategories: ['standard-tools'],
  processChunks: true 
})) {
  if (chunk.type === 'tool_call') {
    console.log('Agent is using tool:', chunk.value.name);
  } else if (chunk.type === 'tool_result') {
    console.log('Tool returned:', chunk.value);
  }
}

📎 Image Attachments

The SDK supports attaching images to your prompts, allowing the AI agent to analyze visual content like charts, token logos, screenshots, or any other images relevant to your crypto queries.

Uploading Images

Use the uploadFile method to upload an image and get an attachment object:

// Upload an image file
const attachment = await client.uploadFile('./chart.png');

// Use the attachment in your chat request
const response = await client.chat([
  { role: 'user', content: 'Analyze this price chart and give me your insights' }
], {
  vaultId: 'my-vault',
  attachments: [attachment]
});

Supported Image Formats

The SDK supports common image formats:

  • PNG (.png)
  • JPEG (.jpg, .jpeg)
  • GIF (.gif)
  • WebP (.webp)

Note: The SDK uses intelligent MIME type detection based on file content, not just file extensions. This means images without extensions or with incorrect extensions will still be properly identified.

File Size Limits

  • Maximum file size: 5MB
  • Files are automatically validated before upload

Using Attachments with Streaming

Attachments work with all SDK modes including streaming:

// Upload image first
const chartImage = await client.uploadFile('./trading-chart.png');

// Stream response with image analysis
for await (const chunk of client.chatStream({
  messages: [{ role: 'user', content: 'What do you see in this chart?' }],
  vaultId: 'my-vault',
  attachments: [chartImage],
  processChunks: true
})) {
  if (chunk.type === 'text') {
    process.stdout.write(chunk.value);
  }
}

Multiple Images

You can attach multiple images to a single prompt:

// Upload multiple images
const [chart1, chart2, screenshot] = await Promise.all([
  client.uploadFile('./btc-chart.png'),
  client.uploadFile('./eth-chart.png'),
  client.uploadFile('./dex-screenshot.png')
]);

// Send all images together
const response = await client.chat([
  { role: 'user', content: 'Compare these charts and analyze the trading interface' }
], {
  vaultId: 'my-vault',
  attachments: [chart1, chart2, screenshot]
});

Custom File Names

You can provide a custom filename when uploading:

// Upload with custom name
const attachment = await client.uploadFile('./temp/img12345.tmp', 'price-chart.png');
// attachment.name will be 'price-chart.png' instead of 'img12345.tmp'

Images Without Extensions

The SDK can handle images without file extensions by detecting the format from the file content:

// Upload an image without extension (MIME type auto-detected)
const attachment = await client.uploadFile('./screenshots/latest');
// The SDK will detect if it's PNG, JPEG, etc. from the file content

Attachment Object Structure

The uploadFile method returns an Attachment object:

interface Attachment {
  /** The name of the file */
  name: string;
  /** MIME type of the file (auto-detected from content) */
  contentType: string;
  /** URL to the uploaded file */
  url: string;
}

// Example attachment object:
{
  name: "chart.png",
  contentType: "image/png",  // Detected from file content, not extension
  url: "https://api.agenthustle.ai/uploads/abc123/chart.png"
}

Error Handling

The upload method includes comprehensive error handling:

try {
  const attachment = await client.uploadFile('./image.png');
} catch (error) {
  // Possible errors:
  // - File not found
  // - File too large (>5MB)
  // - Unsupported file type (not an image)
  // - Network/upload errors
  console.error('Upload failed:', error.message);
}

🧪 Testing Your Integration

The SDK supports an override pattern for easy testing without making real API calls:

// Mock stream results for testing
const mockResponse = await client.chat(
  [{ role: 'user', content: 'Test message' }],
  { vaultId: 'test-vault' },
  async () => ({ content: 'Mocked response', toolCalls: [] })
);

// Mock stream chunks for testing UI
for await (const chunk of client.chatStream(
  { messages: [...], vaultId: 'test-vault' },
  async function* () {
    yield { type: 'text', value: 'Mocked ' };
    yield { type: 'text', value: 'streaming ' };
    yield { type: 'text', value: 'response' };
    yield { type: 'finish', value: { reason: 'stop' } };
  }
)) {
  // Process mocked chunks in tests
}

🔐 Security

  • Never hardcode API keys in your client code
  • Use environment variables for sensitive credentials
  • For browser applications, proxy requests through your backend

📚 Usage in Different Environments

Node.js (CommonJS)

const { HustleIncognitoClient } = require('hustle-incognito');

const client = new HustleIncognitoClient({ apiKey: process.env.HUSTLE_API_KEY });
// Use the client...

Node.js (ESM) / Modern JavaScript

import { HustleIncognitoClient } from 'hustle-incognito';

const client = new HustleIncognitoClient({ apiKey: process.env.HUSTLE_API_KEY });
// Use the client...

TypeScript

import { HustleIncognitoClient, ChatMessage, ToolCategory } from 'hustle-incognito';

const client = new HustleIncognitoClient({ apiKey: process.env.HUSTLE_API_KEY });
const messages: ChatMessage[] = [{ role: 'user', content: 'Hello' }];

// Get available tool categories
const tools: ToolCategory[] = await client.getTools();
console.log('Available tools:', tools);

// Use the client...

Next.js (App Router)

// app/api/chat/route.ts
import { HustleIncognitoClient } from 'hustle-incognito';

export async function POST(req: Request) {
  const { message, vaultId } = await req.json();

  const client = new HustleIncognitoClient({
    apiKey: process.env.HUSTLE_API_KEY!
  });

  const response = await client.chat(
    [{ role: 'user', content: message }],
    { vaultId: vaultId || 'default' }
  );

  return Response.json({ content: response.content });
}

Next.js (Pages Router)

// pages/api/hustle.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { HustleIncognitoClient } from 'hustle-incognito';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const client = new HustleIncognitoClient({
    apiKey: process.env.HUSTLE_API_KEY!
  });

  const response = await client.chat(
    req.body.messages,
    { vaultId: req.body.vaultId || 'default' }
  );

  res.status(200).json(response);
}

Express Server

import express from 'express';
import { HustleIncognitoClient } from 'hustle-incognito';

const app = express();
app.use(express.json());

const client = new HustleIncognitoClient({
  apiKey: process.env.HUSTLE_API_KEY
});

// Non-streaming endpoint
app.post('/api/chat', async (req, res) => {
  const { message, vaultId } = req.body;

  const response = await client.chat(
    [{ role: 'user', content: message }],
    { vaultId: vaultId || 'default' }
  );

  res.json({ content: response.content });
});

// Streaming endpoint with Server-Sent Events
app.post('/api/chat/stream', async (req, res) => {
  const { message, vaultId } = req.body;

  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  for await (const chunk of client.chatStream({
    messages: [{ role: 'user', content: message }],
    vaultId: vaultId || 'default',
    processChunks: true
  })) {
    if (chunk.type === 'text') {
      res.write(`data: ${JSON.stringify({ text: chunk.value })}\n\n`);
    }
  }

  res.end();
});

app.listen(3000, () => console.log('Server running on port 3000'));

Browser (via bundler)

import { HustleIncognitoClient } from 'hustle-incognito';

// NOTE: For security, you should proxy API requests through your backend
// rather than including API keys in client-side code
const client = new HustleIncognitoClient({ 
  apiKey: 'YOUR_API_KEY', // Better to fetch this from your backend
  hustleApiUrl: '/api/hustle-proxy' // Proxy through your backend
});

// Use the client...

🛠️ Contributing & Development

Want to contribute to the SDK? Here's how to get started:

Setup

# Clone the repository
git clone https://github.com/EmblemCompany/hustle-incognito.git
cd hustle-incognito

# Install dependencies
npm install

# Build the SDK
npm run build

Testing

# Run all tests
npm test

# Watch mode for development
npm run test:watch

Build System

The SDK uses a dual package approach to support both ESM and CommonJS:

# Build both versions (ESM + CommonJS)
npm run build

# Build individually
npm run build:esm
npm run build:cjs

Running Examples

See the Examples README for instructions on running the example applications.

Publishing

# Prepare for publishing (runs tests, lint, and build)
npm version patch # or minor, or major
npm publish

📄 License

MIT