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

@shuriken/sdk-ts

v0.13.0

Published

TypeScript SDK for the Shuriken API (REST + WebSocket)

Downloads

699

Readme

@shuriken/sdk-ts

npm

TypeScript SDK for the Shuriken API.

Status: Early development — API surface may change.

Install

npm install @shuriken/sdk-ts

Quick start

For runnable examples, see Shuriken Quickstart TS

import { createShurikenClient } from '@shuriken/sdk-ts'

const client = createShurikenClient({
  apiKey: process.env.SHURIKEN_API_KEY!,
})

// HTTP — works immediately, no connection step
const token = await client.tokens.get('solana:So11111111111111111111111111111111111111112')
console.log(token.name, token.symbol)

// WebSocket — call connect() first, then subscribe to streams
await client.ws.connect()

client.ws.subscribe('svm.token.swaps', { tokenAddress: 'So1111...' }, (event) => {
  console.log('Swap:', event.priceUsd, event.sizeSol)
})

Tokens

// Search tokens
const results = await client.tokens.search({ q: 'bonk', chain: 'solana' })

// Get token metadata
const token = await client.tokens.get('solana:So111...')

// Batch lookup (up to 100)
const batch = await client.tokens.batch({ tokens: ['solana:So111...', 'solana:EPjF...'] })

// Price
const price = await client.tokens.getPrice('solana:So111...')

// OHLCV chart data
const chart = await client.tokens.getChart({
  tokenId: 'solana:So111...',
  resolution: '1h',
  count: 50,
})

// Trading stats (volume, txns, unique traders, price change)
const stats = await client.tokens.getStats('solana:So111...')

// Liquidity pools
const pools = await client.tokens.getPools('solana:So111...')

Swap

// Get a quote
const quote = await client.swap.getQuote({
  chain: 'solana',
  inputMint: 'So11111111111111111111111111111111111111112',
  outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  amount: '1000000000', // in base units (lamports)
  slippageBps: 100,
})

// Managed execution (Shuriken signs & submits)
const status = await client.swap.execute({
  chain: 'solana',
  inputMint: 'So111...',
  outputMint: 'EPjF...',
  amount: '1000000000',
  walletId: 'w_123',
})

// Build unsigned transaction (for self-signing)
const tx = await client.swap.buildTransaction({
  chain: 'solana',
  inputMint: 'So111...',
  outputMint: 'EPjF...',
  amount: '1000000000',
  walletAddress: '7xKX...',
})

// Submit a signed transaction
const submitted = await client.swap.submitTransaction({
  chain: 'solana',
  signedTransaction: 'base64...',
  walletAddress: '7xKX...',
})

// Poll execution status
const result = await client.swap.getStatus('task_id')

// EVM approval helpers
const spender = await client.swap.getApproveSpender(8453) // Base
const allowance = await client.swap.getApproveAllowance({
  chainId: 8453,
  tokenAddress: '0xtoken...',
  walletAddress: '0xwallet...',
})

Portfolio

// Cross-chain balances
const balances = await client.portfolio.getBalances({ chain: 'solana' })

// Trade history
const trades = await client.portfolio.getHistory({ chain: 'solana', limit: 50 })

// PnL summary
const pnl = await client.portfolio.getPnl({ timeframe: '7d' })

// Open positions with PnL
const positions = await client.portfolio.getPositions({ chain: 'solana' })

Account

// User profile
const me = await client.account.getMe()

// Wallets
const wallets = await client.account.getWallets()

// Agent key usage and constraints
const usage = await client.account.getUsage()

// Trade settings
const settings = await client.account.getSettings()
await client.account.updateSettings(settings)

// Enable multisend (durable nonce) on a Solana wallet
const { taskId } = await client.account.enableMultisend('wallet-id')

Trigger orders

// Create a trigger order
const order = await client.trigger.create({
  chain: 'solana',
  inputToken: 'So111...',
  outputToken: 'EPjF...',
  amount: '1000000000',
  walletId: 'w_123',
  triggerMetric: 'price_usd',
  triggerDirection: 'above',
  triggerValue: '0.001',
})

// List orders (cursor-paginated)
const orders = await client.trigger.list({ limit: 50 })

// Get order details
const detail = await client.trigger.get('order_id')

// Cancel
await client.trigger.cancel('order_id')

Wallet groups

// List groups (optional chain filter)
const groups = await client.walletGroups.list()
const svmGroups = await client.walletGroups.list({ chain: 'svm' })

// Create empty / pre-populated
const empty = await client.walletGroups.create({ name: 'treasury', chain: 'svm' })
const seeded = await client.walletGroups.create({
  name: 'snipers',
  chain: 'svm',
  walletIds: ['wallet_1', 'wallet_2'],
})

// Atomically generate N fresh wallets and a group containing them
// (single transaction — no orphans on partial failure)
const generated = await client.walletGroups.createWithWallets({
  name: 'fresh-treasury',
  chain: 'svm',
  walletCount: 4,
})

// Membership management
await client.walletGroups.addWallets(group.groupId, { walletIds: ['w3'] })
await client.walletGroups.removeWallets(group.groupId, { walletIds: ['w3'] })
await client.walletGroups.reorderWallets(group.groupId, {
  walletIds: ['w2', 'w1'], // must equal current membership in new order
})

// Move a wallet into / between groups
await client.walletGroups.moveWallet('wallet_1', { toGroupId: group.groupId })

// Rename / delete
await client.walletGroups.update(group.groupId, { name: 'renamed' })
await client.walletGroups.delete(group.groupId) // idempotent

Scope: each endpoint accepts either read:wallets / write:wallets or the focused manage:wallet-groups scope. A treasury-management key with only manage:wallet-groups can do full group CRUD without granting the broader wallet-address read surface.

Trade suggestions

Agents post advisory trade ideas to the user; the user acks (executes) or dismisses them from the terminal / tg-bot — those flows are session-only and not exposed on the SDK. Lifecycle states (OPEN | ACTED | DISMISSED | EXPIRED) are derived server-side from timestamps — clients should treat state as read-only.

// Post a new suggestion (requires `suggest:trade` scope)
const suggestion = await client.suggestions.create({
  side: 'BUY',
  networkId: 'SOL',
  asset: 'So11111111111111111111111111111111111111112',
  rationale: 'Funding flipped positive after a flush; reclaim of yesterdays range.',
  amountInUsd: 250,
  confidence: 'MEDIUM',
})

// List suggestions (defaults to OPEN; pass `state: 'ALL'` for everything).
// The user's ack / dismiss decisions surface here as `state` plus the
// `actedAt` / `dismissedAt` / `dismissReason` / `linkedTaskId` fields.
const { suggestions, nextCursor } = await client.suggestions.list({
  state: 'OPEN',
  limit: 50,
})

Wallet archive lifecycle

Archive, unarchive, and bulk-archive wallets. Archived wallets are excluded from trading but their history is preserved. All endpoints require the write:wallets scope.

// Archive a single wallet
const { wallet, clearedDefault } = await client.wallets.archive('wallet-id')
// clearedDefault is true if this wallet was the account default

// Unarchive
const { wallet: restored } = await client.wallets.unarchive('wallet-id')

// Bulk-archive up to 100 wallets in one call
const { results } = await client.wallets.bulkArchive({
  walletIds: ['w1', 'w2', 'w3'],
})
for (const entry of results) {
  console.log(entry.walletId, entry.status) // 'archived' | 'already_archived'
}

Wallet-to-wallet transfers

Send tokens between wallets or retire (drain + archive) a source wallet. Both endpoints require the transfer:write scope.

// Send SOL from one wallet to another (blocks until confirmed by default)
const result = await client.transfers.send({
  fromWalletId: 'w_from',
  toWalletId: 'w_to',
  token: 'SOL',
  amount: '1000000', // raw base units (lamports)
  chain: 'SVM',
})
console.log(result.status, result.transaction?.hash)

// EVM transfer (chainId required for EVM)
await client.transfers.send({
  fromWalletId: 'w_evm_from',
  toWalletId: 'w_evm_to',
  token: 'USDC',
  amount: '1000000', // 1 USDC (6 decimals)
  chain: 'EVM',
  chainId: 8453, // Base
})

// Fire-and-forget — get taskId immediately, poll for status
const { taskId } = await client.transfers.send({
  fromWalletId: 'w_from',
  toWalletId: 'w_to',
  token: 'SOL',
  amount: '500000',
  chain: 'SVM',
  awaitResult: false,
})
const status = await client.tasks.getStatus(taskId)

// Retire a wallet: drain full balance then archive the source
const retire = await client.transfers.retireWallet({
  fromWalletId: 'w_old',
  toWalletId: 'w_new',
  token: 'SOL',
  chain: 'SVM',
})
// retire.willArchiveOnSuccess is always true

SplitNOW splits

Cross-chain split using SplitNOW. Two-step flow: plan then execute. Requires split:plan and split:execute scopes respectively.

// Step 1: plan — quote a split and get a planId (valid 60 seconds)
const plan = await client.splits.plan({
  sourceWalletId: 'w_src',
  destinationGroupId: 'grp_abc', // or pass destinations[] with pctBips
  fromAmount: '0.16',
  fromAsset: 'sol',
})
console.log(plan.summary)   // human-readable description — review before executing
console.log(plan.warnings)  // non-fatal warnings (low liquidity, etc.)

// Step 2: execute — submit within expiresInSeconds (60s)
const { taskId, splitnowOrderId } = await client.splits.execute({
  planId: plan.planId,
  agentComment: 'weekly rebalance',
})
const status = await client.tasks.getStatus(taskId)

// Alternatively, supply explicit destination weights instead of a group
const explicitPlan = await client.splits.plan({
  sourceWalletId: 'w_src',
  destinations: [
    { walletId: 'w1', pctBips: 6000 }, // 60 %
    { walletId: 'w2', pctBips: 4000 }, // 40 %
  ],
  fromAmount: '1.0',
  fromAsset: 'eth',
})

Perps

// Markets
const markets = await client.perps.getMarkets()
const btc = await client.perps.getMarket('BTC')

// Account state
const account = await client.perps.getAccount()
const fees = await client.perps.getFees()

// Positions & orders
const positions = await client.perps.getPositions()
const openOrders = await client.perps.getOrders({ coin: 'BTC' })

// Place an order
const result = await client.perps.placeOrder({
  walletId: 'w_123',
  coin: 'BTC',
  isBuy: true,
  sz: '0.1',
  limitPx: '60000',
  orderType: 'limit',
})

// Modify / cancel
await client.perps.modifyOrder({ walletId: 'w_123', coin: 'BTC', isBuy: true, sz: '0.2', limitPx: '61000', oid: 456, orderType: 'limit' })
await client.perps.cancelOrder({ walletId: 'w_123', coin: 'BTC', oid: 456 })

// Batch modify
await client.perps.batchModifyOrders({
  walletId: 'w_123',
  modifications: [
    { coin: 'BTC', isBuy: true, sz: '0.2', limitPx: '61000', oid: 456, orderType: 'limit' },
  ],
})

// Close position / adjust margin / update leverage
await client.perps.closePosition({ walletId: 'w_123', coin: 'BTC', percentage: 100 })
await client.perps.updateMargin({ walletId: 'w_123', coin: 'BTC', amount: '500' })
await client.perps.updateLeverage({ walletId: 'w_123', coin: 'BTC', leverage: 20, isCross: true })

// History
const fills = await client.perps.getFills({ startTime: Date.now() - 86400000 })
const funding = await client.perps.getFunding({ startTime: Date.now() - 86400000 })

WebSocket streams

| Stream | Filter | Description | |--------|--------|-------------| | svm.token.swaps | tokenAddress | Solana token swap events | | svm.token.poolInfo | tokenAddress | Solana token/pool info updates | | svm.token.balances | tokenAddress | Token holder balance changes | | svm.token.distributionStats | tokenAddress | Token distribution analytics | | svm.token.holderStats | tokenAddress | Holder count analytics | | svm.wallet.nativeBalance | walletAddress | SOL balance changes | | svm.wallet.tokenBalances | walletAddress | SPL token balance changes | | svm.bondingCurve.creations | — | New bonding curve tokens | | svm.bondingCurve.graduations | — | Bonding curve graduations | | evm.token.swaps | chainId, tokenAddress | EVM token swap events | | evm.token.poolInfo | chainId, tokenAddress | EVM token/pool info updates | | evm.token.balances | chainId, tokenAddress | EVM token holder balance changes | | evm.wallet.nativeBalance | walletAddress | Native balance changes (ETH/BNB) | | evm.wallet.tokenBalances | walletAddress | ERC-20 token balance changes | | alpha.signalFeedGlobal | — | Global signal feed updates (broadcast) | | alpha.signalFeedPersonal | — | Per-user personal signal feed updates | | alpha.signalFeedProfile | profileId | Per-profile signal feed updates | | alpha.signalFeedNamed | feedId | Named signal feed updates | | alpha.personal | — | Personal alpha channel (chat messages, call references, feed messages) | | portfolio.notifications | — | Per-user transaction & task lifecycle notifications | | automation.updates | — | Per-user automation / strategy lifecycle updates |

Authentication

Get an API key from the Shuriken Agents dashboard. The SDK uses agent keys (sk_...) for authentication.

License

MIT