@secondlayer/subgraphs 0.8.1 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/src/index.d.ts +113 -32
  2. package/dist/src/index.js +486 -99
  3. package/dist/src/index.js.map +9 -10
  4. package/dist/src/runtime/block-processor.d.ts +110 -20
  5. package/dist/src/runtime/block-processor.js +452 -90
  6. package/dist/src/runtime/block-processor.js.map +7 -8
  7. package/dist/src/runtime/catchup.d.ts +110 -20
  8. package/dist/src/runtime/catchup.js +457 -94
  9. package/dist/src/runtime/catchup.js.map +8 -9
  10. package/dist/src/runtime/clarity.js +3 -3
  11. package/dist/src/runtime/clarity.js.map +3 -3
  12. package/dist/src/runtime/context.d.ts +23 -5
  13. package/dist/src/runtime/context.js +57 -1
  14. package/dist/src/runtime/context.js.map +3 -3
  15. package/dist/src/runtime/processor.js +457 -94
  16. package/dist/src/runtime/processor.js.map +8 -9
  17. package/dist/src/runtime/reindex.d.ts +110 -20
  18. package/dist/src/runtime/reindex.js +452 -90
  19. package/dist/src/runtime/reindex.js.map +7 -8
  20. package/dist/src/runtime/reorg.d.ts +110 -20
  21. package/dist/src/runtime/reorg.js +452 -90
  22. package/dist/src/runtime/reorg.js.map +7 -8
  23. package/dist/src/runtime/runner.d.ts +152 -42
  24. package/dist/src/runtime/runner.js +226 -30
  25. package/dist/src/runtime/runner.js.map +4 -4
  26. package/dist/src/runtime/source-matcher.d.ts +88 -31
  27. package/dist/src/runtime/source-matcher.js +171 -61
  28. package/dist/src/runtime/source-matcher.js.map +4 -5
  29. package/dist/src/schema/index.d.ts +110 -20
  30. package/dist/src/schema/index.js +34 -9
  31. package/dist/src/schema/index.js.map +3 -3
  32. package/dist/src/service.js +457 -94
  33. package/dist/src/service.js.map +8 -9
  34. package/dist/src/templates.js +52 -51
  35. package/dist/src/templates.js.map +3 -3
  36. package/dist/src/types.d.ts +111 -29
  37. package/dist/src/types.js +1 -20
  38. package/dist/src/types.js.map +3 -4
  39. package/dist/src/validate.d.ts +112 -22
  40. package/dist/src/validate.js +35 -10
  41. package/dist/src/validate.js.map +3 -3
  42. package/package.json +2 -2
@@ -12,9 +12,9 @@ var templates = [
12
12
 
13
13
  export default defineSubgraph({
14
14
  name: 'dex-swaps',
15
- sources: [
16
- { contract: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01', event: 'swap' },
17
- ],
15
+ sources: {
16
+ swap: { type: 'print_event', contractId: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01', topic: 'swap' },
17
+ },
18
18
  schema: {
19
19
  swaps: {
20
20
  columns: {
@@ -28,13 +28,13 @@ export default defineSubgraph({
28
28
  },
29
29
  },
30
30
  handlers: {
31
- 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01::swap': (event, ctx) => {
31
+ swap: (event, ctx) => {
32
32
  ctx.insert('swaps', {
33
33
  sender: ctx.tx.sender,
34
- token_x: event.tokenX,
35
- token_y: event.tokenY,
36
- amount_x: event.dx,
37
- amount_y: event.dy,
34
+ token_x: event.data.tokenX,
35
+ token_y: event.data.tokenY,
36
+ amount_x: event.data.dx,
37
+ amount_y: event.data.dy,
38
38
  });
39
39
  },
40
40
  },
@@ -51,11 +51,11 @@ export default defineSubgraph({
51
51
 
52
52
  export default defineSubgraph({
53
53
  name: 'nft-marketplace',
54
- sources: [
55
- { contract: 'SP...marketplace', event: 'list-item' },
56
- { contract: 'SP...marketplace', event: 'unlist-item' },
57
- { contract: 'SP...marketplace', event: 'purchase' },
58
- ],
54
+ sources: {
55
+ listItem: { type: 'print_event', contractId: 'SP...marketplace', topic: 'list-item' },
56
+ unlistItem: { type: 'print_event', contractId: 'SP...marketplace', topic: 'unlist-item' },
57
+ purchase: { type: 'print_event', contractId: 'SP...marketplace', topic: 'purchase' },
58
+ },
59
59
  schema: {
60
60
  listings: {
61
61
  columns: {
@@ -76,24 +76,24 @@ export default defineSubgraph({
76
76
  },
77
77
  },
78
78
  handlers: {
79
- 'SP...marketplace::list-item': (event, ctx) => {
80
- ctx.upsert('listings', { nft_id: event.nftId }, {
81
- nft_id: event.nftId,
79
+ listItem: (event, ctx) => {
80
+ ctx.upsert('listings', { nft_id: event.data.nftId }, {
81
+ nft_id: event.data.nftId,
82
82
  seller: ctx.tx.sender,
83
- price: event.price,
83
+ price: event.data.price,
84
84
  status: 'active',
85
85
  });
86
86
  },
87
- 'SP...marketplace::unlist-item': (event, ctx) => {
88
- ctx.update('listings', { nft_id: event.nftId }, { status: 'cancelled' });
87
+ unlistItem: (event, ctx) => {
88
+ ctx.update('listings', { nft_id: event.data.nftId }, { status: 'cancelled' });
89
89
  },
90
- 'SP...marketplace::purchase': (event, ctx) => {
91
- ctx.update('listings', { nft_id: event.nftId }, { status: 'sold' });
90
+ purchase: (event, ctx) => {
91
+ ctx.update('listings', { nft_id: event.data.nftId }, { status: 'sold' });
92
92
  ctx.insert('sales', {
93
- nft_id: event.nftId,
94
- seller: event.seller,
93
+ nft_id: event.data.nftId,
94
+ seller: event.data.seller,
95
95
  buyer: ctx.tx.sender,
96
- price: event.price,
96
+ price: event.data.price,
97
97
  });
98
98
  },
99
99
  },
@@ -110,9 +110,9 @@ export default defineSubgraph({
110
110
 
111
111
  export default defineSubgraph({
112
112
  name: 'token-transfers',
113
- sources: [
114
- { contract: 'SP...token', event: 'transfer' },
115
- ],
113
+ sources: {
114
+ transfer: { type: 'ft_transfer', assetIdentifier: 'SP...token' },
115
+ },
116
116
  schema: {
117
117
  transfers: {
118
118
  columns: {
@@ -130,7 +130,7 @@ export default defineSubgraph({
130
130
  },
131
131
  },
132
132
  handlers: {
133
- 'SP...token::transfer': async (event, ctx) => {
133
+ transfer: async (event, ctx) => {
134
134
  ctx.insert('transfers', {
135
135
  from_addr: event.sender,
136
136
  to_addr: event.recipient,
@@ -142,7 +142,7 @@ export default defineSubgraph({
142
142
  const senderPrev = senderBal ? BigInt(senderBal.balance as string) : 0n;
143
143
  ctx.upsert('balances', { address: event.sender }, {
144
144
  address: event.sender,
145
- balance: senderPrev - BigInt(event.amount as string),
145
+ balance: senderPrev - event.amount,
146
146
  });
147
147
 
148
148
  // Update recipient balance
@@ -150,7 +150,7 @@ export default defineSubgraph({
150
150
  const recipPrev = recipBal ? BigInt(recipBal.balance as string) : 0n;
151
151
  ctx.upsert('balances', { address: event.recipient }, {
152
152
  address: event.recipient,
153
- balance: recipPrev + BigInt(event.amount as string),
153
+ balance: recipPrev + event.amount,
154
154
  });
155
155
  },
156
156
  },
@@ -167,10 +167,10 @@ export default defineSubgraph({
167
167
 
168
168
  export default defineSubgraph({
169
169
  name: 'bns-names',
170
- sources: [
171
- { contract: 'SP000000000000000000002Q6VF78.bns', function: 'name-register' },
172
- { contract: 'SP000000000000000000002Q6VF78.bns', function: 'name-transfer' },
173
- ],
170
+ sources: {
171
+ nameRegister: { type: 'contract_call', contractId: 'SP000000000000000000002Q6VF78.bns', functionName: 'name-register' },
172
+ nameTransfer: { type: 'contract_call', contractId: 'SP000000000000000000002Q6VF78.bns', functionName: 'name-transfer' },
173
+ },
174
174
  schema: {
175
175
  names: {
176
176
  columns: {
@@ -190,22 +190,22 @@ export default defineSubgraph({
190
190
  },
191
191
  },
192
192
  handlers: {
193
- 'SP000000000000000000002Q6VF78.bns::name-register': (event, ctx) => {
194
- ctx.upsert('names', { name: event.name, namespace: event.namespace }, {
195
- name: event.name,
196
- namespace: event.namespace,
193
+ nameRegister: (event, ctx) => {
194
+ ctx.upsert('names', { name: event.args.name, namespace: event.args.namespace }, {
195
+ name: event.args.name,
196
+ namespace: event.args.namespace,
197
197
  owner: ctx.tx.sender,
198
198
  });
199
199
  },
200
- 'SP000000000000000000002Q6VF78.bns::name-transfer': (event, ctx) => {
201
- ctx.update('names', { name: event.name, namespace: event.namespace }, {
202
- owner: event.newOwner,
200
+ nameTransfer: (event, ctx) => {
201
+ ctx.update('names', { name: event.args.name, namespace: event.args.namespace }, {
202
+ owner: event.args.newOwner,
203
203
  });
204
204
  ctx.insert('transfers', {
205
- name: event.name,
206
- namespace: event.namespace,
207
- from_addr: event.sender,
208
- to_addr: event.newOwner,
205
+ name: event.args.name,
206
+ namespace: event.args.namespace,
207
+ from_addr: event.args.sender,
208
+ to_addr: event.args.newOwner,
209
209
  });
210
210
  },
211
211
  },
@@ -220,11 +220,13 @@ export default defineSubgraph({
220
220
  category: "token",
221
221
  code: `import { defineSubgraph } from '@secondlayer/subgraphs';
222
222
 
223
- const WHALE_THRESHOLD = 100_000_000_000; // 100k STX in microSTX
223
+ const WHALE_THRESHOLD = 100_000_000_000n; // 100k STX in microSTX
224
224
 
225
225
  export default defineSubgraph({
226
226
  name: 'stx-whales',
227
- sources: [{ type: 'stx_transfer' }],
227
+ sources: {
228
+ stxTransfer: { type: 'stx_transfer' },
229
+ },
228
230
  schema: {
229
231
  whale_transfers: {
230
232
  columns: {
@@ -235,9 +237,8 @@ export default defineSubgraph({
235
237
  },
236
238
  },
237
239
  handlers: {
238
- stx_transfer: (event, ctx) => {
239
- const amount = BigInt(event.amount as string);
240
- if (amount >= BigInt(WHALE_THRESHOLD)) {
240
+ stxTransfer: (event, ctx) => {
241
+ if (event.amount >= WHALE_THRESHOLD) {
241
242
  ctx.insert('whale_transfers', {
242
243
  sender: event.sender,
243
244
  receiver: event.recipient,
@@ -263,5 +264,5 @@ export {
263
264
  getTemplateById
264
265
  };
265
266
 
266
- //# debugId=C475457B59EBDAC964756E2164756E21
267
+ //# debugId=F4B252C88EAA2F7964756E2164756E21
267
268
  //# sourceMappingURL=templates.js.map
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/templates.ts"],
4
4
  "sourcesContent": [
5
- "export interface SubgraphTemplate {\n\tid: string;\n\tname: string;\n\tdescription: string;\n\tcategory: \"defi\" | \"nft\" | \"token\" | \"infrastructure\";\n\tcode: string;\n\tprompt: string;\n}\n\nexport const templates: SubgraphTemplate[] = [\n\t{\n\t\tid: \"dex-swaps\",\n\t\tname: \"DEX Swap Tracking\",\n\t\tdescription:\n\t\t\t\"Track swap events from ALEX or any AMM pool. Indexes token pairs, amounts, and traders.\",\n\t\tcategory: \"defi\",\n\t\tcode: `import { defineSubgraph } from '@secondlayer/subgraphs';\n\nexport default defineSubgraph({\n name: 'dex-swaps',\n sources: [\n { contract: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01', event: 'swap' },\n ],\n schema: {\n swaps: {\n columns: {\n sender: { type: 'principal', indexed: true },\n token_x: { type: 'text' },\n token_y: { type: 'text' },\n amount_x: { type: 'uint' },\n amount_y: { type: 'uint' },\n },\n indexes: [['sender', 'token_x']],\n },\n },\n handlers: {\n 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01::swap': (event, ctx) => {\n ctx.insert('swaps', {\n sender: ctx.tx.sender,\n token_x: event.tokenX,\n token_y: event.tokenY,\n amount_x: event.dx,\n amount_y: event.dy,\n });\n },\n },\n});\n`,\n\t\tprompt:\n\t\t\t\"Create a Secondlayer subgraph that tracks DEX swap events from ALEX AMM pool. Index sender, token pairs, and amounts.\",\n\t},\n\t{\n\t\tid: \"nft-marketplace\",\n\t\tname: \"NFT Marketplace\",\n\t\tdescription:\n\t\t\t\"Index NFT listings, sales, and cancellations. Track prices and ownership changes.\",\n\t\tcategory: \"nft\",\n\t\tcode: `import { defineSubgraph } from '@secondlayer/subgraphs';\n\nexport default defineSubgraph({\n name: 'nft-marketplace',\n sources: [\n { contract: 'SP...marketplace', event: 'list-item' },\n { contract: 'SP...marketplace', event: 'unlist-item' },\n { contract: 'SP...marketplace', event: 'purchase' },\n ],\n schema: {\n listings: {\n columns: {\n nft_id: { type: 'uint', indexed: true },\n seller: { type: 'principal', indexed: true },\n price: { type: 'uint' },\n status: { type: 'text' },\n },\n uniqueKeys: [['nft_id']],\n },\n sales: {\n columns: {\n nft_id: { type: 'uint', indexed: true },\n seller: { type: 'principal' },\n buyer: { type: 'principal', indexed: true },\n price: { type: 'uint' },\n },\n },\n },\n handlers: {\n 'SP...marketplace::list-item': (event, ctx) => {\n ctx.upsert('listings', { nft_id: event.nftId }, {\n nft_id: event.nftId,\n seller: ctx.tx.sender,\n price: event.price,\n status: 'active',\n });\n },\n 'SP...marketplace::unlist-item': (event, ctx) => {\n ctx.update('listings', { nft_id: event.nftId }, { status: 'cancelled' });\n },\n 'SP...marketplace::purchase': (event, ctx) => {\n ctx.update('listings', { nft_id: event.nftId }, { status: 'sold' });\n ctx.insert('sales', {\n nft_id: event.nftId,\n seller: event.seller,\n buyer: ctx.tx.sender,\n price: event.price,\n });\n },\n },\n});\n`,\n\t\tprompt:\n\t\t\t\"Create a Secondlayer subgraph for an NFT marketplace. Track listings, cancellations, and sales with prices.\",\n\t},\n\t{\n\t\tid: \"token-transfers\",\n\t\tname: \"Token Transfers\",\n\t\tdescription:\n\t\t\t\"Track fungible token transfers with running balance computation per address.\",\n\t\tcategory: \"token\",\n\t\tcode: `import { defineSubgraph } from '@secondlayer/subgraphs';\n\nexport default defineSubgraph({\n name: 'token-transfers',\n sources: [\n { contract: 'SP...token', event: 'transfer' },\n ],\n schema: {\n transfers: {\n columns: {\n from_addr: { type: 'principal', indexed: true },\n to_addr: { type: 'principal', indexed: true },\n amount: { type: 'uint' },\n },\n },\n balances: {\n columns: {\n address: { type: 'principal', indexed: true },\n balance: { type: 'uint' },\n },\n uniqueKeys: [['address']],\n },\n },\n handlers: {\n 'SP...token::transfer': async (event, ctx) => {\n ctx.insert('transfers', {\n from_addr: event.sender,\n to_addr: event.recipient,\n amount: event.amount,\n });\n\n // Update sender balance\n const senderBal = await ctx.findOne('balances', { address: event.sender });\n const senderPrev = senderBal ? BigInt(senderBal.balance as string) : 0n;\n ctx.upsert('balances', { address: event.sender }, {\n address: event.sender,\n balance: senderPrev - BigInt(event.amount as string),\n });\n\n // Update recipient balance\n const recipBal = await ctx.findOne('balances', { address: event.recipient });\n const recipPrev = recipBal ? BigInt(recipBal.balance as string) : 0n;\n ctx.upsert('balances', { address: event.recipient }, {\n address: event.recipient,\n balance: recipPrev + BigInt(event.amount as string),\n });\n },\n },\n});\n`,\n\t\tprompt:\n\t\t\t\"Create a Secondlayer subgraph that tracks token transfers and computes running balances per address.\",\n\t},\n\t{\n\t\tid: \"bns-names\",\n\t\tname: \"BNS Names\",\n\t\tdescription:\n\t\t\t\"Index BNS name registrations and transfers. Search names by owner or namespace.\",\n\t\tcategory: \"infrastructure\",\n\t\tcode: `import { defineSubgraph } from '@secondlayer/subgraphs';\n\nexport default defineSubgraph({\n name: 'bns-names',\n sources: [\n { contract: 'SP000000000000000000002Q6VF78.bns', function: 'name-register' },\n { contract: 'SP000000000000000000002Q6VF78.bns', function: 'name-transfer' },\n ],\n schema: {\n names: {\n columns: {\n name: { type: 'text', indexed: true, search: true },\n namespace: { type: 'text', indexed: true },\n owner: { type: 'principal', indexed: true },\n },\n uniqueKeys: [['name', 'namespace']],\n },\n transfers: {\n columns: {\n name: { type: 'text' },\n namespace: { type: 'text' },\n from_addr: { type: 'principal' },\n to_addr: { type: 'principal' },\n },\n },\n },\n handlers: {\n 'SP000000000000000000002Q6VF78.bns::name-register': (event, ctx) => {\n ctx.upsert('names', { name: event.name, namespace: event.namespace }, {\n name: event.name,\n namespace: event.namespace,\n owner: ctx.tx.sender,\n });\n },\n 'SP000000000000000000002Q6VF78.bns::name-transfer': (event, ctx) => {\n ctx.update('names', { name: event.name, namespace: event.namespace }, {\n owner: event.newOwner,\n });\n ctx.insert('transfers', {\n name: event.name,\n namespace: event.namespace,\n from_addr: event.sender,\n to_addr: event.newOwner,\n });\n },\n },\n});\n`,\n\t\tprompt:\n\t\t\t\"Create a Secondlayer subgraph for BNS name registrations and transfers on Stacks.\",\n\t},\n\t{\n\t\tid: \"stx-whales\",\n\t\tname: \"STX Whale Alerts\",\n\t\tdescription:\n\t\t\t\"Track large STX transfers above a configurable threshold. Great for monitoring whale activity.\",\n\t\tcategory: \"token\",\n\t\tcode: `import { defineSubgraph } from '@secondlayer/subgraphs';\n\nconst WHALE_THRESHOLD = 100_000_000_000; // 100k STX in microSTX\n\nexport default defineSubgraph({\n name: 'stx-whales',\n sources: [{ type: 'stx_transfer' }],\n schema: {\n whale_transfers: {\n columns: {\n sender: { type: 'principal', indexed: true },\n receiver: { type: 'principal', indexed: true },\n amount: { type: 'uint' },\n },\n },\n },\n handlers: {\n stx_transfer: (event, ctx) => {\n const amount = BigInt(event.amount as string);\n if (amount >= BigInt(WHALE_THRESHOLD)) {\n ctx.insert('whale_transfers', {\n sender: event.sender,\n receiver: event.recipient,\n amount: event.amount,\n });\n }\n },\n },\n});\n`,\n\t\tprompt:\n\t\t\t\"Create a Secondlayer subgraph that tracks STX transfers above 100k STX as whale alerts.\",\n\t},\n];\n\nexport function getTemplateById(id: string): SubgraphTemplate | undefined {\n\treturn templates.find((t) => t.id === id);\n}\n\nexport function getTemplatesByCategory(category: string): SubgraphTemplate[] {\n\treturn templates.filter((t) => t.category === category);\n}\n"
5
+ "export interface SubgraphTemplate {\n\tid: string;\n\tname: string;\n\tdescription: string;\n\tcategory: \"defi\" | \"nft\" | \"token\" | \"infrastructure\";\n\tcode: string;\n\tprompt: string;\n}\n\nexport const templates: SubgraphTemplate[] = [\n\t{\n\t\tid: \"dex-swaps\",\n\t\tname: \"DEX Swap Tracking\",\n\t\tdescription:\n\t\t\t\"Track swap events from ALEX or any AMM pool. Indexes token pairs, amounts, and traders.\",\n\t\tcategory: \"defi\",\n\t\tcode: `import { defineSubgraph } from '@secondlayer/subgraphs';\n\nexport default defineSubgraph({\n name: 'dex-swaps',\n sources: {\n swap: { type: 'print_event', contractId: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01', topic: 'swap' },\n },\n schema: {\n swaps: {\n columns: {\n sender: { type: 'principal', indexed: true },\n token_x: { type: 'text' },\n token_y: { type: 'text' },\n amount_x: { type: 'uint' },\n amount_y: { type: 'uint' },\n },\n indexes: [['sender', 'token_x']],\n },\n },\n handlers: {\n swap: (event, ctx) => {\n ctx.insert('swaps', {\n sender: ctx.tx.sender,\n token_x: event.data.tokenX,\n token_y: event.data.tokenY,\n amount_x: event.data.dx,\n amount_y: event.data.dy,\n });\n },\n },\n});\n`,\n\t\tprompt:\n\t\t\t\"Create a Secondlayer subgraph that tracks DEX swap events from ALEX AMM pool. Index sender, token pairs, and amounts.\",\n\t},\n\t{\n\t\tid: \"nft-marketplace\",\n\t\tname: \"NFT Marketplace\",\n\t\tdescription:\n\t\t\t\"Index NFT listings, sales, and cancellations. Track prices and ownership changes.\",\n\t\tcategory: \"nft\",\n\t\tcode: `import { defineSubgraph } from '@secondlayer/subgraphs';\n\nexport default defineSubgraph({\n name: 'nft-marketplace',\n sources: {\n listItem: { type: 'print_event', contractId: 'SP...marketplace', topic: 'list-item' },\n unlistItem: { type: 'print_event', contractId: 'SP...marketplace', topic: 'unlist-item' },\n purchase: { type: 'print_event', contractId: 'SP...marketplace', topic: 'purchase' },\n },\n schema: {\n listings: {\n columns: {\n nft_id: { type: 'uint', indexed: true },\n seller: { type: 'principal', indexed: true },\n price: { type: 'uint' },\n status: { type: 'text' },\n },\n uniqueKeys: [['nft_id']],\n },\n sales: {\n columns: {\n nft_id: { type: 'uint', indexed: true },\n seller: { type: 'principal' },\n buyer: { type: 'principal', indexed: true },\n price: { type: 'uint' },\n },\n },\n },\n handlers: {\n listItem: (event, ctx) => {\n ctx.upsert('listings', { nft_id: event.data.nftId }, {\n nft_id: event.data.nftId,\n seller: ctx.tx.sender,\n price: event.data.price,\n status: 'active',\n });\n },\n unlistItem: (event, ctx) => {\n ctx.update('listings', { nft_id: event.data.nftId }, { status: 'cancelled' });\n },\n purchase: (event, ctx) => {\n ctx.update('listings', { nft_id: event.data.nftId }, { status: 'sold' });\n ctx.insert('sales', {\n nft_id: event.data.nftId,\n seller: event.data.seller,\n buyer: ctx.tx.sender,\n price: event.data.price,\n });\n },\n },\n});\n`,\n\t\tprompt:\n\t\t\t\"Create a Secondlayer subgraph for an NFT marketplace. Track listings, cancellations, and sales with prices.\",\n\t},\n\t{\n\t\tid: \"token-transfers\",\n\t\tname: \"Token Transfers\",\n\t\tdescription:\n\t\t\t\"Track fungible token transfers with running balance computation per address.\",\n\t\tcategory: \"token\",\n\t\tcode: `import { defineSubgraph } from '@secondlayer/subgraphs';\n\nexport default defineSubgraph({\n name: 'token-transfers',\n sources: {\n transfer: { type: 'ft_transfer', assetIdentifier: 'SP...token' },\n },\n schema: {\n transfers: {\n columns: {\n from_addr: { type: 'principal', indexed: true },\n to_addr: { type: 'principal', indexed: true },\n amount: { type: 'uint' },\n },\n },\n balances: {\n columns: {\n address: { type: 'principal', indexed: true },\n balance: { type: 'uint' },\n },\n uniqueKeys: [['address']],\n },\n },\n handlers: {\n transfer: async (event, ctx) => {\n ctx.insert('transfers', {\n from_addr: event.sender,\n to_addr: event.recipient,\n amount: event.amount,\n });\n\n // Update sender balance\n const senderBal = await ctx.findOne('balances', { address: event.sender });\n const senderPrev = senderBal ? BigInt(senderBal.balance as string) : 0n;\n ctx.upsert('balances', { address: event.sender }, {\n address: event.sender,\n balance: senderPrev - event.amount,\n });\n\n // Update recipient balance\n const recipBal = await ctx.findOne('balances', { address: event.recipient });\n const recipPrev = recipBal ? BigInt(recipBal.balance as string) : 0n;\n ctx.upsert('balances', { address: event.recipient }, {\n address: event.recipient,\n balance: recipPrev + event.amount,\n });\n },\n },\n});\n`,\n\t\tprompt:\n\t\t\t\"Create a Secondlayer subgraph that tracks token transfers and computes running balances per address.\",\n\t},\n\t{\n\t\tid: \"bns-names\",\n\t\tname: \"BNS Names\",\n\t\tdescription:\n\t\t\t\"Index BNS name registrations and transfers. Search names by owner or namespace.\",\n\t\tcategory: \"infrastructure\",\n\t\tcode: `import { defineSubgraph } from '@secondlayer/subgraphs';\n\nexport default defineSubgraph({\n name: 'bns-names',\n sources: {\n nameRegister: { type: 'contract_call', contractId: 'SP000000000000000000002Q6VF78.bns', functionName: 'name-register' },\n nameTransfer: { type: 'contract_call', contractId: 'SP000000000000000000002Q6VF78.bns', functionName: 'name-transfer' },\n },\n schema: {\n names: {\n columns: {\n name: { type: 'text', indexed: true, search: true },\n namespace: { type: 'text', indexed: true },\n owner: { type: 'principal', indexed: true },\n },\n uniqueKeys: [['name', 'namespace']],\n },\n transfers: {\n columns: {\n name: { type: 'text' },\n namespace: { type: 'text' },\n from_addr: { type: 'principal' },\n to_addr: { type: 'principal' },\n },\n },\n },\n handlers: {\n nameRegister: (event, ctx) => {\n ctx.upsert('names', { name: event.args.name, namespace: event.args.namespace }, {\n name: event.args.name,\n namespace: event.args.namespace,\n owner: ctx.tx.sender,\n });\n },\n nameTransfer: (event, ctx) => {\n ctx.update('names', { name: event.args.name, namespace: event.args.namespace }, {\n owner: event.args.newOwner,\n });\n ctx.insert('transfers', {\n name: event.args.name,\n namespace: event.args.namespace,\n from_addr: event.args.sender,\n to_addr: event.args.newOwner,\n });\n },\n },\n});\n`,\n\t\tprompt:\n\t\t\t\"Create a Secondlayer subgraph for BNS name registrations and transfers on Stacks.\",\n\t},\n\t{\n\t\tid: \"stx-whales\",\n\t\tname: \"STX Whale Alerts\",\n\t\tdescription:\n\t\t\t\"Track large STX transfers above a configurable threshold. Great for monitoring whale activity.\",\n\t\tcategory: \"token\",\n\t\tcode: `import { defineSubgraph } from '@secondlayer/subgraphs';\n\nconst WHALE_THRESHOLD = 100_000_000_000n; // 100k STX in microSTX\n\nexport default defineSubgraph({\n name: 'stx-whales',\n sources: {\n stxTransfer: { type: 'stx_transfer' },\n },\n schema: {\n whale_transfers: {\n columns: {\n sender: { type: 'principal', indexed: true },\n receiver: { type: 'principal', indexed: true },\n amount: { type: 'uint' },\n },\n },\n },\n handlers: {\n stxTransfer: (event, ctx) => {\n if (event.amount >= WHALE_THRESHOLD) {\n ctx.insert('whale_transfers', {\n sender: event.sender,\n receiver: event.recipient,\n amount: event.amount,\n });\n }\n },\n },\n});\n`,\n\t\tprompt:\n\t\t\t\"Create a Secondlayer subgraph that tracks STX transfers above 100k STX as whale alerts.\",\n\t},\n];\n\nexport function getTemplateById(id: string): SubgraphTemplate | undefined {\n\treturn templates.find((t) => t.id === id);\n}\n\nexport function getTemplatesByCategory(category: string): SubgraphTemplate[] {\n\treturn templates.filter((t) => t.category === category);\n}\n"
6
6
  ],
7
- "mappings": ";;;;AASO,IAAM,YAAgC;AAAA,EAC5C;AAAA,IACC,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aACC;AAAA,IACD,UAAU;AAAA,IACV,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgCN,QACC;AAAA,EACF;AAAA,EACA;AAAA,IACC,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aACC;AAAA,IACD,UAAU;AAAA,IACV,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAoDN,QACC;AAAA,EACF;AAAA,EACA;AAAA,IACC,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aACC;AAAA,IACD,UAAU;AAAA,IACV,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAkDN,QACC;AAAA,EACF;AAAA,EACA;AAAA,IACC,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aACC;AAAA,IACD,UAAU;AAAA,IACV,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgDN,QACC;AAAA,EACF;AAAA,EACA;AAAA,IACC,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aACC;AAAA,IACD,UAAU;AAAA,IACV,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA8BN,QACC;AAAA,EACF;AACD;AAEO,SAAS,eAAe,CAAC,IAA0C;AAAA,EACzE,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAAA;AAGlC,SAAS,sBAAsB,CAAC,UAAsC;AAAA,EAC5E,OAAO,UAAU,OAAO,CAAC,MAAM,EAAE,aAAa,QAAQ;AAAA;",
8
- "debugId": "C475457B59EBDAC964756E2164756E21",
7
+ "mappings": ";;;;AASO,IAAM,YAAgC;AAAA,EAC5C;AAAA,IACC,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aACC;AAAA,IACD,UAAU;AAAA,IACV,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgCN,QACC;AAAA,EACF;AAAA,EACA;AAAA,IACC,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aACC;AAAA,IACD,UAAU;AAAA,IACV,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAoDN,QACC;AAAA,EACF;AAAA,EACA;AAAA,IACC,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aACC;AAAA,IACD,UAAU;AAAA,IACV,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAkDN,QACC;AAAA,EACF;AAAA,EACA;AAAA,IACC,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aACC;AAAA,IACD,UAAU;AAAA,IACV,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgDN,QACC;AAAA,EACF;AAAA,EACA;AAAA,IACC,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aACC;AAAA,IACD,UAAU;AAAA,IACV,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA+BN,QACC;AAAA,EACF;AACD;AAEO,SAAS,eAAe,CAAC,IAA0C;AAAA,EACzE,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAAA;AAGlC,SAAS,sBAAsB,CAAC,UAAsC;AAAA,EAC5E,OAAO,UAAU,OAAO,CAAC,MAAM,EAAE,aAAa,QAAQ;AAAA;",
8
+ "debugId": "F4B252C88EAA2F7964756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -18,19 +18,98 @@ interface SubgraphTable {
18
18
  }
19
19
  /** Subgraph schema — maps table names to table definitions */
20
20
  type SubgraphSchema = Record<string, SubgraphTable>;
21
- /** Source filter for what blockchain data this subgraph processes */
22
- interface SubgraphSource {
23
- /** Contract principal (e.g., SP000...::contract-name). Supports * wildcards. */
24
- contract?: string;
25
- /** Event name/topic to filter on */
26
- event?: string;
27
- /** Function name to filter on */
28
- function?: string;
29
- /** Transaction type filter (e.g., "stx_transfer", "contract_call") */
30
- type?: string;
31
- /** Minimum amount filter (for stx_transfer sources) */
21
+ /** STX event filters */
22
+ interface StxTransferFilter {
23
+ type: "stx_transfer";
24
+ sender?: string;
25
+ recipient?: string;
32
26
  minAmount?: bigint;
27
+ maxAmount?: bigint;
33
28
  }
29
+ interface StxMintFilter {
30
+ type: "stx_mint";
31
+ recipient?: string;
32
+ minAmount?: bigint;
33
+ }
34
+ interface StxBurnFilter {
35
+ type: "stx_burn";
36
+ sender?: string;
37
+ minAmount?: bigint;
38
+ }
39
+ interface StxLockFilter {
40
+ type: "stx_lock";
41
+ lockedAddress?: string;
42
+ minAmount?: bigint;
43
+ }
44
+ /** FT event filters */
45
+ interface FtTransferFilter {
46
+ type: "ft_transfer";
47
+ assetIdentifier?: string;
48
+ sender?: string;
49
+ recipient?: string;
50
+ minAmount?: bigint;
51
+ }
52
+ interface FtMintFilter {
53
+ type: "ft_mint";
54
+ assetIdentifier?: string;
55
+ recipient?: string;
56
+ minAmount?: bigint;
57
+ }
58
+ interface FtBurnFilter {
59
+ type: "ft_burn";
60
+ assetIdentifier?: string;
61
+ sender?: string;
62
+ minAmount?: bigint;
63
+ }
64
+ /** NFT event filters */
65
+ interface NftTransferFilter {
66
+ type: "nft_transfer";
67
+ assetIdentifier?: string;
68
+ sender?: string;
69
+ recipient?: string;
70
+ }
71
+ interface NftMintFilter {
72
+ type: "nft_mint";
73
+ assetIdentifier?: string;
74
+ recipient?: string;
75
+ }
76
+ interface NftBurnFilter {
77
+ type: "nft_burn";
78
+ assetIdentifier?: string;
79
+ sender?: string;
80
+ }
81
+ /** Contract event filters */
82
+ interface ContractCallFilter {
83
+ type: "contract_call";
84
+ contractId?: string;
85
+ functionName?: string;
86
+ caller?: string;
87
+ /** ABI for typed event.args. If omitted, auto-fetched at deploy time. */
88
+ abi?: Record<string, unknown>;
89
+ }
90
+ interface ContractDeployFilter {
91
+ type: "contract_deploy";
92
+ deployer?: string;
93
+ contractName?: string;
94
+ }
95
+ interface PrintEventFilter {
96
+ type: "print_event";
97
+ contractId?: string;
98
+ topic?: string;
99
+ }
100
+ /** All subgraph filter types — discriminated on `type` */
101
+ type SubgraphFilter = StxTransferFilter | StxMintFilter | StxBurnFilter | StxLockFilter | FtTransferFilter | FtMintFilter | FtBurnFilter | NftTransferFilter | NftMintFilter | NftBurnFilter | ContractCallFilter | ContractDeployFilter | PrintEventFilter;
102
+ /** Transaction metadata available in handlers */
103
+ interface TxMeta {
104
+ txId: string;
105
+ sender: string;
106
+ type: string;
107
+ status: string;
108
+ contractId?: string | null;
109
+ functionName?: string | null;
110
+ }
111
+ /** Value or computed function that receives existing row */
112
+ type ComputedValue<T = unknown> = T | ((existing: Record<string, unknown> | null) => T);
34
113
  /** Context passed to subgraph handlers during event processing */
35
114
  interface SubgraphContext {
36
115
  block: {
@@ -39,29 +118,32 @@ interface SubgraphContext {
39
118
  timestamp: number
40
119
  burnBlockHeight: number
41
120
  };
42
- tx: {
43
- txId: string
44
- sender: string
45
- type: string
46
- status: string
47
- };
121
+ tx: TxMeta;
48
122
  insert(table: string, row: Record<string, unknown>): void;
49
123
  update(table: string, where: Record<string, unknown>, set: Record<string, unknown>): void;
50
124
  upsert(table: string, key: Record<string, unknown>, row: Record<string, unknown>): void;
51
125
  delete(table: string, where: Record<string, unknown>): void;
126
+ /** Partial update — sets only specified fields, preserves others */
127
+ patch(table: string, where: Record<string, unknown>, set: Record<string, unknown>): void;
128
+ /** Find-then-merge-or-insert. Values can be functions: (existing) => newValue */
129
+ patchOrInsert(table: string, key: Record<string, unknown>, row: Record<string, ComputedValue>): Promise<void>;
52
130
  findOne(table: string, where: Record<string, unknown>): Promise<Record<string, unknown> | null>;
53
131
  findMany(table: string, where: Record<string, unknown>): Promise<Record<string, unknown>[]>;
132
+ /** Format a bigint amount with decimal places */
133
+ formatUnits(value: bigint, decimals: number): string;
134
+ /** Count rows matching filter */
135
+ count(table: string, where?: Record<string, unknown>): Promise<number>;
136
+ /** Sum a numeric column */
137
+ sum(table: string, column: string, where?: Record<string, unknown>): Promise<bigint>;
138
+ /** Min of a numeric column */
139
+ min(table: string, column: string, where?: Record<string, unknown>): Promise<bigint | null>;
140
+ /** Max of a numeric column */
141
+ max(table: string, column: string, where?: Record<string, unknown>): Promise<bigint | null>;
142
+ /** Count distinct values in a column */
143
+ countDistinct(table: string, column: string, where?: Record<string, unknown>): Promise<number>;
54
144
  }
55
145
  /** Handler function that processes events and writes to the subgraph */
56
146
  type SubgraphHandler = (event: Record<string, unknown>, ctx: SubgraphContext) => Promise<void> | void;
57
- /**
58
- * Derive the source key used to look up handlers.
59
- * - { contract: "SP123.market", function: "list" } → "SP123.market::list"
60
- * - { contract: "SP123.market", event: "sale" } → "SP123.market::sale"
61
- * - { contract: "SP123.market" } → "SP123.market"
62
- * - { type: "stx_transfer" } → "stx_transfer"
63
- */
64
- declare function sourceKey(source: SubgraphSource): string;
65
147
  /** Complete subgraph definition */
66
148
  interface SubgraphDefinition {
67
149
  /** Unique subgraph name (lowercase, alphanumeric + hyphens) */
@@ -72,11 +154,11 @@ interface SubgraphDefinition {
72
154
  description?: string;
73
155
  /** Block height to start indexing from (default: 1) */
74
156
  startBlock?: number;
75
- /** What blockchain data to process one or more source filters */
76
- sources: SubgraphSource[];
157
+ /** Named source filterskeys become handler keys */
158
+ sources: Record<string, SubgraphFilter>;
77
159
  /** Tables in this subgraph */
78
160
  schema: SubgraphSchema;
79
- /** Keyed handler functions — keys match sourceKey() output, "*" is catch-all */
161
+ /** Handler functions — keys must match source names (or "*" for catch-all) */
80
162
  handlers: Record<string, SubgraphHandler>;
81
163
  }
82
- export { sourceKey, SubgraphTable, SubgraphSource, SubgraphSchema, SubgraphHandler, SubgraphDefinition, SubgraphContext, SubgraphColumn, ColumnType };
164
+ export { TxMeta, SubgraphTable, SubgraphSchema, SubgraphHandler, SubgraphFilter, SubgraphDefinition, SubgraphContext, SubgraphColumn, StxTransferFilter, StxMintFilter, StxLockFilter, StxBurnFilter, PrintEventFilter, NftTransferFilter, NftMintFilter, NftBurnFilter, FtTransferFilter, FtMintFilter, FtBurnFilter, ContractDeployFilter, ContractCallFilter, ComputedValue, ColumnType };
package/dist/src/types.js CHANGED
@@ -1,22 +1,3 @@
1
- import { createRequire } from "node:module";
2
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
1
 
4
- // src/types.ts
5
- function sourceKey(source) {
6
- if (source.contract) {
7
- if (source.function)
8
- return `${source.contract}::${source.function}`;
9
- if (source.event)
10
- return `${source.contract}::${source.event}`;
11
- return source.contract;
12
- }
13
- if (source.type)
14
- return source.type;
15
- return "*";
16
- }
17
- export {
18
- sourceKey
19
- };
20
-
21
- //# debugId=8321D6D438D2419C64756E2164756E21
2
+ //# debugId=F2B76011AEAE140064756E2164756E21
22
3
  //# sourceMappingURL=types.js.map
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/types.ts"],
3
+ "sources": [],
4
4
  "sourcesContent": [
5
- "/** Supported column types for subgraph schemas */\nexport type ColumnType =\n\t| \"text\"\n\t| \"uint\"\n\t| \"int\"\n\t| \"principal\"\n\t| \"boolean\"\n\t| \"timestamp\"\n\t| \"jsonb\";\n\n/** Column definition in a subgraph table */\nexport interface SubgraphColumn {\n\ttype: ColumnType;\n\tnullable?: boolean;\n\tindexed?: boolean;\n\tsearch?: boolean;\n\tdefault?: string | number | boolean;\n}\n\n/** Table definition within a subgraph schema */\nexport interface SubgraphTable {\n\tcolumns: Record<string, SubgraphColumn>;\n\t/** Composite indexes (each entry is an array of column names) */\n\tindexes?: string[][];\n\t/** Unique key constraints (each entry is an array of column names). Required for upsert. */\n\tuniqueKeys?: string[][];\n}\n\n/** Subgraph schema — maps table names to table definitions */\nexport type SubgraphSchema = Record<string, SubgraphTable>;\n\n/** Source filter for what blockchain data this subgraph processes */\nexport interface SubgraphSource {\n\t/** Contract principal (e.g., SP000...::contract-name). Supports * wildcards. */\n\tcontract?: string;\n\t/** Event name/topic to filter on */\n\tevent?: string;\n\t/** Function name to filter on */\n\tfunction?: string;\n\t/** Transaction type filter (e.g., \"stx_transfer\", \"contract_call\") */\n\ttype?: string;\n\t/** Minimum amount filter (for stx_transfer sources) */\n\tminAmount?: bigint;\n}\n\n/** Context passed to subgraph handlers during event processing */\nexport interface SubgraphContext {\n\tblock: {\n\t\theight: number;\n\t\thash: string;\n\t\ttimestamp: number;\n\t\tburnBlockHeight: number;\n\t};\n\ttx: { txId: string; sender: string; type: string; status: string };\n\tinsert(table: string, row: Record<string, unknown>): void;\n\tupdate(\n\t\ttable: string,\n\t\twhere: Record<string, unknown>,\n\t\tset: Record<string, unknown>,\n\t): void;\n\tupsert(\n\t\ttable: string,\n\t\tkey: Record<string, unknown>,\n\t\trow: Record<string, unknown>,\n\t): void;\n\tdelete(table: string, where: Record<string, unknown>): void;\n\tfindOne(\n\t\ttable: string,\n\t\twhere: Record<string, unknown>,\n\t): Promise<Record<string, unknown> | null>;\n\tfindMany(\n\t\ttable: string,\n\t\twhere: Record<string, unknown>,\n\t): Promise<Record<string, unknown>[]>;\n}\n\n/** Handler function that processes events and writes to the subgraph */\nexport type SubgraphHandler = (\n\tevent: Record<string, unknown>,\n\tctx: SubgraphContext,\n) => Promise<void> | void;\n\n/**\n * Derive the source key used to look up handlers.\n * - { contract: \"SP123.market\", function: \"list\" } → \"SP123.market::list\"\n * - { contract: \"SP123.market\", event: \"sale\" } → \"SP123.market::sale\"\n * - { contract: \"SP123.market\" } → \"SP123.market\"\n * - { type: \"stx_transfer\" } → \"stx_transfer\"\n */\nexport function sourceKey(source: SubgraphSource): string {\n\tif (source.contract) {\n\t\tif (source.function) return `${source.contract}::${source.function}`;\n\t\tif (source.event) return `${source.contract}::${source.event}`;\n\t\treturn source.contract;\n\t}\n\tif (source.type) return source.type;\n\treturn \"*\";\n}\n\n/** Complete subgraph definition */\nexport interface SubgraphDefinition {\n\t/** Unique subgraph name (lowercase, alphanumeric + hyphens) */\n\tname: string;\n\t/** Semantic version */\n\tversion?: string;\n\t/** Human description */\n\tdescription?: string;\n\t/** Block height to start indexing from (default: 1) */\n\tstartBlock?: number;\n\t/** What blockchain data to process — one or more source filters */\n\tsources: SubgraphSource[];\n\t/** Tables in this subgraph */\n\tschema: SubgraphSchema;\n\t/** Keyed handler functions — keys match sourceKey() output, \"*\" is catch-all */\n\thandlers: Record<string, SubgraphHandler>;\n}\n"
6
5
  ],
7
- "mappings": ";;;;AAyFO,SAAS,SAAS,CAAC,QAAgC;AAAA,EACzD,IAAI,OAAO,UAAU;AAAA,IACpB,IAAI,OAAO;AAAA,MAAU,OAAO,GAAG,OAAO,aAAa,OAAO;AAAA,IAC1D,IAAI,OAAO;AAAA,MAAO,OAAO,GAAG,OAAO,aAAa,OAAO;AAAA,IACvD,OAAO,OAAO;AAAA,EACf;AAAA,EACA,IAAI,OAAO;AAAA,IAAM,OAAO,OAAO;AAAA,EAC/B,OAAO;AAAA;",
8
- "debugId": "8321D6D438D2419C64756E2164756E21",
6
+ "mappings": "",
7
+ "debugId": "F2B76011AEAE140064756E2164756E21",
9
8
  "names": []
10
9
  }
@@ -18,19 +18,98 @@ interface SubgraphTable {
18
18
  }
19
19
  /** Subgraph schema — maps table names to table definitions */
20
20
  type SubgraphSchema = Record<string, SubgraphTable>;
21
- /** Source filter for what blockchain data this subgraph processes */
22
- interface SubgraphSource {
23
- /** Contract principal (e.g., SP000...::contract-name). Supports * wildcards. */
24
- contract?: string;
25
- /** Event name/topic to filter on */
26
- event?: string;
27
- /** Function name to filter on */
28
- function?: string;
29
- /** Transaction type filter (e.g., "stx_transfer", "contract_call") */
30
- type?: string;
31
- /** Minimum amount filter (for stx_transfer sources) */
21
+ /** STX event filters */
22
+ interface StxTransferFilter {
23
+ type: "stx_transfer";
24
+ sender?: string;
25
+ recipient?: string;
32
26
  minAmount?: bigint;
27
+ maxAmount?: bigint;
33
28
  }
29
+ interface StxMintFilter {
30
+ type: "stx_mint";
31
+ recipient?: string;
32
+ minAmount?: bigint;
33
+ }
34
+ interface StxBurnFilter {
35
+ type: "stx_burn";
36
+ sender?: string;
37
+ minAmount?: bigint;
38
+ }
39
+ interface StxLockFilter {
40
+ type: "stx_lock";
41
+ lockedAddress?: string;
42
+ minAmount?: bigint;
43
+ }
44
+ /** FT event filters */
45
+ interface FtTransferFilter {
46
+ type: "ft_transfer";
47
+ assetIdentifier?: string;
48
+ sender?: string;
49
+ recipient?: string;
50
+ minAmount?: bigint;
51
+ }
52
+ interface FtMintFilter {
53
+ type: "ft_mint";
54
+ assetIdentifier?: string;
55
+ recipient?: string;
56
+ minAmount?: bigint;
57
+ }
58
+ interface FtBurnFilter {
59
+ type: "ft_burn";
60
+ assetIdentifier?: string;
61
+ sender?: string;
62
+ minAmount?: bigint;
63
+ }
64
+ /** NFT event filters */
65
+ interface NftTransferFilter {
66
+ type: "nft_transfer";
67
+ assetIdentifier?: string;
68
+ sender?: string;
69
+ recipient?: string;
70
+ }
71
+ interface NftMintFilter {
72
+ type: "nft_mint";
73
+ assetIdentifier?: string;
74
+ recipient?: string;
75
+ }
76
+ interface NftBurnFilter {
77
+ type: "nft_burn";
78
+ assetIdentifier?: string;
79
+ sender?: string;
80
+ }
81
+ /** Contract event filters */
82
+ interface ContractCallFilter {
83
+ type: "contract_call";
84
+ contractId?: string;
85
+ functionName?: string;
86
+ caller?: string;
87
+ /** ABI for typed event.args. If omitted, auto-fetched at deploy time. */
88
+ abi?: Record<string, unknown>;
89
+ }
90
+ interface ContractDeployFilter {
91
+ type: "contract_deploy";
92
+ deployer?: string;
93
+ contractName?: string;
94
+ }
95
+ interface PrintEventFilter {
96
+ type: "print_event";
97
+ contractId?: string;
98
+ topic?: string;
99
+ }
100
+ /** All subgraph filter types — discriminated on `type` */
101
+ type SubgraphFilter = StxTransferFilter | StxMintFilter | StxBurnFilter | StxLockFilter | FtTransferFilter | FtMintFilter | FtBurnFilter | NftTransferFilter | NftMintFilter | NftBurnFilter | ContractCallFilter | ContractDeployFilter | PrintEventFilter;
102
+ /** Transaction metadata available in handlers */
103
+ interface TxMeta {
104
+ txId: string;
105
+ sender: string;
106
+ type: string;
107
+ status: string;
108
+ contractId?: string | null;
109
+ functionName?: string | null;
110
+ }
111
+ /** Value or computed function that receives existing row */
112
+ type ComputedValue<T = unknown> = T | ((existing: Record<string, unknown> | null) => T);
34
113
  /** Context passed to subgraph handlers during event processing */
35
114
  interface SubgraphContext {
36
115
  block: {
@@ -39,18 +118,29 @@ interface SubgraphContext {
39
118
  timestamp: number
40
119
  burnBlockHeight: number
41
120
  };
42
- tx: {
43
- txId: string
44
- sender: string
45
- type: string
46
- status: string
47
- };
121
+ tx: TxMeta;
48
122
  insert(table: string, row: Record<string, unknown>): void;
49
123
  update(table: string, where: Record<string, unknown>, set: Record<string, unknown>): void;
50
124
  upsert(table: string, key: Record<string, unknown>, row: Record<string, unknown>): void;
51
125
  delete(table: string, where: Record<string, unknown>): void;
126
+ /** Partial update — sets only specified fields, preserves others */
127
+ patch(table: string, where: Record<string, unknown>, set: Record<string, unknown>): void;
128
+ /** Find-then-merge-or-insert. Values can be functions: (existing) => newValue */
129
+ patchOrInsert(table: string, key: Record<string, unknown>, row: Record<string, ComputedValue>): Promise<void>;
52
130
  findOne(table: string, where: Record<string, unknown>): Promise<Record<string, unknown> | null>;
53
131
  findMany(table: string, where: Record<string, unknown>): Promise<Record<string, unknown>[]>;
132
+ /** Format a bigint amount with decimal places */
133
+ formatUnits(value: bigint, decimals: number): string;
134
+ /** Count rows matching filter */
135
+ count(table: string, where?: Record<string, unknown>): Promise<number>;
136
+ /** Sum a numeric column */
137
+ sum(table: string, column: string, where?: Record<string, unknown>): Promise<bigint>;
138
+ /** Min of a numeric column */
139
+ min(table: string, column: string, where?: Record<string, unknown>): Promise<bigint | null>;
140
+ /** Max of a numeric column */
141
+ max(table: string, column: string, where?: Record<string, unknown>): Promise<bigint | null>;
142
+ /** Count distinct values in a column */
143
+ countDistinct(table: string, column: string, where?: Record<string, unknown>): Promise<number>;
54
144
  }
55
145
  /** Handler function that processes events and writes to the subgraph */
56
146
  type SubgraphHandler = (event: Record<string, unknown>, ctx: SubgraphContext) => Promise<void> | void;
@@ -64,11 +154,11 @@ interface SubgraphDefinition {
64
154
  description?: string;
65
155
  /** Block height to start indexing from (default: 1) */
66
156
  startBlock?: number;
67
- /** What blockchain data to process one or more source filters */
68
- sources: SubgraphSource[];
157
+ /** Named source filterskeys become handler keys */
158
+ sources: Record<string, SubgraphFilter>;
69
159
  /** Tables in this subgraph */
70
160
  schema: SubgraphSchema;
71
- /** Keyed handler functions — keys match sourceKey() output, "*" is catch-all */
161
+ /** Handler functions — keys must match source names (or "*" for catch-all) */
72
162
  handlers: Record<string, SubgraphHandler>;
73
163
  }
74
164
  import { z } from "zod/v4";
@@ -77,10 +167,10 @@ declare const ColumnTypeSchema: z.ZodType<ColumnType>;
77
167
  declare const SubgraphColumnSchema: z.ZodType<SubgraphColumn>;
78
168
  declare const SubgraphTableSchema: z.ZodType<SubgraphTable>;
79
169
  declare const SubgraphSchemaSchema: z.ZodType<Record<string, SubgraphTable>>;
80
- declare const SubgraphSourceSchema: z.ZodType<SubgraphSource>;
170
+ declare const SubgraphFilterSchema: z.ZodType<SubgraphFilter>;
81
171
  declare const SubgraphDefinitionSchema: z.ZodType<SubgraphDefinition>;
82
172
  /**
83
173
  * Validates a subgraph definition, returning the parsed result or throwing on failure.
84
174
  */
85
175
  declare function validateSubgraphDefinition(def: unknown): SubgraphDefinition;
86
- export { validateSubgraphDefinition, SubgraphTableSchema, SubgraphSourceSchema, SubgraphSchemaSchema, SubgraphNameSchema, SubgraphDefinitionSchema, SubgraphColumnSchema, ColumnTypeSchema };
176
+ export { validateSubgraphDefinition, SubgraphTableSchema, SubgraphSchemaSchema, SubgraphNameSchema, SubgraphFilterSchema, SubgraphDefinitionSchema, SubgraphColumnSchema, ColumnTypeSchema };