create-ponder 0.5.0-next.3 → 0.5.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 (56) hide show
  1. package/README.md +2 -2
  2. package/dist/index.js +53 -18
  3. package/package.json +1 -1
  4. package/templates/empty/package.json +1 -0
  5. package/templates/empty/ponder-env.d.ts +1 -0
  6. package/templates/empty/ponder.config.ts +1 -1
  7. package/templates/empty/src/api/index.ts +5 -0
  8. package/templates/etherscan/package.json +1 -0
  9. package/templates/etherscan/ponder-env.d.ts +1 -0
  10. package/templates/feature-api-functions/abis/erc20ABI.ts +147 -0
  11. package/templates/{feature-callTrace → feature-api-functions}/package.json +2 -1
  12. package/templates/{feature-callTrace → feature-api-functions}/ponder-env.d.ts +2 -1
  13. package/templates/feature-api-functions/ponder.config.ts +21 -0
  14. package/templates/feature-api-functions/ponder.schema.ts +50 -0
  15. package/templates/feature-api-functions/src/api/index.ts +47 -0
  16. package/templates/feature-blocks/package.json +1 -0
  17. package/templates/feature-blocks/ponder-env.d.ts +1 -0
  18. package/templates/feature-call-traces/package.json +1 -0
  19. package/templates/feature-call-traces/ponder-env.d.ts +1 -0
  20. package/templates/feature-factory/package.json +1 -0
  21. package/templates/feature-factory/ponder-env.d.ts +1 -0
  22. package/templates/feature-filter/package.json +1 -0
  23. package/templates/feature-filter/ponder-env.d.ts +1 -0
  24. package/templates/feature-multichain/package.json +1 -0
  25. package/templates/feature-multichain/ponder-env.d.ts +1 -0
  26. package/templates/feature-proxy/package.json +1 -0
  27. package/templates/feature-proxy/ponder-env.d.ts +1 -0
  28. package/templates/feature-read-contract/package.json +1 -0
  29. package/templates/feature-read-contract/ponder-env.d.ts +1 -0
  30. package/templates/project-friendtech/package.json +1 -0
  31. package/templates/project-friendtech/ponder-env.d.ts +1 -0
  32. package/templates/project-uniswap-v3-flash/package.json +1 -0
  33. package/templates/project-uniswap-v3-flash/ponder-env.d.ts +1 -0
  34. package/templates/reference-erc1155/package.json +1 -0
  35. package/templates/reference-erc1155/ponder-env.d.ts +1 -0
  36. package/templates/reference-erc20/package.json +1 -1
  37. package/templates/reference-erc20/ponder-env.d.ts +1 -0
  38. package/templates/reference-erc4626/package.json +1 -0
  39. package/templates/reference-erc4626/ponder-env.d.ts +1 -0
  40. package/templates/reference-erc721/package.json +1 -0
  41. package/templates/reference-erc721/ponder-env.d.ts +1 -0
  42. package/templates/subgraph/package.json +1 -0
  43. package/templates/subgraph/ponder-env.d.ts +1 -0
  44. package/templates/feature-callTrace/ponder.config.ts +0 -22
  45. package/templates/feature-callTrace/ponder.schema.ts +0 -11
  46. package/templates/feature-callTrace/src/index.ts +0 -33
  47. package/templates/reference-erc20/sqlite/ponder.db +0 -0
  48. package/templates/reference-erc20/sqlite/ponder_cache.db +0 -0
  49. package/templates/reference-erc20/sqlite/ponder_sync.db +0 -0
  50. package/templates/reference-erc20/src/api/index.ts +0 -26
  51. package/templates/reference-erc20/src/server/index.ts +0 -20
  52. /package/templates/{feature-callTrace → feature-api-functions}/_dot_env.local +0 -0
  53. /package/templates/{feature-callTrace → feature-api-functions}/_dot_eslintrc.json +0 -0
  54. /package/templates/{feature-callTrace → feature-api-functions}/_dot_gitignore +0 -0
  55. /package/templates/{reference-erc20/src/indexing → feature-api-functions/src}/index.ts +0 -0
  56. /package/templates/{feature-callTrace → feature-api-functions}/tsconfig.json +0 -0
package/README.md CHANGED
@@ -33,7 +33,7 @@ Join [Ponder's telegram chat](https://t.me/ponder_sh) for support, feedback, and
33
33
 
34
34
  ### 1. Run `create-ponder`
35
35
 
36
- You will be asked for a project name, and if you are using a [template](https://ponder.sh/api-reference/create-ponder#templates) (recommended). Then, the CLI will create a project directory, install dependencies, and initialize a git repository.
36
+ You will be asked for a project name, and if you are using a [template](https://ponder.sh/docs/api-reference/create-ponder#templates) (recommended). Then, the CLI will create a project directory, install dependencies, and initialize a git repository.
37
37
 
38
38
  ```bash
39
39
  npm init ponder@latest
@@ -128,7 +128,7 @@ ponder.on("BaseRegistrar:NameRegistered", async ({ event, context }) => {
128
128
  });
129
129
  ```
130
130
 
131
- See the [create & update records](https://ponder.sh/docs/guides/create-update-records) docs for a detailed guide on writing indexing functions.
131
+ See the [create & update records](https://ponder.sh/docs/indexing/create-update-records) docs for a detailed guide on writing indexing functions.
132
132
 
133
133
  ### 6. Query the GraphQL API
134
134
 
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ import { default as prompts } from "prompts";
16
16
  // package.json
17
17
  var package_default = {
18
18
  name: "create-ponder",
19
- version: "0.5.0-next.3",
19
+ version: "0.5.1",
20
20
  type: "module",
21
21
  description: "A CLI tool to create Ponder apps",
22
22
  license: "MIT",
@@ -484,8 +484,6 @@ var chainIdByGraphNetwork = {
484
484
  fantom: 250,
485
485
  "fantom-testnet": 4002,
486
486
  bsc: 56,
487
- chapel: -1,
488
- clover: 0,
489
487
  avalanche: 43114,
490
488
  fuji: 43113,
491
489
  celo: 42220,
@@ -493,7 +491,6 @@ var chainIdByGraphNetwork = {
493
491
  fuse: 122,
494
492
  moonbeam: 1284,
495
493
  moonriver: 1285,
496
- mbase: -1,
497
494
  base: 8453,
498
495
  "base-sepolia": 84532,
499
496
  "arbitrum-one": 42161,
@@ -504,7 +501,7 @@ var chainIdByGraphNetwork = {
504
501
  "aurora-testnet": 1313161555
505
502
  };
506
503
  var getGraphProtocolChainId = (networkName) => {
507
- return chainIdByGraphNetwork[networkName];
504
+ return chainIdByGraphNetwork[networkName] ?? 0;
508
505
  };
509
506
  var subgraphYamlFileNames = ["subgraph.yaml"].concat(
510
507
  Object.keys(chainIdByGraphNetwork).map((n) => `subgraph-${n}.yaml`)
@@ -516,17 +513,33 @@ var validateGraphProtocolSource = (source) => {
516
513
  };
517
514
 
518
515
  // src/subgraph.ts
519
- var fetchIpfsFile = async (cid) => {
520
- const url = `https://ipfs.network.thegraph.com/api/v0/cat?arg=${cid}`;
516
+ var subgraphProviders = [
517
+ {
518
+ id: "thegraph",
519
+ name: "The Graph",
520
+ getUrl: (cid) => `https://ipfs.network.thegraph.com/api/v0/cat?arg=${cid}`
521
+ },
522
+ {
523
+ id: "satsuma",
524
+ name: "Alchemy Subgraph (Satsuma)",
525
+ getUrl: (cid) => `https://ipfs.satsuma.xyz/ipfs/${cid}`
526
+ }
527
+ ];
528
+ var fetchIpfsFile = async (cid, subgraphProvider) => {
529
+ const url = subgraphProvider.getUrl(cid);
521
530
  const response = await fetch(url);
522
531
  const contentRaw = await response.text();
523
532
  return contentRaw;
524
533
  };
525
534
  var fromSubgraphId = async ({
526
535
  rootDir,
527
- subgraphId
536
+ subgraphId,
537
+ subgraphProvider = "thegraph"
528
538
  }) => {
529
- const manifestRaw = await fetchIpfsFile(subgraphId);
539
+ const provider = subgraphProviders.find((p) => p.id === subgraphProvider);
540
+ if (!provider)
541
+ throw new Error(`Unknown subgraph provider: ${subgraphProvider}`);
542
+ const manifestRaw = await fetchIpfsFile(subgraphId, provider);
530
543
  const manifest = parse(manifestRaw);
531
544
  const contracts = {};
532
545
  manifest.dataSources.forEach((d) => {
@@ -545,7 +558,7 @@ var fromSubgraphId = async ({
545
558
  const abis = {};
546
559
  await Promise.all(
547
560
  abiFiles.map(async (abi) => {
548
- const abiContent = await fetchIpfsFile(abi.file["/"].slice(6));
561
+ const abiContent = await fetchIpfsFile(abi.file["/"].slice(6), provider);
549
562
  const abiPath = path3.join(rootDir, `./abis/${abi.name}Abi.ts`);
550
563
  writeFileSync2(
551
564
  abiPath,
@@ -562,10 +575,6 @@ var fromSubgraphId = async ({
562
575
  const ponderContracts = dataSources.map((sourceInvalid) => {
563
576
  const source = validateGraphProtocolSource(sourceInvalid);
564
577
  const network = source.network || "mainnet";
565
- const chainId = getGraphProtocolChainId(network);
566
- if (!chainId || chainId === -1) {
567
- throw new Error(`Unhandled network name: ${network}`);
568
- }
569
578
  const abiRelativePath = `./abis/${source.source.abi}Abi.ts`;
570
579
  return {
571
580
  name: source.name,
@@ -582,10 +591,11 @@ var fromSubgraphId = async ({
582
591
  const contractsObject = {};
583
592
  const networksObject = {};
584
593
  ponderContracts.forEach((pc) => {
594
+ const chainId = getGraphProtocolChainId(pc.network);
585
595
  contractsObject[pc.name] = pc;
586
596
  networksObject[pc.network] = {
587
- chainId: getGraphProtocolChainId(pc.network),
588
- transport: `http(process.env.PONDER_RPC_URL_${getGraphProtocolChainId(pc.network)})`
597
+ chainId,
598
+ transport: `http(process.env.PONDER_RPC_URL_${chainId})`
589
599
  };
590
600
  contractsObject[pc.name].name = void 0;
591
601
  });
@@ -626,6 +636,11 @@ var templates = [
626
636
  title: "Feature - Custom event filter",
627
637
  description: "A Ponder app using an event filter"
628
638
  },
639
+ {
640
+ id: "feature-api-functions",
641
+ title: "Feature - Custom api functions",
642
+ description: "A Ponder app using a custom api functions"
643
+ },
629
644
  {
630
645
  id: "feature-blocks",
631
646
  title: "Feature - Block filter",
@@ -776,7 +791,20 @@ async function run({
776
791
  }
777
792
  }
778
793
  let subgraph = options.subgraph;
794
+ let subgraphProvider = options.subgraphProvider;
779
795
  if (templateMeta.id === "subgraph") {
796
+ if (subgraphProvider === void 0) {
797
+ const result = await prompts({
798
+ name: "subgraphProvider",
799
+ message: "Which provider is the subgraph deployed to?",
800
+ type: "select",
801
+ choices: subgraphProviders.map(({ id, name }) => ({
802
+ title: name,
803
+ value: id
804
+ }))
805
+ });
806
+ subgraphProvider = result.subgraphProvider;
807
+ }
780
808
  if (!subgraph) {
781
809
  const result = await prompts({
782
810
  type: "text",
@@ -811,7 +839,11 @@ async function run({
811
839
  }
812
840
  if (templateMeta.id === "subgraph") {
813
841
  const result = await oraPromise(
814
- fromSubgraphId({ rootDir: projectPath, subgraphId: subgraph }),
842
+ fromSubgraphId({
843
+ rootDir: projectPath,
844
+ subgraphId: subgraph,
845
+ subgraphProvider
846
+ }),
815
847
  {
816
848
  text: "Fetching subgraph metadata. This may take a few seconds.",
817
849
  failText: "Failed to fetch subgraph metadata.",
@@ -967,7 +999,10 @@ async function run({
967
999
  const cli = cac(package_default.name).version(package_default.version).usage(`${pico5.green("<directory>")} [options]`).option(
968
1000
  "-t, --template [id]",
969
1001
  `Use a template. Options: ${templates.map(({ id }) => id).join(", ")}`
970
- ).option("--etherscan [url]", "Use the Etherscan template").option("--subgraph [id]", "Use the subgraph template").option("--npm", "Use npm as your package manager").option("--pnpm", "Use pnpm as your package manager").option("--yarn", "Use yarn as your package manager").option("--skip-git", "Skip initializing a git repository").option(
1002
+ ).option("--etherscan [url]", "Use the Etherscan template").option("--subgraph [id]", "Use the subgraph template").option(
1003
+ "--subgraph-provider [provider]",
1004
+ `Specify the subgraph provider. Options: ${subgraphProviders.map(({ id }) => id).join(", ")}`
1005
+ ).option("--npm", "Use npm as your package manager").option("--pnpm", "Use pnpm as your package manager").option("--yarn", "Use yarn as your package manager").option("--skip-git", "Skip initializing a git repository").option(
971
1006
  "--etherscan-api-key [key]",
972
1007
  "Etherscan API key for Etherscan template"
973
1008
  ).help();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ponder",
3
- "version": "0.5.0-next.3",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
5
  "description": "A CLI tool to create Ponder apps",
6
6
  "license": "MIT",
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "^0.0.95",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.3"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -14,7 +14,7 @@ export default createConfig({
14
14
  ExampleContract: {
15
15
  network: "mainnet",
16
16
  abi: ExampleContractAbi,
17
- address: "0x0",
17
+ address: "0x0000000000000000000000000000000000000000",
18
18
  startBlock: 1234567,
19
19
  },
20
20
  },
@@ -0,0 +1,5 @@
1
+ import { ponder } from "@/generated";
2
+ import { graphql } from "@ponder/core";
3
+
4
+ ponder.use("/graphql", graphql());
5
+ ponder.use("/", graphql());
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "^0.0.95",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.3"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -0,0 +1,147 @@
1
+ export const erc20ABI = [
2
+ {
3
+ stateMutability: "view",
4
+ type: "function",
5
+ inputs: [],
6
+ name: "DOMAIN_SEPARATOR",
7
+ outputs: [{ name: "", internalType: "bytes32", type: "bytes32" }],
8
+ },
9
+ {
10
+ stateMutability: "view",
11
+ type: "function",
12
+ inputs: [
13
+ { name: "", internalType: "address", type: "address" },
14
+ { name: "", internalType: "address", type: "address" },
15
+ ],
16
+ name: "allowance",
17
+ outputs: [{ name: "", internalType: "uint256", type: "uint256" }],
18
+ },
19
+ {
20
+ stateMutability: "nonpayable",
21
+ type: "function",
22
+ inputs: [
23
+ { name: "spender", internalType: "address", type: "address" },
24
+ { name: "amount", internalType: "uint256", type: "uint256" },
25
+ ],
26
+ name: "approve",
27
+ outputs: [{ name: "", internalType: "bool", type: "bool" }],
28
+ },
29
+ {
30
+ stateMutability: "view",
31
+ type: "function",
32
+ inputs: [{ name: "", internalType: "address", type: "address" }],
33
+ name: "balanceOf",
34
+ outputs: [{ name: "", internalType: "uint256", type: "uint256" }],
35
+ },
36
+ {
37
+ stateMutability: "view",
38
+ type: "function",
39
+ inputs: [],
40
+ name: "decimals",
41
+ outputs: [{ name: "", internalType: "uint8", type: "uint8" }],
42
+ },
43
+ {
44
+ stateMutability: "view",
45
+ type: "function",
46
+ inputs: [],
47
+ name: "name",
48
+ outputs: [{ name: "", internalType: "string", type: "string" }],
49
+ },
50
+ {
51
+ stateMutability: "view",
52
+ type: "function",
53
+ inputs: [{ name: "", internalType: "address", type: "address" }],
54
+ name: "nonces",
55
+ outputs: [{ name: "", internalType: "uint256", type: "uint256" }],
56
+ },
57
+ {
58
+ stateMutability: "nonpayable",
59
+ type: "function",
60
+ inputs: [
61
+ { name: "owner", internalType: "address", type: "address" },
62
+ { name: "spender", internalType: "address", type: "address" },
63
+ { name: "value", internalType: "uint256", type: "uint256" },
64
+ { name: "deadline", internalType: "uint256", type: "uint256" },
65
+ { name: "v", internalType: "uint8", type: "uint8" },
66
+ { name: "r", internalType: "bytes32", type: "bytes32" },
67
+ { name: "s", internalType: "bytes32", type: "bytes32" },
68
+ ],
69
+ name: "permit",
70
+ outputs: [],
71
+ },
72
+ {
73
+ stateMutability: "view",
74
+ type: "function",
75
+ inputs: [],
76
+ name: "symbol",
77
+ outputs: [{ name: "", internalType: "string", type: "string" }],
78
+ },
79
+ {
80
+ stateMutability: "view",
81
+ type: "function",
82
+ inputs: [],
83
+ name: "totalSupply",
84
+ outputs: [{ name: "", internalType: "uint256", type: "uint256" }],
85
+ },
86
+ {
87
+ stateMutability: "nonpayable",
88
+ type: "function",
89
+ inputs: [
90
+ { name: "to", internalType: "address", type: "address" },
91
+ { name: "amount", internalType: "uint256", type: "uint256" },
92
+ ],
93
+ name: "transfer",
94
+ outputs: [{ name: "", internalType: "bool", type: "bool" }],
95
+ },
96
+ {
97
+ stateMutability: "nonpayable",
98
+ type: "function",
99
+ inputs: [
100
+ { name: "from", internalType: "address", type: "address" },
101
+ { name: "to", internalType: "address", type: "address" },
102
+ { name: "amount", internalType: "uint256", type: "uint256" },
103
+ ],
104
+ name: "transferFrom",
105
+ outputs: [{ name: "", internalType: "bool", type: "bool" }],
106
+ },
107
+ {
108
+ type: "event",
109
+ anonymous: false,
110
+ inputs: [
111
+ {
112
+ name: "owner",
113
+ internalType: "address",
114
+ type: "address",
115
+ indexed: true,
116
+ },
117
+ {
118
+ name: "spender",
119
+ internalType: "address",
120
+ type: "address",
121
+ indexed: true,
122
+ },
123
+ {
124
+ name: "amount",
125
+ internalType: "uint256",
126
+ type: "uint256",
127
+ indexed: false,
128
+ },
129
+ ],
130
+ name: "Approval",
131
+ },
132
+ {
133
+ type: "event",
134
+ anonymous: false,
135
+ inputs: [
136
+ { name: "from", internalType: "address", type: "address", indexed: true },
137
+ { name: "to", internalType: "address", type: "address", indexed: true },
138
+ {
139
+ name: "amount",
140
+ internalType: "uint256",
141
+ type: "uint256",
142
+ indexed: false,
143
+ },
144
+ ],
145
+ name: "Transfer",
146
+ },
147
+ ] as const;
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "ponder-examples-feature-callTrace",
2
+ "name": "ponder-examples-feature-api-functions",
3
3
  "private": true,
4
4
  "type": "module",
5
5
  "scripts": {
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.9"
16
17
  },
17
18
  "devDependencies": {
@@ -1,7 +1,7 @@
1
1
  // This file enables type checking and editor autocomplete for this Ponder project.
2
2
  // After upgrading, you may find that changes have been made to this file.
3
3
  // If this happens, please commit the changes. Do not manually edit this file.
4
- // See https://ponder.sh/docs/guides/typescript for more information.
4
+ // See https://ponder.sh/docs/getting-started/installation#typescript for more information.
5
5
 
6
6
  declare module "@/generated" {
7
7
  import type { Virtual } from "@ponder/core";
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -0,0 +1,21 @@
1
+ import { createConfig } from "@ponder/core";
2
+ import { http } from "viem";
3
+ import { erc20ABI } from "./abis/erc20ABI";
4
+
5
+ export default createConfig({
6
+ networks: {
7
+ mainnet: {
8
+ chainId: 1,
9
+ transport: http(process.env.PONDER_RPC_URL_1),
10
+ },
11
+ },
12
+ contracts: {
13
+ ERC20: {
14
+ network: "mainnet",
15
+ abi: erc20ABI,
16
+ address: "0x32353A6C91143bfd6C7d363B546e62a9A2489A20",
17
+ startBlock: 13142655,
18
+ endBlock: 13150000,
19
+ },
20
+ },
21
+ });
@@ -0,0 +1,50 @@
1
+ import { createSchema } from "@ponder/core";
2
+
3
+ export default createSchema((p) => ({
4
+ Account: p.createTable({
5
+ id: p.hex(),
6
+ balance: p.bigint(),
7
+ isOwner: p.boolean(),
8
+
9
+ allowances: p.many("Allowance.ownerId"),
10
+ approvalOwnerEvents: p.many("ApprovalEvent.ownerId"),
11
+ approvalSpenderEvents: p.many("ApprovalEvent.spenderId"),
12
+ transferFromEvents: p.many("TransferEvent.fromId"),
13
+ transferToEvents: p.many("TransferEvent.toId"),
14
+ }),
15
+ Allowance: p.createTable({
16
+ id: p.string(),
17
+ amount: p.bigint(),
18
+
19
+ ownerId: p.hex().references("Account.id"),
20
+ spenderId: p.hex().references("Account.id"),
21
+
22
+ owner: p.one("ownerId"),
23
+ spender: p.one("spenderId"),
24
+ }),
25
+ TransferEvent: p.createTable(
26
+ {
27
+ id: p.string(),
28
+ amount: p.bigint(),
29
+ timestamp: p.int(),
30
+
31
+ fromId: p.hex().references("Account.id"),
32
+ toId: p.hex().references("Account.id"),
33
+
34
+ from: p.one("fromId"),
35
+ to: p.one("toId"),
36
+ },
37
+ { fromIdIndex: p.index("fromId") },
38
+ ),
39
+ ApprovalEvent: p.createTable({
40
+ id: p.string(),
41
+ amount: p.bigint(),
42
+ timestamp: p.int(),
43
+
44
+ ownerId: p.hex().references("Account.id"),
45
+ spenderId: p.hex().references("Account.id"),
46
+
47
+ owner: p.one("ownerId"),
48
+ spender: p.one("spenderId"),
49
+ }),
50
+ }));
@@ -0,0 +1,47 @@
1
+ import { ponder } from "@/generated";
2
+ import { count, desc, eq, graphql, or, replaceBigInts } from "@ponder/core";
3
+ import { formatEther, getAddress } from "viem";
4
+
5
+ ponder.use("/graphql", graphql());
6
+
7
+ ponder.get("/count", async (c) => {
8
+ const result = await c.db
9
+ .select({ count: count() })
10
+ .from(c.tables.TransferEvent);
11
+
12
+ if (result.length === 0) return c.text("0");
13
+ return c.text(String(result[0]!.count));
14
+ });
15
+
16
+ ponder.get("/count/:address", async (c) => {
17
+ const account = getAddress(c.req.param("address"));
18
+ const { TransferEvent } = c.tables;
19
+
20
+ const result = await c.db
21
+ .select({ count: count() })
22
+ .from(c.tables.TransferEvent)
23
+ .where(
24
+ or(eq(TransferEvent.fromId, account), eq(TransferEvent.toId, account)),
25
+ );
26
+
27
+ if (result.length === 0) return c.text("0");
28
+ return c.text(String(result[0]!.count));
29
+ });
30
+
31
+ ponder.get("/whale-transfers", async (c) => {
32
+ const { TransferEvent, Account } = c.tables;
33
+
34
+ // Top 10 transfers from whale accounts
35
+ const result = await c.db
36
+ .select({
37
+ amount: TransferEvent.amount,
38
+ senderBalance: Account.balance,
39
+ })
40
+ .from(TransferEvent)
41
+ .innerJoin(Account, eq(TransferEvent.fromId, Account.id))
42
+ .orderBy(desc(Account.balance))
43
+ .limit(10);
44
+
45
+ if (result.length === 0) return c.text("Not found", 500);
46
+ return c.json(replaceBigInts(result, (b) => formatEther(b)));
47
+ });
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.9"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.9"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -13,6 +13,7 @@
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
15
  "abitype": "^0.10.2",
16
+ "hono": "^4.5.0",
16
17
  "viem": "^1.19.9"
17
18
  },
18
19
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.9"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.9"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.9"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.9"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.9"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.9"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.9"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
- "hono": "^4.4.6",
15
+ "hono": "^4.5.0",
16
16
  "viem": "^1.19.9"
17
17
  },
18
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.9"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "workspace:*",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.9"
16
17
  },
17
18
  "devDependencies": {
@@ -21,6 +21,7 @@ declare module "@/generated" {
21
21
  schema,
22
22
  name
23
23
  >;
24
+ export type ApiContext = Virtual.Drizzle<schema>;
24
25
  export type IndexingFunctionArgs<name extends EventNames = EventNames> =
25
26
  Virtual.IndexingFunctionArgs<config, schema, name>;
26
27
  export type Schema = Virtual.Schema<schema>;
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@ponder/core": "^0.0.95",
15
+ "hono": "^4.5.0",
15
16
  "viem": "^1.19.3"
16
17
  },
17
18
  "devDependencies": {
@@ -25,6 +25,7 @@ declare module "@/generated" {
25
25
  Schema,
26
26
  name
27
27
  >;
28
+ export type ApiContext = Virtual.Drizzle<schema>;
28
29
  export type IndexingFunctionArgs<name extends EventNames = EventNames> = {
29
30
  event: Event<name>;
30
31
  context: Context<name>;
@@ -1,22 +0,0 @@
1
- import { createConfig } from "@ponder/core";
2
- import { http, Abi, multicall3Abi } from "viem";
3
- import { mainnet } from "viem/chains";
4
-
5
- export default createConfig({
6
- networks: {
7
- mainnet: {
8
- chainId: 1,
9
- transport: http(process.env.PONDER_RPC_URL_1),
10
- },
11
- },
12
- contracts: {
13
- multicall3: {
14
- network: "mainnet",
15
- abi: multicall3Abi,
16
- address: mainnet.contracts.multicall3.address,
17
- startBlock: 19_800_000,
18
- includeFunctionCalls: true,
19
- maxBlockRange: 25,
20
- },
21
- },
22
- });
@@ -1,11 +0,0 @@
1
- import { createSchema } from "@ponder/core";
2
-
3
- export default createSchema((p) => ({
4
- multicalls: p.createTable({
5
- id: p.hex(),
6
- gasUsed: p.bigint(),
7
- bytes: p.int(),
8
- successfulCalls: p.int(),
9
- failedCalls: p.int(),
10
- }),
11
- }));
@@ -1,33 +0,0 @@
1
- import { ponder } from "@/generated";
2
-
3
- ponder.on("multicall3.aggregate3()", async ({ event, context }) => {
4
- await context.db.multicalls.upsert({
5
- id: event.trace.from,
6
- create: {
7
- gasUsed: event.trace.gasUsed,
8
- bytes: event.args[0].reduce<number>(
9
- (acc, cur) => acc + Math.ceil((cur.callData.length - 2) / 8),
10
- 0,
11
- ),
12
- successfulCalls: event.result.filter(({ success }) => success === true)
13
- .length,
14
- failedCalls: event.result.filter(({ success }) => success === false)
15
- .length,
16
- },
17
- update: ({ current }) => ({
18
- gasUsed: current.gasUsed + event.trace.gasUsed,
19
- bytes:
20
- current.bytes +
21
- event.args[0].reduce<number>(
22
- (acc, cur) => acc + Math.ceil((cur.callData.length - 2) / 8),
23
- 0,
24
- ),
25
- successfulCalls:
26
- current.successfulCalls +
27
- event.result.filter(({ success }) => success === true).length,
28
- failedCalls:
29
- current.failedCalls +
30
- event.result.filter(({ success }) => success === false).length,
31
- }),
32
- });
33
- });
@@ -1,26 +0,0 @@
1
- import { ponder } from "@/generated";
2
- import { graphql, sql } from "@ponder/core";
3
-
4
- // write file
5
- ponder.use("/graphql", graphql());
6
-
7
- ponder.get("/router", async (c) => {
8
- const db = c.get("db");
9
-
10
- // await db.query(`UPDATE "Account" SET "isOwner" = 1`);
11
- // if (Math.random() > 0.5) {
12
- // throw new Error("kyle");
13
- // }
14
-
15
- const v = 1;
16
-
17
- const account = await db.query<{ balance: bigint }>(
18
- sql`SELECT * FROM "Account" LIMIT ${v}`,
19
- );
20
-
21
- if (account.rows.length === 0) {
22
- return c.text("Not Found!");
23
- } else {
24
- return c.text(`Balance: ${account.rows[0]!.balance.toString()}`);
25
- }
26
- });
@@ -1,20 +0,0 @@
1
- import { ponder } from "@/generated";
2
- import { graphql } from "@ponder/core";
3
-
4
- ponder.use("/graphql", graphql());
5
-
6
- ponder.get("/router", async (c) => {
7
- const db = c.get("db");
8
-
9
- // await db.query(`UPDATE "Account" SET "isOwner" = 1`);
10
-
11
- const account = await db.query<{ balance: bigint }>(
12
- `SELECT * FROM "Account" LIMIT 1`,
13
- );
14
-
15
- if (account.rows.length === 0) {
16
- return c.text("Not Found!");
17
- } else {
18
- return c.text(`Balance: ${account.rows[0]!.balance.toString()}`);
19
- }
20
- });