@shuriken/sdk-ts
v0.13.0
Published
TypeScript SDK for the Shuriken API (REST + WebSocket)
Downloads
699
Readme
@shuriken/sdk-ts
TypeScript SDK for the Shuriken API.
Status: Early development — API surface may change.
Install
npm install @shuriken/sdk-tsQuick 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) // idempotentScope: each endpoint accepts either
read:wallets/write:walletsor the focusedmanage:wallet-groupsscope. A treasury-management key with onlymanage:wallet-groupscan 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 trueSplitNOW 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
