GitHub - ryanwaits/secondlayer: Decoded Stacks data in your own database. Self-hosted. · GitHub
Skip to content

Latest commit

 

History

3,762 Commits

Folders and files

Repository files navigation

Secondlayer

Your app needs Stacks data that no public API has — your contract, your schema, your uptime. Today that means writing an indexer.

Secondlayer is the runtime instead: decoded chain data in your own database, backfilled from genesis, reorg-safe, kept current. Get tables and a REST API out of the box, or stream rows into your own schema — Postgres, SQLite, or anything you already run — and serve them however you already serve things.

The instance itself is Postgres plus one container, on your hardware.

See STRATEGY.md.

curl "http://127.0.0.1:3800/v1/index/events?event_type=ft_transfer&limit=5"

Quickstart

bun add -g @secondlayer/cli
secondlayer init --network mainnet
cd docker/oss && docker compose up -d
secondlayer observer --mode indexer --endpoint secondlayer:3700
secondlayer bootstrap --against <manifest>
secondlayer verify all --against <manifest>

# Index a contract into a typed, queryable Postgres table
export SL_API_URL=http://127.0.0.1:3800
secondlayer subgraphs scaffold SP1234ABCD.my-contract -o subgraphs/my-contract.ts
secondlayer subgraphs deploy subgraphs/my-contract.ts --start-block <recent-block>
secondlayer subgraphs query my-contract <table> --sort _block_height --order desc

A chain subscription fires on raw events with no subgraph:

secondlayer subscriptions create amm-swaps \
  --url https://my-app.com/webhook \
  --trigger '{"type":"contract_call","contractId":"SP....amm","functionName":"swap-*"}'

Docs → self-host · CLI → packages/cli/README.md.

Read it from your instance

SDK default is http://127.0.0.1:3800 (or SL_API_URL).

import { SecondLayer } from "@secondlayer/sdk";

const sl = new SecondLayer();
const { rows, next_cursor, tip } = await sl.subgraphs.rows("my-contract", "<table>", {
  order: "desc",
  limit: 25,
});
curl "http://127.0.0.1:3800/v1/subgraphs/my-contract/<table>?_limit=25"

Pages are _id-keyset: pass ?cursor=<next_cursor> to resume, _order=asc|desc for direction.

MCPbunx -p @secondlayer/mcp secondlayer-mcp (default local API). Set INSTANCE_TOKEN from secondlayer init for writes. See MCP README.

Packages

Two TypeScript SDKs, one chooser: @secondlayer/sdk talks to this instance (query subgraphs, manage webhooks); @secondlayer/stacks is low-level chain primitives (Clarity decoding, reads). Most apps only need sdk.

Package Description
@secondlayer/cli secondlayer binary — init, bootstrap, verify, deploy
@secondlayer/sdk TypeScript SDK — Streams, Index, subgraphs, webhooks
@secondlayer/mcp MCP server — instance tools for agents
@secondlayer/stacks viem-style Stacks client — public/wallet, BNS
@secondlayer/subgraphs defineSubgraph() — schema, triggers, handlers
@secondlayer/shared Shared db, schemas, crypto helpers
@secondlayer/api REST API for the instance

Self-host

git clone https://github.com/ryanwaits/secondlayer
cd secondlayer/docker/oss
secondlayer init --network mainnet
docker compose up -d

OSS quickstart.

Development

bun install && bun run build && bun run test

Releases flow through Changesets: bun run version to bump, bun run release to publish.

License

MIT

About

Decoded Stacks data in your own database. Self-hosted.

Topics

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages