Introduction
Decoded Stacks chain data, backfilled from genesis, reorg-safe and kept current. Trust, and verify it yourself.
Do you already have an API layer?
index.tsts
import { Index } from "@secondlayer/sdk";
await new Index().events.consume({
eventType: "ft_transfer",
fromCursor: await db.loadCheckpoint(),
onBatch: async (events, envelope, ctx) => {
await db.commit(events, ctx.cursor);
return ctx.cursor;
},
onReorg: (reorg) => db.deleteFromHeight(reorg.fork_point_height),
});
, and when a reorg lands. You keep your schema and serve it however you already do. Index →
subgraph.config.tsts
import { defineSubgraph } from "@secondlayer/subgraphs";
export default defineSubgraph({
name: "sbtc-flows",
startBlock: 8000000,
sources: { transfers: { type: "ft_transfer", assetIdentifier: "SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token::sbtc-token" } },
schema: { transfers: { columns: { amount: { type: "uint" }, sender: { type: "principal" } } } },
handlers: {
transfers: (event, ctx) => ctx.insert("transfers", { amount: event.amount, sender: event.sender }),
},
});
The , and fills a table that REST serves. You get an API you didn't write. That's the point, and the tradeoff. Subgraphs →
indexer.tsts
await sl.streams.events.consume({
types: ["ft_transfer"],
fromCursor: await db.loadCheckpoint(),
onBatch: async (events, envelope, ctx) => {
await db.insertEvents(events, ctx.cursor);
return ctx.cursor;
},
onReorg: (reorg) => db.deleteFromHeight(reorg.fork_point_height),
});
You get , and a . This is what Index is built on. Streams →
Five commands from key to a row you can check against Bitcoin. Keys come from /account/keys.
Using an agent? bunx skills add ryanwaits/secondlayer --skill secondlayer -y
Every command and example reads these two variables.
$bun add -g @secondlayer/cli
$export SECONDLAYER_API_URL=https://api.secondlayer.tools
$export SECONDLAYER_API_KEY=sk-sl_...
Scaffolds a typed subgraph from a contract's events.
$secondlayer subgraphs create my-balances --from-contract SP....my-contract
Set a startBlock first: the event and transaction rows it reads bill. Reads of your own tables are free.
$secondlayer subgraphs deploy subgraphs/my-balances.ts
$curl -H "Authorization: Bearer $SECONDLAYER_API_KEY" \
"$SECONDLAYER_API_URL/v1/subgraphs/my-balances/balances"
Proves the block your rows came from against Bitcoin. Verification →
$secondlayer verify block 9137005
Prefer your own box? Self-host is the same product on your Postgres.
Edit on GitHub