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

@guru-fund/sdk

v0.2.11

Published

Guru Protocol SDK — quote + transaction builders for on-chain managed funds.

Downloads

1,788

Readme

@guru-fund/sdk

Quote + transaction builders for Guru Protocol managed funds.

The SDK is submission-agnostic: every quote returns a txData: TransactionRequest plus a decodeLogs(logs) closure. You sign and broadcast yourself. Simulation is a caller-supplied callback so the SDK never reaches Alchemy / Tenderly / your provider of choice directly.

Install

npm install @guru-fund/sdk ethers

Peer-quality runtime deps: ethers (>=6.15) and zod. Zero internal / proprietary deps — the SDK is meant to be standalone-publishable.

Constructor

import { GuruProtocol } from '@guru-fund/sdk'

const protocol = new GuruProtocol({
    rpcUrl: 'https://mainnet.infura.io/v3/<key>',
    chainId: 1, // mainnet (1), base (8453), and Robinhood (4663) are supported
})

new GuruProtocol({ rpcUrl, chainId }) is the only required surface. The constructor:

  • Builds an internal JsonRpcProvider(rpcUrl). Do not pass a provider in.
  • Resolves the Guru Protocol contract addresses from the SDK's vendored registry. Do not pass contracts in.
  • Throws UnsupportedChainError for any chain outside { 1, 8453, 4663 }.

Optional override slots (GuruProtocolOptions): simulator, getSwapFeePercentage, getPriceUsd1e18, veloraEndpoint, getPath. Each has a sensible default — see the no-sim pattern and the Alchemy pairing example below.

Quote methods

Every quote method returns bigints natively. Stringify at your wire boundary if you serialize to JSON.

| Method | Returns | | -------------------------- | ------------------------------------------------------------------------------ | | protocol.quoteDeposit | { sharesOutMin, extCalls, fees, referrerFeeBps, …, txData, decodeLogs } | | protocol.quoteWithdrawal | { proceeds, extCalls, routing, referrerFeeBps, …, txData, decodeLogs } | | protocol.quoteTrade | Route + txData for one-off manager trade execution | | protocol.quoteHarvest | { extCalls, harvestableFraction, managementFee, txData, decodeLogs } | | protocol.quoteRebalance | { extCalls, trades, cumulativeSlippageBps, txData, decodeLogs, emptyReason } |

const quote = await protocol.quoteDeposit({
    ledger: '0xe93f393b987247530a94cef205070868924797e7',
    account: '0xUserAddress',
    coin: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
    amount: 1_000_000n, // 1 USDC (6 decimals)
    referrerFeeBps: 0n, // see "Referrer fee policy" below
})

// 1. Submit `quote.txData` from `account`. Approvals are out-of-band.
// 2. After execution (or sim), pipe receipt logs through quote.decodeLogs:
const decoded = quote.decodeLogs(receipt.logs)
//   { expectedShares: 1234n } | null

Referrer fee policy

referrerFeeBps is a required input on deposit / withdrawal. The SDK range-validates 0 <= referrerFeeBps <= MAX_BPS (=10_000n) but does NOT derive it. Policies that depend on server-side data (governance-token holdings, fund composition, holdings checks) belong outside the SDK — pass the resolved bps in.

slippageSettings on deposit / withdrawal / harvest / rebalance are optional per-token e3 slippage overrides ("500" = 0.5%). They become especially important in no-sim mode, where callers may want explicit bounds instead of the router defaults.

Transaction builders

Static, synchronous calldata encoders. Use directly when you already know the deposit / withdraw / harvest shape and want a TransactionRequest without going through the quote.

const tx = GuruProtocol.buildDepositTx({
    controller, ledger, coin, amount, sharesOutMin, extCalls,
    referrerFeeBps, from,
})
GuruProtocol.buildWithdrawTx({ controller, ledger, coin, amountIn, extCalls, …, from })
GuruProtocol.buildHarvestTx({ controller, ledger, coin, isManagementFeeEligible, extCalls, …, from })

The quote methods call these builders internally — single source of truth for calldata shape.

Approvals are NOT bundled into deposit txData — handle them yourself before submitting the quote's txData.

No-sim pattern

The default simulator callback returns { success: false }, which causes the Velora primary router to fall through to the caller-supplied slippage without doing on-chain "highest-passing-amount" search. This is the zero-config path — quotes still work, but they are degraded for real execution quality because the SDK cannot validate route executability against current liquidity conditions.

const protocol = new GuruProtocol({ rpcUrl, chainId })
// simulator defaults to noop — callers get caller-supplied-slippage quotes

Alchemy sim pairing example

Inject a custom simulator to recover the search behavior. Below uses Alchemy Bundle Simulation; substitute Tenderly / your own provider with the same callback shape.

import { GuruProtocol, type SwapSimulator } from '@guru-fund/sdk'
import { Alchemy, Network } from 'alchemy-sdk'

const alchemy = new Alchemy({
    apiKey: process.env.ALCHEMY_API_KEY!,
    network: Network.ETH_MAINNET,
})

const simulator: SwapSimulator = async ({
    chainId,
    from,
    to,
    callData,
    blockNumber,
    account,
    amountIn,
    tokenIn,
}) => {
    try {
        const bundle = await alchemy.transact.simulateExecutionBundle(
            [
                // optional ERC20 prelude funding the controller
                {
                    from: account,
                    to: tokenIn,
                    value: '0x0',
                    data: encodeApprove(to, amountIn),
                },
                { from, to, value: '0x0', data: callData },
            ],
            { blockNumber: `0x${blockNumber.toString(16)}` }
        )
        const target = bundle[bundle.length - 1]
        return {
            success: !target.error && !target.revertReason,
            revertMessage: target.revertReason ?? target.error?.message,
        }
    } catch (err) {
        return { success: false, revertMessage: String(err) }
    }
}

const protocol = new GuruProtocol({ rpcUrl, chainId, simulator })

SimulateSwapParams and SimulateSwapResult are exported types — the SDK will only ever call your callback with the documented shape.

Custom routing

By default the SDK fetches swap paths from Velora's DEX aggregator API. You might override this if Velora changes endpoints, you have an API key for a private instance, or you want to plug in a different routing backend entirely:

// Just change the endpoint
const protocolWithCustomEndpoint = new GuruProtocol({
    rpcUrl,
    chainId,
    veloraEndpoint: 'https://custom-velora.example/swap',
})

// Full custom path logic
import type { PathFetcher } from '@guru-fund/sdk'

const getPath: PathFetcher = async ({ chainId, dex, tokenIn, tokenOut }) => {
    // your routing backend — return CachedPath or false
}

const protocolWithCustomPath = new GuruProtocol({ rpcUrl, chainId, getPath })

PathFetcher, GetPathParams, and CachedPath are exported types.

Decoding receipts

decodeLogs(logs) is a closure baked into each quote result. It reads the contract event ABIs the SDK already has, so you don't have to assemble them yourself. Returns null on miss (event not present) — pair it with a sensible fallback in your code.

const tx = await wallet.sendTransaction(quote.txData)
const receipt = await tx.wait()
const decoded = quote.decodeLogs(receipt!.logs) ?? {
    expectedShares: quote.sharesOutMin, // sensible fallback
}

Errors

  • UnsupportedChainError — thrown by the constructor on chainId outside { 1, 8453, 4663 }.
  • z.ZodError — thrown by quote methods on malformed inputs (zod schema at the SDK boundary parses every quote method's input).
  • SdkError — internal errors (e.g., EVENT_NOT_FOUND from the receipt parser, NETWORK_NOT_SUPPORTED from the pool helper).
  • Plain Error — semantic invariants like "coin is not a supported stablecoin", "toll not applicable", "target weights do not sum to UNIT".

License

MIT.