SDK Reference

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.1

secp256k1 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 viem

Exports

SymbolSignatureDescription
deriveAgentIdentity(seed: Hex) => AgentIdentityDomain-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) => MetaAddressKeysParse st:base:0x… into spend & scan pubkeys.
AgentIdentitytype{ spendPub, scanPub, metaAddressEncoded, deriveSpendingKey, deriveScanningKey }

@shroud-fi/payments

npm · v0.1

Sender-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/payments

Exports

SymbolSignatureDescription
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.
RecipientNotOnboardedErrorclassThrown when a recipient has no published meta-address. Structured .wallet field for privacy-safe UX.

@shroud-fi/scanning

npm · v0.1

Receiver-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/scanning

Exports

SymbolSignatureDescription
createScanner(transport, identity) => ScannerScanner bound to an agent identity + transport.
scanner.scan(range) => Promise<DetectedPayment[]>Detect inbound payments in a block range; returns stealth private key per hit.
DetectedPaymenttype{ stealthAddress, stealthPrivateKey, ephemeralPubKey, viewTag, blockNumber, logIndex }

@shroud-fi/relayer

npm · v0.1

Gasless 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/relayer

Exports

SymbolSignatureDescription
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.
StealthAddressEmptyErrorclassDistinguishes “already swept” from wallet insufficiency.

@shroud-fi/transport

npm · v0.1

Pluggable 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 viem

Exports

SymbolSignatureDescription
createTransport(cfg: TransportConfig) => TransportBuild a transport from chain, rpcUrl, or an existing viem client.
getDeployment(chainId: number) => DeploymentManifestLookup verified contract addresses by chain ID. Base mainnet (8453).
ShroudFiStealthAbi · RegistrarAbi · RelayerAbi · EthRelayerAbiconstTyped ABIs for every deployed contract.

@shroud-fi/agent-runtime

npm · v0.1

The 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 viem

Exports

SymbolSignatureDescription
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.
agent.tstypescript
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.1

Stealth-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/x402

Exports

SymbolSignatureDescription
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.
x402.tstypescript
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.1

Operator-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/compliance

Exports

SymbolSignatureDescription
exportViewingKey(identity) => ViewingKeyExportSerialize 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.1

Model 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-server

Tools

ToolArgsPurpose
shroud_registerPublish the agent’s stealth meta-address into ERC-6538. Idempotent.
shroud_sendto · asset · amountSend to st:base:0x….
shroud_send_to_walletrecipient · asset · amountSend to a plain wallet — SDK looks up the meta-address.
shroud_receivefromBlock · toBlock?Scan a block range for inbound stealth payments.
shroud_sweepdetection · destination · viaRelayer?Sweep a detected stealth address (direct or gasless).
shroud_balanceaddress? · token?Read ETH + optional ERC-20 balance.
shroud_statusOperator wallet, meta-address, chain, latest block, registration state.
shroud_x402_payurl · maxPriceUsdcAtomic?One-shot HTTP 402 client. Auto-signs USDC if a 402 lands.
shroud_x402_serveop · argsServer-side x402 primitives — mint 402 challenges or verify payments.
.mcp.jsonjson
{
  "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-host

HTTP / 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.json

Endpoints

PathMethodPurpose
/v1/auth/challengePOSTMint an EIP-191 nonce for a wallet. 5-min TTL, single-use.
/v1/registerPOSTPublish meta-address into ERC-6538.
/v1/sendPOSTSend to a meta-address.
/v1/send-to-walletPOSTSend to a wallet via meta-address lookup.
/v1/paymentsGETScan a block range for inbound payments.
/v1/sweepPOSTDirect or gasless sweep.
/v1/balance · /v1/statusGETOperator state read-outs.
/v1/x402-pay · /v1/x402-servePOSTSame x402 client + server primitives as MCP.
python_agent.pypython
# 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)