create-ponder 0.0.17 → 0.0.19
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.
- package/dist/src/bin/create-ponder.d.ts +1 -6
- package/dist/src/bin/create-ponder.js +103 -0
- package/dist/src/common.d.ts +22 -0
- package/dist/src/common.js +10 -0
- package/dist/src/helpers/git.d.ts +1 -0
- package/dist/src/helpers/git.js +55 -0
- package/dist/src/helpers/validateGraphProtocolSource.d.ts +1 -1
- package/dist/src/helpers/wait.d.ts +1 -0
- package/dist/src/helpers/wait.js +5 -0
- package/dist/src/index.d.ts +2 -5
- package/dist/src/index.js +55 -32
- package/dist/src/templates/basic.d.ts +4 -3
- package/dist/src/templates/basic.js +3 -8
- package/dist/src/templates/etherscan.d.ts +5 -2
- package/dist/src/templates/etherscan.js +9 -17
- package/dist/src/templates/subgraphId.d.ts +5 -0
- package/dist/src/templates/subgraphId.js +72 -0
- package/dist/src/templates/subgraphRepo.d.ts +5 -0
- package/dist/src/templates/{subgraph.js → subgraphRepo.js} +6 -14
- package/package.json +7 -4
- package/dist/src/bin/create-ponder +0 -40
- package/dist/src/templates/subgraph.d.ts +0 -3
|
@@ -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;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const wait: (ms: number) => Promise<unknown>;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { CreatePonderOptions } from "./common";
|
|
2
2
|
export declare type PonderNetwork = {
|
|
3
|
-
kind?: string;
|
|
4
3
|
name: string;
|
|
5
4
|
chainId: number;
|
|
6
5
|
rpcUrl: string;
|
|
7
6
|
};
|
|
8
7
|
export declare type PonderContract = {
|
|
9
|
-
kind?: "evm";
|
|
10
8
|
name: string;
|
|
11
9
|
network: string;
|
|
12
10
|
abi: string;
|
|
@@ -14,8 +12,7 @@ export declare type PonderContract = {
|
|
|
14
12
|
startBlock?: number;
|
|
15
13
|
};
|
|
16
14
|
export declare type PartialPonderConfig = {
|
|
17
|
-
|
|
18
|
-
database: {
|
|
15
|
+
database?: {
|
|
19
16
|
kind: string;
|
|
20
17
|
};
|
|
21
18
|
networks: PonderNetwork[];
|
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
|
|
18
|
+
const subgraphId_1 = require("./templates/subgraphId");
|
|
19
|
+
const subgraphRepo_1 = require("./templates/subgraphRepo");
|
|
17
20
|
const run = async (options, overrides = {}) => {
|
|
18
|
-
const {
|
|
21
|
+
const { rootDir } = options;
|
|
19
22
|
// Create required directories.
|
|
20
|
-
(0, node_fs_1.mkdirSync)(node_path_1.default.join(
|
|
21
|
-
(0, node_fs_1.mkdirSync)(node_path_1.default.join(
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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(
|
|
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,24 +73,22 @@ const run = async (options, overrides = {}) => {
|
|
|
49
73
|
})`)
|
|
50
74
|
.join("\n")}
|
|
51
75
|
`;
|
|
52
|
-
(0, node_fs_1.writeFileSync)(node_path_1.default.join(
|
|
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 = `
|
|
56
80
|
import type { PonderConfig } from "@ponder/core";
|
|
57
|
-
import { graphqlPlugin } from "@ponder/graphql";
|
|
58
81
|
|
|
59
82
|
export const config: PonderConfig = {
|
|
60
|
-
plugins: [graphqlPlugin()],
|
|
61
83
|
networks: ${JSON.stringify(ponderConfig.networks).replaceAll(/"process.env.PONDER_RPC_URL_(.*?)"/g, "process.env.PONDER_RPC_URL_$1")},
|
|
62
84
|
contracts: ${JSON.stringify(ponderConfig.contracts)},
|
|
63
85
|
};
|
|
64
86
|
`;
|
|
65
|
-
(0, node_fs_1.writeFileSync)(node_path_1.default.join(
|
|
87
|
+
(0, node_fs_1.writeFileSync)(node_path_1.default.join(rootDir, "ponder.config.ts"), prettier_1.default.format(finalPonderConfig, { parser: "babel" }));
|
|
66
88
|
// Write the .env.local file.
|
|
67
89
|
const uniqueChainIds = Array.from(new Set(ponderConfig.networks.map((n) => n.chainId)));
|
|
68
90
|
const envLocal = `${uniqueChainIds.map((chainId) => `PONDER_RPC_URL_${chainId}=""\n`)}`;
|
|
69
|
-
(0, node_fs_1.writeFileSync)(node_path_1.default.join(
|
|
91
|
+
(0, node_fs_1.writeFileSync)(node_path_1.default.join(rootDir, ".env.local"), envLocal);
|
|
70
92
|
// Write the package.json file.
|
|
71
93
|
const packageJson = `
|
|
72
94
|
{
|
|
@@ -77,8 +99,7 @@ const run = async (options, overrides = {}) => {
|
|
|
77
99
|
"codegen": "ponder codegen"
|
|
78
100
|
},
|
|
79
101
|
"dependencies": {
|
|
80
|
-
"@ponder/core": "latest"
|
|
81
|
-
"@ponder/graphql": "latest"
|
|
102
|
+
"@ponder/core": "latest"
|
|
82
103
|
},
|
|
83
104
|
"devDependencies": {
|
|
84
105
|
"@types/node": "^18.11.18",
|
|
@@ -89,7 +110,7 @@ const run = async (options, overrides = {}) => {
|
|
|
89
110
|
}
|
|
90
111
|
}
|
|
91
112
|
`;
|
|
92
|
-
(0, node_fs_1.writeFileSync)(node_path_1.default.join(
|
|
113
|
+
(0, node_fs_1.writeFileSync)(node_path_1.default.join(rootDir, "package.json"), prettier_1.default.format(packageJson, { parser: "json" }));
|
|
93
114
|
// Write the tsconfig.json file.
|
|
94
115
|
const tsConfig = `
|
|
95
116
|
{
|
|
@@ -104,28 +125,30 @@ const run = async (options, overrides = {}) => {
|
|
|
104
125
|
"exclude": ["node_modules"]
|
|
105
126
|
}
|
|
106
127
|
`;
|
|
107
|
-
(0, node_fs_1.writeFileSync)(node_path_1.default.join(
|
|
128
|
+
(0, node_fs_1.writeFileSync)(node_path_1.default.join(rootDir, "tsconfig.json"), prettier_1.default.format(tsConfig, { parser: "json" }));
|
|
108
129
|
// Write the .gitignore file.
|
|
109
|
-
(0, node_fs_1.writeFileSync)(node_path_1.default.join(
|
|
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/`);
|
|
110
131
|
const packageManager = await (0, detectPackageManager_1.detect)();
|
|
111
132
|
const runCommand = packageManager === "npm" ? `${packageManager} run` : packageManager;
|
|
112
133
|
// Install packages.
|
|
113
|
-
console.log(picocolors_1.default.
|
|
134
|
+
console.log(picocolors_1.default.bold(`\nInstalling with ${packageManager}.`));
|
|
114
135
|
const installCommand = overrides.installCommand
|
|
115
136
|
? overrides.installCommand
|
|
116
137
|
: `${packageManager} install`;
|
|
117
138
|
(0, node_child_process_1.execSync)(installCommand, {
|
|
118
|
-
cwd:
|
|
139
|
+
cwd: rootDir,
|
|
119
140
|
stdio: "inherit",
|
|
120
141
|
});
|
|
142
|
+
// Intialize git repository
|
|
143
|
+
process.chdir(rootDir);
|
|
144
|
+
(0, git_1.tryGitInit)(rootDir);
|
|
145
|
+
console.log(`\nInitialized a git repository.`);
|
|
121
146
|
// Run codegen.
|
|
122
|
-
console.log(picocolors_1.default.cyan("[create-ponder] ") + `Generating types`);
|
|
123
147
|
(0, node_child_process_1.execSync)(`${runCommand} --silent codegen --silent`, {
|
|
124
|
-
cwd:
|
|
148
|
+
cwd: rootDir,
|
|
125
149
|
stdio: "inherit",
|
|
126
150
|
});
|
|
127
|
-
console.log(
|
|
128
|
-
|
|
129
|
-
`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}`);
|
|
130
153
|
};
|
|
131
154
|
exports.run = run;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import type { PartialPonderConfig } from "
|
|
2
|
-
|
|
3
|
-
|
|
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 = (
|
|
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(
|
|
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,14 +24,10 @@ const fromBasic = (options) => {
|
|
|
25
24
|
}
|
|
26
25
|
`;
|
|
27
26
|
// Generate the schema.graphql file.
|
|
28
|
-
const ponderSchemaFilePath = node_path_1.default.join(
|
|
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 = {
|
|
32
|
-
plugins: ["graphqlPlugin()"],
|
|
33
|
-
database: {
|
|
34
|
-
kind: "sqlite",
|
|
35
|
-
},
|
|
36
31
|
networks: [
|
|
37
32
|
{
|
|
38
33
|
name: "mainnet",
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import type { PartialPonderConfig } from "src/index";
|
|
2
|
-
|
|
3
|
-
|
|
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
|
|
14
|
-
const fromEtherscan = async (
|
|
15
|
-
const
|
|
16
|
-
|
|
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
|
|
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
|
|
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(
|
|
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,14 +42,10 @@ const fromEtherscan = async (options) => {
|
|
|
46
42
|
}
|
|
47
43
|
`;
|
|
48
44
|
// Generate the schema.graphql file.
|
|
49
|
-
const ponderSchemaFilePath = node_path_1.default.join(
|
|
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 = {
|
|
53
|
-
plugins: ["graphqlPlugin()"],
|
|
54
|
-
database: {
|
|
55
|
-
kind: "sqlite",
|
|
56
|
-
},
|
|
57
49
|
networks: [
|
|
58
50
|
{
|
|
59
51
|
name: name,
|
|
@@ -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;
|
|
@@ -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.
|
|
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
|
|
13
|
-
|
|
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(
|
|
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(
|
|
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,
|
|
@@ -76,13 +72,9 @@ const fromSubgraph = (options) => {
|
|
|
76
72
|
});
|
|
77
73
|
// Build the partial ponder config.
|
|
78
74
|
const ponderConfig = {
|
|
79
|
-
plugins: ["graphqlPlugin()"],
|
|
80
|
-
database: {
|
|
81
|
-
kind: "sqlite",
|
|
82
|
-
},
|
|
83
75
|
networks: ponderNetworks,
|
|
84
76
|
contracts: ponderContracts,
|
|
85
77
|
};
|
|
86
78
|
return ponderConfig;
|
|
87
79
|
};
|
|
88
|
-
exports.
|
|
80
|
+
exports.fromSubgraphRepo = fromSubgraphRepo;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-ponder",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
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.
|
|
35
|
+
"@ponder/core": "0.0.36"
|
|
33
36
|
},
|
|
34
37
|
"scripts": {
|
|
35
|
-
"build": "rm -rf dist && tsc && tsconfig-replace-paths --src .
|
|
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);
|