create-ponder 0.0.18 → 0.0.37

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.
@@ -1,7 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export interface CreatePonderOptions {
3
- ponderRootDir: string;
4
- fromSubgraph?: string;
5
- fromEtherscan?: string;
6
- etherscanApiKey?: string;
7
- }
2
+ export {};
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const cac_1 = require("cac");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const prompts_1 = __importDefault(require("prompts"));
10
+ const common_1 = require("../common");
11
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
12
+ // @ts-ignore
13
+ const package_json_1 = __importDefault(require("../../../package.json"));
14
+ const index_1 = require("../index");
15
+ const createPonder = async () => {
16
+ const cli = (0, cac_1.cac)(package_json_1.default.name)
17
+ .version(package_json_1.default.version)
18
+ .usage("[options]")
19
+ .help()
20
+ .option("--dir [path]", "Path to directory for generated project")
21
+ .option("--from-subgraph-id [id]", "Subgraph deployment ID")
22
+ .option("--from-subgraph-repo [path]", "Path to subgraph repository")
23
+ .option("--from-etherscan [url]", "Link to etherscan contract page")
24
+ .option("--etherscan-api-key [key]", "Etherscan API key");
25
+ const parsed = cli.parse(process.argv);
26
+ const options = parsed.options;
27
+ if (options.help) {
28
+ process.exit(0);
29
+ }
30
+ const { fromEtherscan, fromSubgraphId, fromSubgraphRepo } = options;
31
+ // Validate CLI options.
32
+ if ((fromSubgraphId && fromSubgraphRepo) ||
33
+ (fromSubgraphId && fromEtherscan) ||
34
+ (fromSubgraphRepo && fromEtherscan)) {
35
+ throw new Error(`Cannot specify more than one "--from" option:\n --from-subgraph\n --from-etherscan-id\n --from-etherscan-repo`);
36
+ }
37
+ const { projectName } = await (0, prompts_1.default)({
38
+ type: "text",
39
+ name: "projectName",
40
+ message: "What is your project named?",
41
+ initial: "my-app",
42
+ });
43
+ // Get template from options if provided.
44
+ let template = undefined;
45
+ if (fromEtherscan) {
46
+ template = { kind: common_1.TemplateKind.ETHERSCAN, link: fromEtherscan };
47
+ }
48
+ if (fromSubgraphId) {
49
+ template = { kind: common_1.TemplateKind.SUBGRAPH_ID, id: fromSubgraphId };
50
+ }
51
+ if (fromSubgraphRepo) {
52
+ template = { kind: common_1.TemplateKind.SUBGRAPH_REPO, path: fromSubgraphRepo };
53
+ }
54
+ // Get template from prompts if not provided.
55
+ if (!fromSubgraphId && !fromSubgraphRepo && !fromEtherscan) {
56
+ const { template: templateKind } = await (0, prompts_1.default)({
57
+ type: "select",
58
+ name: "template",
59
+ message: "Would you like to use a template for this project?",
60
+ choices: [
61
+ { title: "None" },
62
+ { title: "Etherscan contract link" },
63
+ { title: "Subgraph ID" },
64
+ { title: "Subgraph repository" },
65
+ ],
66
+ });
67
+ if (templateKind === common_1.TemplateKind.ETHERSCAN) {
68
+ const { link } = await (0, prompts_1.default)({
69
+ type: "text",
70
+ name: "link",
71
+ message: "Enter an Etherscan contract link",
72
+ initial: "https://etherscan.io/address/0x97...",
73
+ });
74
+ template = { kind: common_1.TemplateKind.ETHERSCAN, link };
75
+ }
76
+ if (templateKind === common_1.TemplateKind.SUBGRAPH_ID) {
77
+ const { id } = await (0, prompts_1.default)({
78
+ type: "text",
79
+ name: "id",
80
+ message: "Enter a subgraph deployment ID",
81
+ initial: "QmNus...",
82
+ });
83
+ template = { kind: common_1.TemplateKind.SUBGRAPH_ID, id };
84
+ }
85
+ if (templateKind === common_1.TemplateKind.SUBGRAPH_REPO) {
86
+ const { path } = await (0, prompts_1.default)({
87
+ type: "text",
88
+ name: "path",
89
+ message: "Enter a path to a subgraph repository",
90
+ initial: "../subgraph",
91
+ });
92
+ template = { kind: common_1.TemplateKind.SUBGRAPH_REPO, path };
93
+ }
94
+ }
95
+ const validatedOptions = {
96
+ projectName,
97
+ rootDir: node_path_1.default.resolve(".", options.dir ? options.dir : projectName),
98
+ template,
99
+ etherscanApiKey: options.etherscanApiKey,
100
+ };
101
+ await (0, index_1.run)(validatedOptions);
102
+ };
103
+ createPonder();
@@ -0,0 +1,22 @@
1
+ export declare enum TemplateKind {
2
+ NONE = 0,
3
+ ETHERSCAN = 1,
4
+ SUBGRAPH_ID = 2,
5
+ SUBGRAPH_REPO = 3
6
+ }
7
+ export declare type Template = {
8
+ kind: TemplateKind.ETHERSCAN;
9
+ link: string;
10
+ } | {
11
+ kind: TemplateKind.SUBGRAPH_ID;
12
+ id: string;
13
+ } | {
14
+ kind: TemplateKind.SUBGRAPH_REPO;
15
+ path: string;
16
+ };
17
+ export interface CreatePonderOptions {
18
+ rootDir: string;
19
+ projectName: string;
20
+ template?: Template;
21
+ etherscanApiKey?: string;
22
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TemplateKind = void 0;
4
+ var TemplateKind;
5
+ (function (TemplateKind) {
6
+ TemplateKind[TemplateKind["NONE"] = 0] = "NONE";
7
+ TemplateKind[TemplateKind["ETHERSCAN"] = 1] = "ETHERSCAN";
8
+ TemplateKind[TemplateKind["SUBGRAPH_ID"] = 2] = "SUBGRAPH_ID";
9
+ TemplateKind[TemplateKind["SUBGRAPH_REPO"] = 3] = "SUBGRAPH_REPO";
10
+ })(TemplateKind = exports.TemplateKind || (exports.TemplateKind = {}));
@@ -0,0 +1 @@
1
+ export declare function tryGitInit(root: string): boolean;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.tryGitInit = void 0;
7
+ /* eslint-disable no-empty */
8
+ const child_process_1 = require("child_process");
9
+ const path_1 = __importDefault(require("path"));
10
+ const rimraf_1 = __importDefault(require("rimraf"));
11
+ // File adapted from next.js
12
+ // https://github.dev/vercel/next.js/blob/9ad1f321b7902542acd2be041fb2f15f023a0ed9/packages/create-next-app/helpers/git.ts
13
+ function isInGitRepository() {
14
+ try {
15
+ (0, child_process_1.execSync)("git rev-parse --is-inside-work-tree", { stdio: "ignore" });
16
+ return true;
17
+ }
18
+ catch (_) { }
19
+ return false;
20
+ }
21
+ function isInMercurialRepository() {
22
+ try {
23
+ (0, child_process_1.execSync)("hg --cwd . root", { stdio: "ignore" });
24
+ return true;
25
+ }
26
+ catch (_) { }
27
+ return false;
28
+ }
29
+ function tryGitInit(root) {
30
+ let didInit = false;
31
+ try {
32
+ (0, child_process_1.execSync)("git --version", { stdio: "ignore" });
33
+ if (isInGitRepository() || isInMercurialRepository()) {
34
+ return false;
35
+ }
36
+ (0, child_process_1.execSync)("git init", { stdio: "ignore" });
37
+ didInit = true;
38
+ (0, child_process_1.execSync)("git checkout -b main", { stdio: "ignore" });
39
+ (0, child_process_1.execSync)("git add -A", { stdio: "ignore" });
40
+ (0, child_process_1.execSync)('git commit -m "chore: initial commit from create-ponder"', {
41
+ stdio: "ignore",
42
+ });
43
+ return true;
44
+ }
45
+ catch (e) {
46
+ if (didInit) {
47
+ try {
48
+ rimraf_1.default.sync(path_1.default.join(root, ".git"));
49
+ }
50
+ catch (_) { }
51
+ }
52
+ return false;
53
+ }
54
+ }
55
+ exports.tryGitInit = tryGitInit;
@@ -14,7 +14,7 @@ export declare type GraphSource = {
14
14
  entities: string[];
15
15
  abis: {
16
16
  name: string;
17
- file: string;
17
+ file: any;
18
18
  }[];
19
19
  eventHandlers?: {
20
20
  event: string;
@@ -0,0 +1 @@
1
+ export declare const wait: (ms: number) => Promise<unknown>;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wait = void 0;
4
+ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
5
+ exports.wait = wait;
@@ -1,4 +1,4 @@
1
- import type { CreatePonderOptions } from "./bin/create-ponder";
1
+ import { CreatePonderOptions } from "./common";
2
2
  export declare type PonderNetwork = {
3
3
  name: string;
4
4
  chainId: number;
package/dist/src/index.js CHANGED
@@ -10,30 +10,54 @@ const node_fs_1 = require("node:fs");
10
10
  const node_path_1 = __importDefault(require("node:path"));
11
11
  const picocolors_1 = __importDefault(require("picocolors"));
12
12
  const prettier_1 = __importDefault(require("prettier"));
13
+ const common_1 = require("./common");
13
14
  const detectPackageManager_1 = require("./helpers/detectPackageManager");
15
+ const git_1 = require("./helpers/git");
14
16
  const basic_1 = require("./templates/basic");
15
17
  const etherscan_1 = require("./templates/etherscan");
16
- const subgraph_1 = require("./templates/subgraph");
18
+ const subgraphId_1 = require("./templates/subgraphId");
19
+ const subgraphRepo_1 = require("./templates/subgraphRepo");
17
20
  const run = async (options, overrides = {}) => {
18
- const { ponderRootDir } = options;
21
+ const { rootDir } = options;
19
22
  // Create required directories.
20
- (0, node_fs_1.mkdirSync)(node_path_1.default.join(ponderRootDir, "abis"), { recursive: true });
21
- (0, node_fs_1.mkdirSync)(node_path_1.default.join(ponderRootDir, "src"), { recursive: true });
23
+ (0, node_fs_1.mkdirSync)(node_path_1.default.join(rootDir, "abis"), { recursive: true });
24
+ (0, node_fs_1.mkdirSync)(node_path_1.default.join(rootDir, "src"), { recursive: true });
22
25
  let ponderConfig;
23
- if (options.fromSubgraph) {
24
- console.log(picocolors_1.default.cyan("[create-ponder] ") + `Bootstrapping from subgraph`);
25
- ponderConfig = (0, subgraph_1.fromSubgraph)(options);
26
- }
27
- else if (options.fromEtherscan) {
28
- console.log(picocolors_1.default.cyan("[create-ponder] ") + `Bootstrapping from Etherscan`);
29
- ponderConfig = await (0, etherscan_1.fromEtherscan)(options);
30
- }
31
- else {
32
- ponderConfig = (0, basic_1.fromBasic)(options);
26
+ console.log(`\nCreating a new Ponder app in ${picocolors_1.default.bold(picocolors_1.default.green(rootDir))}.`);
27
+ switch (options.template?.kind) {
28
+ case common_1.TemplateKind.ETHERSCAN: {
29
+ console.log(`\nUsing ${picocolors_1.default.cyan("Etherscan contract link")} template.`);
30
+ ponderConfig = await (0, etherscan_1.fromEtherscan)({
31
+ rootDir,
32
+ etherscanLink: options.template.link,
33
+ etherscanApiKey: options.etherscanApiKey,
34
+ });
35
+ break;
36
+ }
37
+ case common_1.TemplateKind.SUBGRAPH_ID: {
38
+ console.log(`\nUsing ${picocolors_1.default.cyan("Subgraph ID")} template.`);
39
+ ponderConfig = await (0, subgraphId_1.fromSubgraphId)({
40
+ rootDir,
41
+ subgraphId: options.template.id,
42
+ });
43
+ break;
44
+ }
45
+ case common_1.TemplateKind.SUBGRAPH_REPO: {
46
+ console.log(`\nUsing ${picocolors_1.default.cyan("Subgraph repository")} template.`);
47
+ ponderConfig = (0, subgraphRepo_1.fromSubgraphRepo)({
48
+ rootDir,
49
+ subgraphPath: options.template.path,
50
+ });
51
+ break;
52
+ }
53
+ default: {
54
+ ponderConfig = (0, basic_1.fromBasic)({ rootDir });
55
+ break;
56
+ }
33
57
  }
34
58
  // Write the handler ts files.
35
59
  ponderConfig.contracts.forEach((contract) => {
36
- const abi = (0, node_fs_1.readFileSync)(node_path_1.default.join(ponderRootDir, contract.abi), {
60
+ const abi = (0, node_fs_1.readFileSync)(node_path_1.default.join(rootDir, contract.abi), {
37
61
  encoding: "utf-8",
38
62
  });
39
63
  const abiInterface = new ethers_1.ethers.utils.Interface(abi);
@@ -49,7 +73,7 @@ const run = async (options, overrides = {}) => {
49
73
  })`)
50
74
  .join("\n")}
51
75
  `;
52
- (0, node_fs_1.writeFileSync)(node_path_1.default.join(ponderRootDir, `./src/${contract.name}.ts`), prettier_1.default.format(handlerFileContents, { parser: "typescript" }));
76
+ (0, node_fs_1.writeFileSync)(node_path_1.default.join(rootDir, `./src/${contract.name}.ts`), prettier_1.default.format(handlerFileContents, { parser: "typescript" }));
53
77
  });
54
78
  // Write the ponder.config.ts file.
55
79
  const finalPonderConfig = `
@@ -60,11 +84,11 @@ const run = async (options, overrides = {}) => {
60
84
  contracts: ${JSON.stringify(ponderConfig.contracts)},
61
85
  };
62
86
  `;
63
- (0, node_fs_1.writeFileSync)(node_path_1.default.join(ponderRootDir, "ponder.config.ts"), prettier_1.default.format(finalPonderConfig, { parser: "babel" }));
87
+ (0, node_fs_1.writeFileSync)(node_path_1.default.join(rootDir, "ponder.config.ts"), prettier_1.default.format(finalPonderConfig, { parser: "babel" }));
64
88
  // Write the .env.local file.
65
89
  const uniqueChainIds = Array.from(new Set(ponderConfig.networks.map((n) => n.chainId)));
66
90
  const envLocal = `${uniqueChainIds.map((chainId) => `PONDER_RPC_URL_${chainId}=""\n`)}`;
67
- (0, node_fs_1.writeFileSync)(node_path_1.default.join(ponderRootDir, ".env.local"), envLocal);
91
+ (0, node_fs_1.writeFileSync)(node_path_1.default.join(rootDir, ".env.local"), envLocal);
68
92
  // Write the package.json file.
69
93
  const packageJson = `
70
94
  {
@@ -75,8 +99,7 @@ const run = async (options, overrides = {}) => {
75
99
  "codegen": "ponder codegen"
76
100
  },
77
101
  "dependencies": {
78
- "@ponder/core": "latest",
79
- "@ponder/graphql": "latest"
102
+ "@ponder/core": "latest"
80
103
  },
81
104
  "devDependencies": {
82
105
  "@types/node": "^18.11.18",
@@ -87,7 +110,7 @@ const run = async (options, overrides = {}) => {
87
110
  }
88
111
  }
89
112
  `;
90
- (0, node_fs_1.writeFileSync)(node_path_1.default.join(ponderRootDir, "package.json"), prettier_1.default.format(packageJson, { parser: "json" }));
113
+ (0, node_fs_1.writeFileSync)(node_path_1.default.join(rootDir, "package.json"), prettier_1.default.format(packageJson, { parser: "json" }));
91
114
  // Write the tsconfig.json file.
92
115
  const tsConfig = `
93
116
  {
@@ -102,28 +125,30 @@ const run = async (options, overrides = {}) => {
102
125
  "exclude": ["node_modules"]
103
126
  }
104
127
  `;
105
- (0, node_fs_1.writeFileSync)(node_path_1.default.join(ponderRootDir, "tsconfig.json"), prettier_1.default.format(tsConfig, { parser: "json" }));
128
+ (0, node_fs_1.writeFileSync)(node_path_1.default.join(rootDir, "tsconfig.json"), prettier_1.default.format(tsConfig, { parser: "json" }));
106
129
  // Write the .gitignore file.
107
- (0, node_fs_1.writeFileSync)(node_path_1.default.join(ponderRootDir, ".gitignore"), `node_modules/\n.DS_Store\n\n.env.local\n.ponder/\ngenerated/`);
130
+ (0, node_fs_1.writeFileSync)(node_path_1.default.join(rootDir, ".gitignore"), `node_modules/\n.DS_Store\n\n.env.local\n.ponder/\ngenerated/`);
108
131
  const packageManager = await (0, detectPackageManager_1.detect)();
109
132
  const runCommand = packageManager === "npm" ? `${packageManager} run` : packageManager;
110
133
  // Install packages.
111
- console.log(picocolors_1.default.cyan("[create-ponder] ") + `Installing with ${packageManager}`);
134
+ console.log(picocolors_1.default.bold(`\nInstalling with ${packageManager}.`));
112
135
  const installCommand = overrides.installCommand
113
136
  ? overrides.installCommand
114
137
  : `${packageManager} install`;
115
138
  (0, node_child_process_1.execSync)(installCommand, {
116
- cwd: ponderRootDir,
139
+ cwd: rootDir,
117
140
  stdio: "inherit",
118
141
  });
142
+ // Intialize git repository
143
+ process.chdir(rootDir);
144
+ (0, git_1.tryGitInit)(rootDir);
145
+ console.log(`\nInitialized a git repository.`);
119
146
  // Run codegen.
120
- console.log(picocolors_1.default.cyan("[create-ponder] ") + `Generating types`);
121
147
  (0, node_child_process_1.execSync)(`${runCommand} --silent codegen --silent`, {
122
- cwd: ponderRootDir,
148
+ cwd: rootDir,
123
149
  stdio: "inherit",
124
150
  });
125
- console.log(picocolors_1.default.cyan("[create-ponder] ") +
126
- picocolors_1.default.green("Done! ") +
127
- `To get started run ${picocolors_1.default.yellow(`${runCommand} dev`)}`);
151
+ console.log(`\nGenerated types.`);
152
+ console.log(picocolors_1.default.green("\nSuccess! ") + `Created ${options.projectName} at ${rootDir}`);
128
153
  };
129
154
  exports.run = run;
@@ -1,3 +1,4 @@
1
- import type { PartialPonderConfig } from "src/index";
2
- import type { CreatePonderOptions } from "../bin/create-ponder";
3
- export declare const fromBasic: (options: CreatePonderOptions) => PartialPonderConfig;
1
+ import type { PartialPonderConfig } from "../index";
2
+ export declare const fromBasic: ({ rootDir }: {
3
+ rootDir: string;
4
+ }) => PartialPonderConfig;
@@ -7,11 +7,10 @@ exports.fromBasic = void 0;
7
7
  const node_fs_1 = require("node:fs");
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const prettier_1 = __importDefault(require("prettier"));
10
- const fromBasic = (options) => {
11
- const { ponderRootDir } = options;
10
+ const fromBasic = ({ rootDir }) => {
12
11
  const abiFileContents = `[]`;
13
12
  const abiRelativePath = "./abis/ExampleContract.json";
14
- const abiAbsolutePath = node_path_1.default.join(ponderRootDir, abiRelativePath);
13
+ const abiAbsolutePath = node_path_1.default.join(rootDir, abiRelativePath);
15
14
  (0, node_fs_1.writeFileSync)(abiAbsolutePath, abiFileContents);
16
15
  const schemaGraphqlFileContents = `
17
16
  type ExampleToken @entity {
@@ -25,7 +24,7 @@ const fromBasic = (options) => {
25
24
  }
26
25
  `;
27
26
  // Generate the schema.graphql file.
28
- const ponderSchemaFilePath = node_path_1.default.join(ponderRootDir, "schema.graphql");
27
+ const ponderSchemaFilePath = node_path_1.default.join(rootDir, "schema.graphql");
29
28
  (0, node_fs_1.writeFileSync)(ponderSchemaFilePath, prettier_1.default.format(schemaGraphqlFileContents, { parser: "graphql" }));
30
29
  // Build the partial ponder config.
31
30
  const ponderConfig = {
@@ -1,3 +1,6 @@
1
1
  import type { PartialPonderConfig } from "src/index";
2
- import type { CreatePonderOptions } from "../bin/create-ponder";
3
- export declare const fromEtherscan: (options: CreatePonderOptions) => Promise<PartialPonderConfig>;
2
+ export declare const fromEtherscan: ({ rootDir, etherscanLink, etherscanApiKey, }: {
3
+ rootDir: string;
4
+ etherscanLink: string;
5
+ etherscanApiKey?: string | undefined;
6
+ }) => Promise<PartialPonderConfig>;
@@ -10,14 +10,10 @@ const node_path_1 = __importDefault(require("node:path"));
10
10
  const node_fetch_1 = __importDefault(require("node-fetch"));
11
11
  const prettier_1 = __importDefault(require("prettier"));
12
12
  const getEtherscanChainId_1 = require("../helpers/getEtherscanChainId");
13
- const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
14
- const fromEtherscan = async (options) => {
15
- const { ponderRootDir } = options;
16
- if (!options.fromEtherscan) {
17
- throw new Error(`Internal error: fromEtherscan undefined`);
18
- }
19
- const apiKey = options.etherscanApiKey || process.env.ETHERSCAN_API_KEY;
20
- const url = new URL(options.fromEtherscan);
13
+ const wait_1 = require("../helpers/wait");
14
+ const fromEtherscan = async ({ rootDir, etherscanLink, etherscanApiKey, }) => {
15
+ const apiKey = etherscanApiKey || process.env.ETHERSCAN_API_KEY;
16
+ const url = new URL(etherscanLink);
21
17
  const network = (0, getEtherscanChainId_1.getNetworkByEtherscanHostname)(url.hostname);
22
18
  if (!network) {
23
19
  throw new Error(`Unrecognized etherscan hostname: ${url.hostname}`);
@@ -26,18 +22,18 @@ const fromEtherscan = async (options) => {
26
22
  const contractAddress = url.pathname.slice(1).split("/")[1];
27
23
  const txHash = await getContractCreationTxn(contractAddress, apiUrl, apiKey);
28
24
  if (!apiKey) {
29
- console.log("(1/2) Waiting 5 seconds for Etherscan API rate limit");
30
- await delay(5000);
25
+ console.log("\n(1/2) Waiting 5 seconds for Etherscan API rate limit");
26
+ await (0, wait_1.wait)(5000);
31
27
  }
32
28
  const blockNumber = await getTxBlockNumber(txHash, apiUrl, apiKey);
33
29
  if (!apiKey) {
34
30
  console.log("(2/2) Waiting 5 seconds for Etherscan API rate limit");
35
- await delay(5000);
31
+ await (0, wait_1.wait)(5000);
36
32
  }
37
33
  const { abi, contractName } = await getContractAbiAndName(contractAddress, apiUrl, apiKey);
38
34
  // Write contract ABI file.
39
35
  const abiRelativePath = `./abis/${contractName}.json`;
40
- const abiAbsolutePath = node_path_1.default.join(ponderRootDir, abiRelativePath);
36
+ const abiAbsolutePath = node_path_1.default.join(rootDir, abiRelativePath);
41
37
  (0, node_fs_1.writeFileSync)(abiAbsolutePath, prettier_1.default.format(abi, { parser: "json" }));
42
38
  const schemaGraphqlFileContents = `
43
39
  type ExampleEntity @entity {
@@ -46,7 +42,7 @@ const fromEtherscan = async (options) => {
46
42
  }
47
43
  `;
48
44
  // Generate the schema.graphql file.
49
- const ponderSchemaFilePath = node_path_1.default.join(ponderRootDir, "schema.graphql");
45
+ const ponderSchemaFilePath = node_path_1.default.join(rootDir, "schema.graphql");
50
46
  (0, node_fs_1.writeFileSync)(ponderSchemaFilePath, prettier_1.default.format(schemaGraphqlFileContents, { parser: "graphql" }));
51
47
  // Build and return the partial ponder config.
52
48
  const ponderConfig = {
@@ -0,0 +1,5 @@
1
+ import type { PartialPonderConfig } from "src/index";
2
+ export declare const fromSubgraphId: ({ rootDir, subgraphId, }: {
3
+ rootDir: string;
4
+ subgraphId: string;
5
+ }) => Promise<PartialPonderConfig>;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fromSubgraphId = void 0;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const node_fetch_1 = __importDefault(require("node-fetch"));
10
+ const prettier_1 = __importDefault(require("prettier"));
11
+ const yaml_1 = require("yaml");
12
+ const getGraphProtocolChainId_1 = require("../helpers/getGraphProtocolChainId");
13
+ const validateGraphProtocolSource_1 = require("../helpers/validateGraphProtocolSource");
14
+ const fetchIpfsFile = async (cid) => {
15
+ const url = `https://ipfs.network.thegraph.com/api/v0/cat?arg=${cid}`;
16
+ const response = await (0, node_fetch_1.default)(url);
17
+ const contentRaw = await response.text();
18
+ return contentRaw;
19
+ };
20
+ const fromSubgraphId = async ({ rootDir, subgraphId, }) => {
21
+ const ponderNetworks = [];
22
+ let ponderContracts = [];
23
+ // Fetch the manifest file.
24
+ const manifestRaw = await fetchIpfsFile(subgraphId);
25
+ const manifest = (0, yaml_1.parse)(manifestRaw);
26
+ // Fetch and write the schema.graphql file.
27
+ const schemaCid = manifest.schema.file["/"].slice(6);
28
+ const schemaRaw = await fetchIpfsFile(schemaCid);
29
+ const ponderSchemaFilePath = node_path_1.default.join(rootDir, "schema.graphql");
30
+ (0, node_fs_1.writeFileSync)(ponderSchemaFilePath, prettier_1.default.format(schemaRaw, { parser: "graphql" }));
31
+ const dataSources = manifest.dataSources.map(validateGraphProtocolSource_1.validateGraphProtocolSource);
32
+ // Fetch and write all referenced ABIs.
33
+ const abiFiles = dataSources
34
+ .map((source) => source.mapping.abis)
35
+ .flat()
36
+ .filter((source, idx, arr) => arr.findIndex((s) => s.name === source.name) === idx);
37
+ await Promise.all(abiFiles.map(async (abi) => {
38
+ const abiContent = await fetchIpfsFile(abi.file["/"].slice(6));
39
+ const abiPath = node_path_1.default.join(rootDir, `./abis/${abi.name}.json`);
40
+ (0, node_fs_1.writeFileSync)(abiPath, prettier_1.default.format(abiContent, { parser: "json" }));
41
+ }));
42
+ // Build the ponder sources.
43
+ ponderContracts = dataSources.map((source) => {
44
+ const network = source.network || "mainnet";
45
+ const chainId = (0, getGraphProtocolChainId_1.getGraphProtocolChainId)(network);
46
+ if (!chainId || chainId === -1) {
47
+ throw new Error(`Unhandled network name: ${network}`);
48
+ }
49
+ if (!ponderNetworks.map((n) => n.name).includes(network)) {
50
+ ponderNetworks.push({
51
+ name: network,
52
+ chainId: chainId,
53
+ rpcUrl: `process.env.PONDER_RPC_URL_${chainId}`,
54
+ });
55
+ }
56
+ const abiRelativePath = `./abis/${source.source.abi}.json`;
57
+ return {
58
+ name: source.name,
59
+ network: network,
60
+ address: source.source.address,
61
+ abi: abiRelativePath,
62
+ startBlock: source.source.startBlock,
63
+ };
64
+ });
65
+ // Build the partial ponder config.
66
+ const ponderConfig = {
67
+ networks: ponderNetworks,
68
+ contracts: ponderContracts,
69
+ };
70
+ return ponderConfig;
71
+ };
72
+ exports.fromSubgraphId = fromSubgraphId;
@@ -0,0 +1,5 @@
1
+ import type { PartialPonderConfig } from "../index";
2
+ export declare const fromSubgraphRepo: ({ rootDir, subgraphPath, }: {
3
+ rootDir: string;
4
+ subgraphPath: string;
5
+ }) => PartialPonderConfig;
@@ -3,18 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.fromSubgraph = void 0;
6
+ exports.fromSubgraphRepo = void 0;
7
7
  const node_fs_1 = require("node:fs");
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const yaml_1 = require("yaml");
10
10
  const getGraphProtocolChainId_1 = require("../helpers/getGraphProtocolChainId");
11
11
  const validateGraphProtocolSource_1 = require("../helpers/validateGraphProtocolSource");
12
- const fromSubgraph = (options) => {
13
- if (!options.fromSubgraph) {
14
- throw new Error(`Internal error: fromSubgraph undefined`);
15
- }
16
- const { ponderRootDir } = options;
17
- const subgraphRootDir = node_path_1.default.resolve(options.fromSubgraph);
12
+ const fromSubgraphRepo = ({ rootDir, subgraphPath, }) => {
13
+ const subgraphRootDir = node_path_1.default.resolve(subgraphPath);
18
14
  const ponderNetworks = [];
19
15
  let ponderContracts = [];
20
16
  // If the `--from-subgraph` option was passed, parse subgraph files
@@ -38,7 +34,7 @@ const fromSubgraph = (options) => {
38
34
  const subgraphYaml = (0, yaml_1.parse)(subgraphYamlRaw);
39
35
  // Copy over the schema.graphql file.
40
36
  const subgraphSchemaFilePath = node_path_1.default.join(subgraphRootDirPath, subgraphYaml.schema.file);
41
- const ponderSchemaFilePath = node_path_1.default.join(ponderRootDir, "schema.graphql");
37
+ const ponderSchemaFilePath = node_path_1.default.join(rootDir, "schema.graphql");
42
38
  (0, node_fs_1.copyFileSync)(subgraphSchemaFilePath, ponderSchemaFilePath);
43
39
  // Build the ponder sources. Also copy over the ABI files for each source.
44
40
  ponderContracts = subgraphYaml.dataSources
@@ -64,7 +60,7 @@ const fromSubgraph = (options) => {
64
60
  const abiAbsolutePath = node_path_1.default.join(subgraphRootDirPath, abiPath);
65
61
  const abiFileName = node_path_1.default.basename(abiPath);
66
62
  const ponderAbiRelativePath = `./abis/${abiFileName}`;
67
- const ponderAbiAbsolutePath = node_path_1.default.join(ponderRootDir, ponderAbiRelativePath);
63
+ const ponderAbiAbsolutePath = node_path_1.default.join(rootDir, ponderAbiRelativePath);
68
64
  (0, node_fs_1.copyFileSync)(abiAbsolutePath, ponderAbiAbsolutePath);
69
65
  return {
70
66
  name: source.name,
@@ -81,4 +77,4 @@ const fromSubgraph = (options) => {
81
77
  };
82
78
  return ponderConfig;
83
79
  };
84
- exports.fromSubgraph = fromSubgraph;
80
+ exports.fromSubgraphRepo = fromSubgraphRepo;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ponder",
3
- "version": "0.0.18",
3
+ "version": "0.0.37",
4
4
  "description": "Tool to bootstrap a Ponder project",
5
5
  "license": "MIT",
6
6
  "author": "olias.eth",
@@ -8,7 +8,7 @@
8
8
  "dist/src"
9
9
  ],
10
10
  "bin": {
11
- "create-ponder": "dist/src/bin/create-ponder"
11
+ "create-ponder": "dist/src/bin/create-ponder.js"
12
12
  },
13
13
  "dependencies": {
14
14
  "@ethersproject/abi": "^5.6.4",
@@ -19,6 +19,8 @@
19
19
  "node-fetch": "^2.6.7",
20
20
  "picocolors": "^1.0.0",
21
21
  "prettier": "^2.6.2",
22
+ "prompts": "^2.4.2",
23
+ "rimraf": "^4.1.2",
22
24
  "yaml": "^2.1.1"
23
25
  },
24
26
  "devDependencies": {
@@ -26,13 +28,14 @@
26
28
  "@types/node": "^18.7.8",
27
29
  "@types/node-fetch": "2",
28
30
  "@types/prettier": "^2.7.1",
31
+ "@types/prompts": "^2.4.2",
29
32
  "jest": "^29.3.1",
30
33
  "tsconfig-replace-paths": "^0.0.11",
31
34
  "typescript": "^4.5.5",
32
- "@ponder/core": "0.0.32"
35
+ "@ponder/core": "0.0.37"
33
36
  },
34
37
  "scripts": {
35
- "build": "rm -rf dist && tsc && tsconfig-replace-paths --src . && mv dist/src/bin/create-ponder.js dist/src/bin/create-ponder",
38
+ "build": "rm -rf dist && tsc && tsconfig-replace-paths --src .",
36
39
  "test": "$npm_execpath build && export $(grep -v '^#' .env.local | xargs) && jest",
37
40
  "typecheck": "tsc --noEmit"
38
41
  }
@@ -1,40 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- /* eslint-disable @typescript-eslint/no-var-requires */
4
- var __importDefault = (this && this.__importDefault) || function (mod) {
5
- return (mod && mod.__esModule) ? mod : { "default": mod };
6
- };
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- const cac_1 = require("cac");
9
- const node_path_1 = __importDefault(require("node:path"));
10
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
11
- // @ts-ignore
12
- const package_json_1 = __importDefault(require("../../../package.json"));
13
- const cli = (0, cac_1.cac)(package_json_1.default.name)
14
- .version(package_json_1.default.version)
15
- .usage("[options]")
16
- .help()
17
- .option("--dir [path]", "Path to directory for generated project")
18
- .option("--from-subgraph [path]", "Path to subgraph directory")
19
- .option("--from-etherscan [url]", "Link to etherscan contract page")
20
- .option("--etherscan-api-key [key]", "Etherscan API key");
21
- const parsed = cli.parse(process.argv);
22
- const options = parsed.options;
23
- if (options.help) {
24
- process.exit(0);
25
- }
26
- // Validate CLI options.
27
- if (options.fromSubgraph && options.fromEtherscan) {
28
- throw new Error(`Cannot specify more than one "--from" option:
29
- --from-subgraph
30
- --from-etherscan
31
- `);
32
- }
33
- const validatedOptions = {
34
- // Default `dir` to "ponder".
35
- ponderRootDir: node_path_1.default.resolve(".", options.dir ? options.dir : "ponder"),
36
- fromSubgraph: options.fromSubgraph,
37
- fromEtherscan: options.fromEtherscan,
38
- etherscanApiKey: options.etherscanApiKey,
39
- };
40
- require("../index").run(validatedOptions);
@@ -1,3 +0,0 @@
1
- import type { PartialPonderConfig } from "src/index";
2
- import type { CreatePonderOptions } from "../bin/create-ponder";
3
- export declare const fromSubgraph: (options: CreatePonderOptions) => PartialPonderConfig;