Packages & surfaces
ShroudFi ships as nine TypeScript packages plus an HTTP / REST API. Pick the surface that matches your runtime — the on-chain guarantees are identical underneath. Wagmi/viem compatible throughout.
All nine packages are live on npm at v0.1. The SDK is viem-native end to end — if your agent already uses viem or wagmi, the install is one line per package.
@shroud-fi/core
npm · v0.1secp256k1 identity layer. Derives a stealth meta-address from a master seed, encodes / decodes the st:base:0x… wire format, and exposes the EIP-5564 / 6538 primitives every other package builds on.
$ npm i @shroud-fi/core viemExports
| Symbol | Signature | Description |
|---|---|---|
| deriveAgentIdentity | (seed: Hex) => AgentIdentity | Domain-separated identity derivation from a master seed. Same seed = same meta-address across SDK + MCP + REST. |
| encodeMetaAddress | (id: AgentIdentity) => `st:base:0x${string}` | Encode spend + scan public keys into the canonical wire format. |
| decodeMetaAddress | (s: string) => MetaAddressKeys | Parse st:base:0x… into spend & scan pubkeys. |
| AgentIdentity | type | { spendPub, scanPub, metaAddressEncoded, deriveSpendingKey, deriveScanningKey } |
@shroud-fi/payments
npm · v0.1Sender-side stealth payment construction. Derives a fresh stealth address per payment, computes the EIP-5564 announcement, broadcasts ETH or ERC-20, and resolves recipient meta-addresses via the on-chain ERC-6538 registry.
$ npm i @shroud-fi/paymentsExports
| Symbol | Signature | Description |
|---|---|---|
| sendETHPayment | (args) => Promise<PaymentReceipt> | Derive stealth, announce, transfer ETH — one call. |
| sendERC20Payment | (args) => Promise<PaymentReceipt> | Same shape for ERC-20. USDC on Base mainnet is the v1 target. |
| sweepETH · sweepERC20 | (args) => Promise<TxHash> | Direct sweep from stealth address to destination. Fee-free. |
| lookupMetaAddress | (transport, addr) => Promise<MetaLookup> | Resolve a wallet’s registered stealth meta-address via ERC-6538. |
| RecipientNotOnboardedError | class | Thrown when a recipient has no published meta-address. Structured .wallet field for privacy-safe UX. |
@shroud-fi/scanning
npm · v0.1Receiver-side detection. Scans a block range for EIP-5564 announcements, pre-filters by one-byte view tag (~99.6% reduction), then derives the matching stealth private key for each surviving candidate.
$ npm i @shroud-fi/scanningExports
| Symbol | Signature | Description |
|---|---|---|
| createScanner | (transport, identity) => Scanner | Scanner bound to an agent identity + transport. |
| scanner.scan | (range) => Promise<DetectedPayment[]> | Detect inbound payments in a block range; returns stealth private key per hit. |
| DetectedPayment | type | { stealthAddress, stealthPrivateKey, ephemeralPubKey, viewTag, blockNumber, logIndex } |
@shroud-fi/relayer
npm · v0.1Gasless sweep client. ERC-20 sweeps via EIP-2612 permit + ERC-2771 metaTx (Gelato 1Balance forwarder). Native ETH via EIP-7702 delegated code on a relayer EOA. Recipient pays a 1% fee at sweep time; direct sweeps via @shroud-fi/payments remain fee-free.
$ npm i @shroud-fi/relayerExports
| Symbol | Signature | Description |
|---|---|---|
| relayedSweepERC20 | (transport, pk, token, dest, relayer) => Promise<RelayerSweepReceipt> | Gasless ERC-20 sweep via Gelato. Receipt has no plaintext amount field. |
| relayedSweepETH | (args) => Promise<RelayedEthSweepReceipt> | Gasless ETH sweep via EIP-7702 delegated relayer. |
| StealthAddressEmptyError | class | Distinguishes “already swept” from wallet insufficiency. |
@shroud-fi/transport
npm · v0.1Pluggable I/O. Wraps viem clients for RPC, contract calls, and event subscription. Carries the canonical Base mainnet deployment manifest — swap in your own RPC URL or a private mempool transport without touching the rest of the SDK.
$ npm i @shroud-fi/transport viemExports
| Symbol | Signature | Description |
|---|---|---|
| createTransport | (cfg: TransportConfig) => Transport | Build a transport from chain, rpcUrl, or an existing viem client. |
| getDeployment | (chainId: number) => DeploymentManifest | Lookup verified contract addresses by chain ID. Base mainnet (8453). |
| ShroudFiStealthAbi · RegistrarAbi · RelayerAbi · EthRelayerAbi | const | Typed ABIs for every deployed contract. |
@shroud-fi/agent-runtime
npm · v0.1The high-level agent surface most projects integrate against. One createShroudAgent call composes core + payments + scanning + relayer into the four operations an agent actually performs: register, send, receive, sweep.
$ npm i @shroud-fi/agent-runtime viemExports
| Symbol | Signature | Description |
|---|---|---|
| createShroudAgent | (cfg) => Promise<ShroudAgent> | Wires deterministic identity, transport, scanner, and sweep paths. |
| agent.register | () => Promise<TxHash | 'already-registered'> | Publish the agent meta-address into the ERC-6538 registry. |
| agent.send | (to, asset, amount) => Promise<PaymentReceipt> | Send to a meta-address (privacy-native) or a wallet (SDK looks up the meta-address). |
| agent.sendToWallet | (wallet, asset, amount) => Promise<PaymentReceipt> | Wallet-input convenience path with onboarding error if the recipient isn’t registered. |
| agent.receive | (range) => Promise<DetectedPayment[]> | Detect inbound payments in a block range. |
| agent.sweep | (detection, destination, opts?) => Promise<TxHash | RelayerSweepReceipt> | Direct or relayer-routed sweep; auto-routes ERC-20 via Gelato, ETH via EIP-7702. |
import { createShroudAgent } from '@shroud-fi/agent-runtime'
const agent = await createShroudAgent(({
chain: 'base',
masterSeed: process.env.SHROUDFI_MASTER_SEED,
rpcUrl: process.env.SHROUDFI_RPC_URL,
})
await agent.register()
await agent.sendToWallet(peer, { token: USDC }, 25_000000n)@shroud-fi/x402
npm · v0.1Stealth-addressed HTTP 402. Any endpoint can issue a 402 challenge and any agent can pay it — the settlement broadcasts an EIP-3009 transferWithAuthorization into a fresh stealth address derived from the seller’s meta-address.
$ npm i @shroud-fi/x402Exports
| Symbol | Signature | Description |
|---|---|---|
| payX402 | (args) => Promise<unknown> | One-shot client. Calls a URL, signs USDC if a 402 lands, retries with X-PAYMENT, returns the unlocked body. |
| createX402Server | (cfg) => { challenge, verify } | Server-side primitives. Mint a 402 challenge or verify a payment payload before unlocking content. |
| buildX402Payment | (args) => Promise<X402PaymentEnvelope> | Lower-level sign-only flow for custom HTTP machinery. |
import { payX402 } from '@shroud-fi/x402'
const signal = await payX402(({
agent,
url: 'https://api.alpha.xyz/signal',
maxPriceUsdcAtomic: 10_000n
})@shroud-fi/compliance
npm · v0.1Operator-side viewing-key tools. Export a deterministic audit trail of every payment ever directed at an agent’s meta-address — without granting spend authority, without revealing live strategy.
$ npm i @shroud-fi/complianceExports
| Symbol | Signature | Description |
|---|---|---|
| exportViewingKey | (identity) => ViewingKeyExport | Serialize a scan-only key safe to hand to an auditor. |
| replayHistory | (transport, viewingKey, range) => Promise<DetectedPayment[]> | Reconstruct every payment ever sent to the meta-address. |
@shroud-fi/mcp-server
npm · v0.1Model Context Protocol server. Exposes the agent runtime as 9 tools any MCP-aware host can call — Claude Code, Cursor, Windsurf, Zed AI, or any custom MCP client. Stdio for local install, HTTP with EIP-191 challenge-response for shared infrastructure.
$ npm i @shroud-fi/mcp-serverTools
| Tool | Args | Purpose |
|---|---|---|
| shroud_register | — | Publish the agent’s stealth meta-address into ERC-6538. Idempotent. |
| shroud_send | to · asset · amount | Send to st:base:0x…. |
| shroud_send_to_wallet | recipient · asset · amount | Send to a plain wallet — SDK looks up the meta-address. |
| shroud_receive | fromBlock · toBlock? | Scan a block range for inbound stealth payments. |
| shroud_sweep | detection · destination · viaRelayer? | Sweep a detected stealth address (direct or gasless). |
| shroud_balance | address? · token? | Read ETH + optional ERC-20 balance. |
| shroud_status | — | Operator wallet, meta-address, chain, latest block, registration state. |
| shroud_x402_pay | url · maxPriceUsdcAtomic? | One-shot HTTP 402 client. Auto-signs USDC if a 402 lands. |
| shroud_x402_serve | op · args | Server-side x402 primitives — mint 402 challenges or verify payments. |
{
"mcpServers": {
"shroudfi": {
"command": "node",
"args": ["node_modules/@shroud-fi/mcp-server/dist/esm/bin/stdio.js"],
"env": {
"SHROUDFI_PRIVATE_KEY_FILE": "/abs/path/agent-eoa.key",
"SHROUDFI_CHAIN": "base",
"SHROUDFI_RPC_URL": "https://base-mainnet.g.alchemy.com/v2/<key>"
}
}
}
}REST API
v1 · self-hostHTTP / REST surface for any language that speaks fetch. Mirrors the MCP tool set as 7 endpoints under /v1, secured by the same EIP-191 challenge-response flow. OpenAPI 3.1 schema at /v1/openapi.json; TypeScript + Python clients ship in the repo.
$ curl https://api.shroudfi.live/v1/openapi.jsonEndpoints
| Path | Method | Purpose |
|---|---|---|
| /v1/auth/challenge | POST | Mint an EIP-191 nonce for a wallet. 5-min TTL, single-use. |
| /v1/register | POST | Publish meta-address into ERC-6538. |
| /v1/send | POST | Send to a meta-address. |
| /v1/send-to-wallet | POST | Send to a wallet via meta-address lookup. |
| /v1/payments | GET | Scan a block range for inbound payments. |
| /v1/sweep | POST | Direct or gasless sweep. |
| /v1/balance · /v1/status | GET | Operator state read-outs. |
| /v1/x402-pay · /v1/x402-serve | POST | Same x402 client + server primitives as MCP. |
# 50-line agent that buys an x402-priced signal
import httpx, json, os
from eth_account import Account
from eth_account.messages import encode_defunct
API = "https://api.shroudfi.live"
acct = Account.from_key(os.environ["AGENT_PK"])
# 1. Get a challenge.
ch = httpx.post(f"{API}/v1/auth/challenge", json={"wallet": acct.address}).json()
# 2. Sign EIP-191.
sig = acct.sign_message(encode_defunct(text=ch["message"])).signature.hex()
# 3. Pay an x402 endpoint.
res = httpx.post(f"{API}/v1/x402-pay",
headers={"x-shroudfi-wallet": acct.address,
"x-shroudfi-nonce": ch["nonce"],
"x-shroudfi-signature": "0x" + sig},
json={"url": "https://api.alpha.xyz/signal",
"maxPriceUsdcAtomic": "10000"}).json()
print(res)