@graphprotocol/graph-cli 0.90.1 → 0.91.0-alpha-20241202202221-345552f
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/CHANGELOG.md +9 -0
- package/dist/codegen/schema.d.ts +2 -2
- package/dist/codegen/schema.js +7 -5
- package/dist/codegen/schema.test.js +1 -1
- package/dist/command-helpers/abi.js +4 -0
- package/dist/command-helpers/scaffold.d.ts +3 -2
- package/dist/command-helpers/scaffold.js +3 -2
- package/dist/commands/codegen.d.ts +1 -0
- package/dist/commands/codegen.js +13 -1
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +77 -22
- package/dist/protocols/ethereum/type-generator.d.ts +1 -0
- package/dist/protocols/ethereum/type-generator.js +23 -6
- package/dist/protocols/index.d.ts +3 -2
- package/dist/protocols/index.js +29 -3
- package/dist/protocols/subgraph/manifest.graphql +71 -0
- package/dist/protocols/subgraph/scaffold/manifest.d.ts +9 -0
- package/dist/protocols/subgraph/scaffold/manifest.js +22 -0
- package/dist/protocols/subgraph/scaffold/mapping.d.ts +4 -0
- package/dist/protocols/subgraph/scaffold/mapping.js +16 -0
- package/dist/protocols/subgraph/subgraph.d.ts +10 -0
- package/dist/protocols/subgraph/subgraph.js +20 -0
- package/dist/scaffold/index.d.ts +2 -0
- package/dist/scaffold/index.js +1 -0
- package/dist/schema.d.ts +4 -2
- package/dist/schema.js +18 -3
- package/dist/type-generator.d.ts +10 -1
- package/dist/type-generator.js +32 -4
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +34 -0
- package/oclif.manifest.json +19 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @graphprotocol/graph-cli
|
|
2
2
|
|
|
3
|
+
## 0.91.0-alpha-20241202202221-345552f
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1754](https://github.com/graphprotocol/graph-tooling/pull/1754)
|
|
8
|
+
[`2050bf6`](https://github.com/graphprotocol/graph-tooling/commit/2050bf6259c19bd86a7446410c7e124dfaddf4cd)
|
|
9
|
+
Thanks [@incrypto32](https://github.com/incrypto32)! - Add support for subgraph datasource and
|
|
10
|
+
associated types.
|
|
11
|
+
|
|
3
12
|
## 0.90.1
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
package/dist/codegen/schema.d.ts
CHANGED
|
@@ -20,12 +20,12 @@ export default class SchemaCodeGenerator {
|
|
|
20
20
|
private schema;
|
|
21
21
|
constructor(schema: Schema);
|
|
22
22
|
generateModuleImports(): tsCodegen.ModuleImports[];
|
|
23
|
-
generateTypes(): Array<tsCodegen.Class>;
|
|
23
|
+
generateTypes(generateStoreMethods?: boolean): Array<tsCodegen.Class>;
|
|
24
24
|
generateDerivedLoaders(): any[];
|
|
25
25
|
_isEntityTypeDefinition(def: DefinitionNode): def is ObjectTypeDefinitionNode;
|
|
26
26
|
_isDerivedField(field: FieldDefinitionNode | undefined): boolean;
|
|
27
27
|
_isInterfaceDefinition(def: DefinitionNode): def is InterfaceTypeDefinitionNode;
|
|
28
|
-
_generateEntityType(def: ObjectTypeDefinitionNode): tsCodegen.Class;
|
|
28
|
+
_generateEntityType(def: ObjectTypeDefinitionNode, generateStoreMethods?: boolean): tsCodegen.Class;
|
|
29
29
|
_generateDerivedLoader(typeName: string): any;
|
|
30
30
|
_getTypeNameForField(gqlType: TypeNode): string;
|
|
31
31
|
_generateConstructor(_entityName: string, fields: readonly FieldDefinitionNode[] | undefined): tsCodegen.Method;
|
package/dist/codegen/schema.js
CHANGED
|
@@ -94,12 +94,12 @@ class SchemaCodeGenerator {
|
|
|
94
94
|
], '@graphprotocol/graph-ts'),
|
|
95
95
|
];
|
|
96
96
|
}
|
|
97
|
-
generateTypes() {
|
|
97
|
+
generateTypes(generateStoreMethods = true) {
|
|
98
98
|
return this.schema.ast.definitions
|
|
99
99
|
.map(def => {
|
|
100
100
|
if (this._isEntityTypeDefinition(def)) {
|
|
101
101
|
schemaCodeGeneratorDebug.extend('generateTypes')(`Generating entity type for ${def.name.value}`);
|
|
102
|
-
return this._generateEntityType(def);
|
|
102
|
+
return this._generateEntityType(def, generateStoreMethods);
|
|
103
103
|
}
|
|
104
104
|
})
|
|
105
105
|
.filter(Boolean);
|
|
@@ -132,15 +132,17 @@ class SchemaCodeGenerator {
|
|
|
132
132
|
_isInterfaceDefinition(def) {
|
|
133
133
|
return def.kind === 'InterfaceTypeDefinition';
|
|
134
134
|
}
|
|
135
|
-
_generateEntityType(def) {
|
|
135
|
+
_generateEntityType(def, generateStoreMethods = true) {
|
|
136
136
|
const name = def.name.value;
|
|
137
137
|
const klass = tsCodegen.klass(name, { export: true, extends: 'Entity' });
|
|
138
138
|
const fields = def.fields;
|
|
139
139
|
const idField = IdField.fromFields(fields);
|
|
140
140
|
// Generate and add a constructor
|
|
141
141
|
klass.addMethod(this._generateConstructor(name, fields));
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
if (generateStoreMethods) {
|
|
143
|
+
// Generate and add save() and getById() methods
|
|
144
|
+
this._generateStoreMethods(name, idField).forEach(method => klass.addMethod(method));
|
|
145
|
+
}
|
|
144
146
|
// Generate and add entity field getters and setters
|
|
145
147
|
def.fields
|
|
146
148
|
?.reduce((methods, field) => methods.concat(this._generateEntityFieldMethods(def, field)), [])
|
|
@@ -34,7 +34,7 @@ const schema_1 = __importDefault(require("../schema"));
|
|
|
34
34
|
const schema_2 = __importDefault(require("./schema"));
|
|
35
35
|
const typescript_1 = require("./typescript");
|
|
36
36
|
const formatTS = async (code) => await prettier_1.default.format(code, { parser: 'typescript', semi: false });
|
|
37
|
-
const createSchemaCodeGen = (schema) => new schema_2.default(new schema_1.default(
|
|
37
|
+
const createSchemaCodeGen = (schema) => new schema_2.default(new schema_1.default(schema, graphql.parse(schema), ''));
|
|
38
38
|
const testEntity = async (generatedTypes, expectedEntity) => {
|
|
39
39
|
const entity = generatedTypes.find(type => type.name === expectedEntity.name);
|
|
40
40
|
(0, vitest_1.expect)(entity instanceof typescript_1.Class).toBe(true);
|
|
@@ -282,6 +282,8 @@ const getEtherscanLikeAPIUrl = (network) => {
|
|
|
282
282
|
return 'https://maizenet-explorer.usecorn.com/api';
|
|
283
283
|
case 'corn-testnet':
|
|
284
284
|
return 'https://testnet-explorer.usecorn.com/api';
|
|
285
|
+
case 'botanix-testnet':
|
|
286
|
+
return 'https://api.routescan.io/v2/network/testnet/evm/3636/etherscan/api';
|
|
285
287
|
default:
|
|
286
288
|
return `https://api-${network}.etherscan.io/api`;
|
|
287
289
|
}
|
|
@@ -446,6 +448,8 @@ const getPublicRPCEndpoint = (network) => {
|
|
|
446
448
|
return 'https://maizenet-rpc.usecorn.com';
|
|
447
449
|
case 'corn-testnet':
|
|
448
450
|
return 'https://testnet-rpc.usecorn.com';
|
|
451
|
+
case 'botanix-testnet':
|
|
452
|
+
return 'https://node.botanixlabs.dev';
|
|
449
453
|
default:
|
|
450
454
|
throw new Error(`Unknown network: ${network}`);
|
|
451
455
|
}
|
|
@@ -3,10 +3,10 @@ import Protocol from '../protocols';
|
|
|
3
3
|
import ABI from '../protocols/ethereum/abi';
|
|
4
4
|
import { Spinner } from './spinner';
|
|
5
5
|
export declare const generateDataSource: (protocol: Protocol, contractName: string, network: string, contractAddress: string, abi: ABI, startBlock?: string) => Promise<Map<unknown, unknown>>;
|
|
6
|
-
export declare const generateScaffold: ({ protocolInstance, abi,
|
|
6
|
+
export declare const generateScaffold: ({ protocolInstance, abi, source, network, subgraphName, indexEvents, contractName, startBlock, node, spkgPath, entities, }: {
|
|
7
7
|
protocolInstance: Protocol;
|
|
8
8
|
abi: ABI;
|
|
9
|
-
|
|
9
|
+
source: string;
|
|
10
10
|
network: string;
|
|
11
11
|
subgraphName: string;
|
|
12
12
|
indexEvents: boolean;
|
|
@@ -14,6 +14,7 @@ export declare const generateScaffold: ({ protocolInstance, abi, contract, netwo
|
|
|
14
14
|
startBlock?: string | undefined;
|
|
15
15
|
node?: string | undefined;
|
|
16
16
|
spkgPath?: string | undefined;
|
|
17
|
+
entities?: string[] | undefined;
|
|
17
18
|
}, spinner: Spinner) => Promise<{
|
|
18
19
|
'subgraph.yaml': string;
|
|
19
20
|
'schema.graphql': string;
|
|
@@ -28,19 +28,20 @@ const generateDataSource = async (protocol, contractName, network, contractAddre
|
|
|
28
28
|
}))).asMutable();
|
|
29
29
|
};
|
|
30
30
|
exports.generateDataSource = generateDataSource;
|
|
31
|
-
const generateScaffold = async ({ protocolInstance, abi,
|
|
31
|
+
const generateScaffold = async ({ protocolInstance, abi, source, network, subgraphName, indexEvents, contractName = 'Contract', startBlock, node, spkgPath, entities, }, spinner) => {
|
|
32
32
|
(0, spinner_1.step)(spinner, 'Generate subgraph');
|
|
33
33
|
const scaffold = new scaffold_1.default({
|
|
34
34
|
protocol: protocolInstance,
|
|
35
35
|
abi,
|
|
36
36
|
indexEvents,
|
|
37
|
-
contract,
|
|
37
|
+
contract: source,
|
|
38
38
|
network,
|
|
39
39
|
contractName,
|
|
40
40
|
startBlock,
|
|
41
41
|
subgraphName,
|
|
42
42
|
node,
|
|
43
43
|
spkgPath,
|
|
44
|
+
entities,
|
|
44
45
|
});
|
|
45
46
|
return await scaffold.generate();
|
|
46
47
|
};
|
|
@@ -10,6 +10,7 @@ export default class CodegenCommand extends Command {
|
|
|
10
10
|
'skip-migrations': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
watch: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
12
12
|
uncrashable: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
ipfs: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
13
14
|
'uncrashable-config': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
14
15
|
};
|
|
15
16
|
run(): Promise<void>;
|
package/dist/commands/codegen.js
CHANGED
|
@@ -29,6 +29,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
const path_1 = __importDefault(require("path"));
|
|
30
30
|
const core_1 = require("@oclif/core");
|
|
31
31
|
const DataSourcesExtractor = __importStar(require("../command-helpers/data-sources"));
|
|
32
|
+
const ipfs_1 = require("../command-helpers/ipfs");
|
|
32
33
|
const version_1 = require("../command-helpers/version");
|
|
33
34
|
const debug_1 = __importDefault(require("../debug"));
|
|
34
35
|
const protocols_1 = __importDefault(require("../protocols"));
|
|
@@ -36,9 +37,10 @@ const type_generator_1 = __importDefault(require("../type-generator"));
|
|
|
36
37
|
const codegenDebug = (0, debug_1.default)('graph-cli:codegen');
|
|
37
38
|
class CodegenCommand extends core_1.Command {
|
|
38
39
|
async run() {
|
|
39
|
-
const { args: { 'subgraph-manifest': manifest }, flags: { 'output-dir': outputDir, 'skip-migrations': skipMigrations, watch, uncrashable, 'uncrashable-config': uncrashableConfig, }, } = await this.parse(CodegenCommand);
|
|
40
|
+
const { args: { 'subgraph-manifest': manifest }, flags: { 'output-dir': outputDir, 'skip-migrations': skipMigrations, watch, ipfs, uncrashable, 'uncrashable-config': uncrashableConfig, }, } = await this.parse(CodegenCommand);
|
|
40
41
|
codegenDebug('Initialized codegen manifest: %o', manifest);
|
|
41
42
|
let protocol;
|
|
43
|
+
let subgraphSources;
|
|
42
44
|
try {
|
|
43
45
|
// Checks to make sure codegen doesn't run against
|
|
44
46
|
// older subgraphs (both apiVersion and graph-ts version).
|
|
@@ -50,6 +52,9 @@ class CodegenCommand extends core_1.Command {
|
|
|
50
52
|
await (0, version_1.assertGraphTsVersion)(path_1.default.dirname(manifest), '0.25.0');
|
|
51
53
|
const dataSourcesAndTemplates = await DataSourcesExtractor.fromFilePath(manifest);
|
|
52
54
|
protocol = protocols_1.default.fromDataSources(dataSourcesAndTemplates);
|
|
55
|
+
subgraphSources = dataSourcesAndTemplates
|
|
56
|
+
.filter((ds) => ds.kind == 'subgraph')
|
|
57
|
+
.map((ds) => ds.source.address);
|
|
53
58
|
}
|
|
54
59
|
catch (e) {
|
|
55
60
|
this.error(e, { exit: 1 });
|
|
@@ -60,7 +65,9 @@ class CodegenCommand extends core_1.Command {
|
|
|
60
65
|
skipMigrations,
|
|
61
66
|
protocol,
|
|
62
67
|
uncrashable,
|
|
68
|
+
subgraphSources,
|
|
63
69
|
uncrashableConfig: uncrashableConfig || 'uncrashable-config.yaml',
|
|
70
|
+
ipfsUrl: ipfs,
|
|
64
71
|
});
|
|
65
72
|
// Watch working directory for file updates or additions, trigger
|
|
66
73
|
// type generation (if watch argument specified)
|
|
@@ -98,6 +105,11 @@ CodegenCommand.flags = {
|
|
|
98
105
|
summary: 'Generate Float Subgraph Uncrashable helper file.',
|
|
99
106
|
char: 'u',
|
|
100
107
|
}),
|
|
108
|
+
ipfs: core_1.Flags.string({
|
|
109
|
+
summary: 'IPFS node to use for fetching subgraph data.',
|
|
110
|
+
char: 'i',
|
|
111
|
+
default: ipfs_1.DEFAULT_IPFS_URL,
|
|
112
|
+
}),
|
|
101
113
|
'uncrashable-config': core_1.Flags.file({
|
|
102
114
|
summary: 'Directory for uncrashable config.',
|
|
103
115
|
aliases: ['uc'],
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export default class InitCommand extends Command {
|
|
|
19
19
|
abi: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
20
20
|
spkg: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
21
21
|
network: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
22
|
+
ipfs: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
22
23
|
};
|
|
23
24
|
run(): Promise<void>;
|
|
24
25
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -31,8 +31,11 @@ const os_1 = __importDefault(require("os"));
|
|
|
31
31
|
const path_1 = __importDefault(require("path"));
|
|
32
32
|
const toolbox = __importStar(require("gluegun"));
|
|
33
33
|
const gluegun_1 = require("gluegun");
|
|
34
|
+
const ipfs_http_client_1 = require("ipfs-http-client");
|
|
34
35
|
const core_1 = require("@oclif/core");
|
|
35
36
|
const abi_1 = require("../command-helpers/abi");
|
|
37
|
+
const compiler_1 = require("../command-helpers/compiler");
|
|
38
|
+
const ipfs_1 = require("../command-helpers/ipfs");
|
|
36
39
|
const network_1 = require("../command-helpers/network");
|
|
37
40
|
const node_1 = require("../command-helpers/node");
|
|
38
41
|
const scaffold_1 = require("../command-helpers/scaffold");
|
|
@@ -43,6 +46,8 @@ const constants_1 = require("../constants");
|
|
|
43
46
|
const debug_1 = __importDefault(require("../debug"));
|
|
44
47
|
const protocols_1 = __importDefault(require("../protocols"));
|
|
45
48
|
const schema_1 = require("../scaffold/schema");
|
|
49
|
+
const schema_2 = __importDefault(require("../schema"));
|
|
50
|
+
const utils_1 = __importDefault(require("../utils"));
|
|
46
51
|
const validation_1 = require("../validation");
|
|
47
52
|
const add_1 = __importDefault(require("./add"));
|
|
48
53
|
const protocolChoices = Array.from(protocols_1.default.availableProtocols().keys());
|
|
@@ -88,7 +93,7 @@ const DEFAULT_EXAMPLE_SUBGRAPH = 'ethereum-gravatar';
|
|
|
88
93
|
class InitCommand extends core_1.Command {
|
|
89
94
|
async run() {
|
|
90
95
|
const { args: { subgraphName, directory }, flags, } = await this.parse(InitCommand);
|
|
91
|
-
const { protocol, node: nodeFlag, 'from-contract': fromContract, 'contract-name': contractName, 'from-example': fromExample, 'index-events': indexEvents, 'skip-install': skipInstall, 'skip-git': skipGit, network, abi: abiPath, 'start-block': startBlock, spkg: spkgPath, } = flags;
|
|
96
|
+
const { protocol, node: nodeFlag, 'from-contract': fromContract, 'contract-name': contractName, 'from-example': fromExample, 'index-events': indexEvents, 'skip-install': skipInstall, 'skip-git': skipGit, ipfs, network, abi: abiPath, 'start-block': startBlock, spkg: spkgPath, } = flags;
|
|
92
97
|
initDebugger('Flags: %O', flags);
|
|
93
98
|
let { node } = (0, node_1.chooseNodeUrl)({
|
|
94
99
|
node: nodeFlag,
|
|
@@ -170,7 +175,7 @@ class InitCommand extends core_1.Command {
|
|
|
170
175
|
protocolInstance,
|
|
171
176
|
abi,
|
|
172
177
|
directory,
|
|
173
|
-
|
|
178
|
+
source: fromContract,
|
|
174
179
|
indexEvents,
|
|
175
180
|
network,
|
|
176
181
|
subgraphName,
|
|
@@ -180,6 +185,7 @@ class InitCommand extends core_1.Command {
|
|
|
180
185
|
spkgPath,
|
|
181
186
|
skipInstall,
|
|
182
187
|
skipGit,
|
|
188
|
+
ipfsUrl: ipfs,
|
|
183
189
|
}, { commands, addContract: false });
|
|
184
190
|
// Exit with success
|
|
185
191
|
return this.exit(0);
|
|
@@ -208,7 +214,7 @@ class InitCommand extends core_1.Command {
|
|
|
208
214
|
abi,
|
|
209
215
|
abiPath,
|
|
210
216
|
directory,
|
|
211
|
-
|
|
217
|
+
source: fromContract,
|
|
212
218
|
indexEvents,
|
|
213
219
|
fromExample,
|
|
214
220
|
network,
|
|
@@ -216,6 +222,7 @@ class InitCommand extends core_1.Command {
|
|
|
216
222
|
contractName,
|
|
217
223
|
startBlock,
|
|
218
224
|
spkgPath,
|
|
225
|
+
ipfsUrl: ipfs,
|
|
219
226
|
});
|
|
220
227
|
if (!answers) {
|
|
221
228
|
this.exit(1);
|
|
@@ -230,7 +237,7 @@ class InitCommand extends core_1.Command {
|
|
|
230
237
|
directory: answers.directory,
|
|
231
238
|
abi: answers.abi,
|
|
232
239
|
network: answers.network,
|
|
233
|
-
|
|
240
|
+
source: answers.source,
|
|
234
241
|
indexEvents: answers.indexEvents,
|
|
235
242
|
contractName: answers.contractName,
|
|
236
243
|
node,
|
|
@@ -238,6 +245,7 @@ class InitCommand extends core_1.Command {
|
|
|
238
245
|
spkgPath: answers.spkgPath,
|
|
239
246
|
skipInstall,
|
|
240
247
|
skipGit,
|
|
248
|
+
ipfsUrl: answers.ipfs,
|
|
241
249
|
}, { commands, addContract: true });
|
|
242
250
|
}
|
|
243
251
|
// Exit with success
|
|
@@ -312,6 +320,11 @@ InitCommand.flags = {
|
|
|
312
320
|
description: 'Check https://thegraph.com/docs/en/developing/supported-networks/ for supported networks',
|
|
313
321
|
dependsOn: ['from-contract'],
|
|
314
322
|
}),
|
|
323
|
+
ipfs: core_1.Flags.string({
|
|
324
|
+
summary: 'IPFS node to use for fetching subgraph data.',
|
|
325
|
+
char: 'i',
|
|
326
|
+
default: ipfs_1.DEFAULT_IPFS_URL,
|
|
327
|
+
}),
|
|
315
328
|
};
|
|
316
329
|
exports.default = InitCommand;
|
|
317
330
|
async function processFromExampleInitForm({ directory: initDirectory, subgraphName: initSubgraphName, }) {
|
|
@@ -360,7 +373,7 @@ async function retryWithPrompt(func) {
|
|
|
360
373
|
}
|
|
361
374
|
return undefined;
|
|
362
375
|
}
|
|
363
|
-
async function processInitForm({ protocol: initProtocol, abi: initAbi, abiPath: initAbiPath, directory: initDirectory,
|
|
376
|
+
async function processInitForm({ protocol: initProtocol, abi: initAbi, abiPath: initAbiPath, directory: initDirectory, source: initContract, indexEvents: initIndexEvents, fromExample: initFromExample, network: initNetwork, subgraphName: initSubgraphName, contractName: initContractName, startBlock: initStartBlock, spkgPath: initSpkgPath, ipfsUrl, }) {
|
|
364
377
|
let abiFromEtherscan = undefined;
|
|
365
378
|
let startBlockFromEtherscan = undefined;
|
|
366
379
|
let contractNameFromEtherscan = undefined;
|
|
@@ -381,6 +394,7 @@ async function processInitForm({ protocol: initProtocol, abi: initAbi, abiPath:
|
|
|
381
394
|
},
|
|
382
395
|
});
|
|
383
396
|
const protocolInstance = new protocols_1.default(protocol);
|
|
397
|
+
const isComposedSubgraph = protocolInstance.isComposedSubgraph();
|
|
384
398
|
const isSubstreams = protocol === 'substreams';
|
|
385
399
|
initDebugger.extend('processInitForm')('isSubstreams: %O', isSubstreams);
|
|
386
400
|
const { subgraphName } = await gluegun_1.prompt.ask([
|
|
@@ -421,18 +435,20 @@ async function processInitForm({ protocol: initProtocol, abi: initAbi, abiPath:
|
|
|
421
435
|
},
|
|
422
436
|
},
|
|
423
437
|
]);
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
// - cosmos
|
|
438
|
+
const sourceMessage = isComposedSubgraph
|
|
439
|
+
? 'Source subgraph identifier'
|
|
440
|
+
: `Contract ${protocolInstance.getContract()?.identifierName()}`;
|
|
441
|
+
const { source } = await gluegun_1.prompt.ask([
|
|
429
442
|
{
|
|
430
443
|
type: 'input',
|
|
431
|
-
name: '
|
|
432
|
-
message:
|
|
433
|
-
skip: () =>
|
|
444
|
+
name: 'source',
|
|
445
|
+
message: sourceMessage,
|
|
446
|
+
skip: () => !isComposedSubgraph,
|
|
434
447
|
initial: initContract,
|
|
435
448
|
validate: async (value) => {
|
|
449
|
+
if (isComposedSubgraph) {
|
|
450
|
+
return true;
|
|
451
|
+
}
|
|
436
452
|
if (initFromExample !== undefined || !protocolInstance.hasContract()) {
|
|
437
453
|
return true;
|
|
438
454
|
}
|
|
@@ -445,7 +461,8 @@ async function processInitForm({ protocol: initProtocol, abi: initAbi, abiPath:
|
|
|
445
461
|
return valid ? true : error;
|
|
446
462
|
},
|
|
447
463
|
result: async (value) => {
|
|
448
|
-
if (initFromExample !== undefined || isSubstreams || initAbiPath) {
|
|
464
|
+
if (initFromExample !== undefined || isSubstreams || initAbiPath || isComposedSubgraph) {
|
|
465
|
+
initDebugger("value: '%s'", value);
|
|
449
466
|
return value;
|
|
450
467
|
}
|
|
451
468
|
const ABI = protocolInstance.getABI();
|
|
@@ -478,6 +495,15 @@ async function processInitForm({ protocol: initProtocol, abi: initAbi, abiPath:
|
|
|
478
495
|
},
|
|
479
496
|
},
|
|
480
497
|
]);
|
|
498
|
+
const { ipfs } = await gluegun_1.prompt.ask([
|
|
499
|
+
{
|
|
500
|
+
type: 'input',
|
|
501
|
+
name: 'ipfs',
|
|
502
|
+
message: `IPFS node to use for fetching subgraph manifest`,
|
|
503
|
+
initial: ipfsUrl,
|
|
504
|
+
skip: () => !isComposedSubgraph,
|
|
505
|
+
},
|
|
506
|
+
]);
|
|
481
507
|
const { spkg } = await gluegun_1.prompt.ask([
|
|
482
508
|
{
|
|
483
509
|
type: 'input',
|
|
@@ -497,9 +523,14 @@ async function processInitForm({ protocol: initProtocol, abi: initAbi, abiPath:
|
|
|
497
523
|
skip: () => !protocolInstance.hasABIs() ||
|
|
498
524
|
initFromExample !== undefined ||
|
|
499
525
|
abiFromEtherscan !== undefined ||
|
|
500
|
-
isSubstreams
|
|
526
|
+
isSubstreams ||
|
|
527
|
+
!!initAbiPath ||
|
|
528
|
+
isComposedSubgraph,
|
|
501
529
|
validate: async (value) => {
|
|
502
|
-
if (initFromExample ||
|
|
530
|
+
if (initFromExample ||
|
|
531
|
+
abiFromEtherscan ||
|
|
532
|
+
!protocolInstance.hasABIs() ||
|
|
533
|
+
isComposedSubgraph) {
|
|
503
534
|
return true;
|
|
504
535
|
}
|
|
505
536
|
const ABI = protocolInstance.getABI();
|
|
@@ -514,7 +545,10 @@ async function processInitForm({ protocol: initProtocol, abi: initAbi, abiPath:
|
|
|
514
545
|
}
|
|
515
546
|
},
|
|
516
547
|
result: async (value) => {
|
|
517
|
-
if (initFromExample ||
|
|
548
|
+
if (initFromExample ||
|
|
549
|
+
abiFromEtherscan ||
|
|
550
|
+
!protocolInstance.hasABIs() ||
|
|
551
|
+
isComposedSubgraph) {
|
|
518
552
|
return null;
|
|
519
553
|
}
|
|
520
554
|
const ABI = protocolInstance.getABI();
|
|
@@ -555,7 +589,7 @@ async function processInitForm({ protocol: initProtocol, abi: initAbi, abiPath:
|
|
|
555
589
|
name: 'indexEvents',
|
|
556
590
|
message: 'Index contract events as entities',
|
|
557
591
|
initial: true,
|
|
558
|
-
skip: () => !!initIndexEvents || isSubstreams,
|
|
592
|
+
skip: () => !!initIndexEvents || isSubstreams || isComposedSubgraph,
|
|
559
593
|
},
|
|
560
594
|
]);
|
|
561
595
|
return {
|
|
@@ -567,9 +601,10 @@ async function processInitForm({ protocol: initProtocol, abi: initAbi, abiPath:
|
|
|
567
601
|
fromExample: !!initFromExample,
|
|
568
602
|
network,
|
|
569
603
|
contractName,
|
|
570
|
-
|
|
604
|
+
source,
|
|
571
605
|
indexEvents,
|
|
572
606
|
spkgPath: spkg,
|
|
607
|
+
ipfs,
|
|
573
608
|
};
|
|
574
609
|
}
|
|
575
610
|
catch (e) {
|
|
@@ -753,14 +788,33 @@ async function initSubgraphFromExample({ fromExample, subgraphName, directory, s
|
|
|
753
788
|
}
|
|
754
789
|
printNextSteps.bind(this)({ subgraphName, directory }, { commands });
|
|
755
790
|
}
|
|
756
|
-
async function initSubgraphFromContract({ protocolInstance, subgraphName, directory, abi, network,
|
|
791
|
+
async function initSubgraphFromContract({ protocolInstance, subgraphName, directory, abi, network, source, indexEvents, contractName, node, startBlock, spkgPath, skipInstall, skipGit, ipfsUrl, }, { commands, addContract, }) {
|
|
757
792
|
const isSubstreams = protocolInstance.name === 'substreams';
|
|
793
|
+
const isComposedSubgraph = protocolInstance.isComposedSubgraph();
|
|
758
794
|
if (gluegun_1.filesystem.exists(directory) &&
|
|
759
795
|
!(await gluegun_1.prompt.confirm('Directory already exists, do you want to initialize the subgraph here (files will be overwritten) ?', false))) {
|
|
760
796
|
this.exit(1);
|
|
761
797
|
return;
|
|
762
798
|
}
|
|
763
|
-
|
|
799
|
+
let entities;
|
|
800
|
+
if (isComposedSubgraph) {
|
|
801
|
+
try {
|
|
802
|
+
const ipfsClient = (0, ipfs_http_client_1.create)({
|
|
803
|
+
url: (0, compiler_1.appendApiVersionForGraph)(ipfsUrl),
|
|
804
|
+
headers: {
|
|
805
|
+
...constants_1.GRAPH_CLI_SHARED_HEADERS,
|
|
806
|
+
},
|
|
807
|
+
});
|
|
808
|
+
const schemaString = await (0, utils_1.default)(ipfsClient, source);
|
|
809
|
+
const schema = await schema_2.default.loadFromString(schemaString);
|
|
810
|
+
entities = schema.getEntityNames();
|
|
811
|
+
}
|
|
812
|
+
catch (e) {
|
|
813
|
+
this.error(`Failed to load and parse subgraph schema: ${e.message}`, { exit: 1 });
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
if (!protocolInstance.isComposedSubgraph() &&
|
|
817
|
+
protocolInstance.hasABIs() &&
|
|
764
818
|
((0, schema_1.abiEvents)(abi).size === 0 ||
|
|
765
819
|
// @ts-expect-error TODO: the abiEvents result is expected to be a List, how's it an array?
|
|
766
820
|
(0, schema_1.abiEvents)(abi).length === 0)) {
|
|
@@ -774,12 +828,13 @@ async function initSubgraphFromContract({ protocolInstance, subgraphName, direct
|
|
|
774
828
|
subgraphName,
|
|
775
829
|
abi,
|
|
776
830
|
network,
|
|
777
|
-
|
|
831
|
+
source,
|
|
778
832
|
indexEvents,
|
|
779
833
|
contractName,
|
|
780
834
|
startBlock,
|
|
781
835
|
node,
|
|
782
836
|
spkgPath,
|
|
837
|
+
entities,
|
|
783
838
|
}, spinner);
|
|
784
839
|
await (0, scaffold_1.writeScaffold)(scaffold, directory, spinner);
|
|
785
840
|
return true;
|
|
@@ -7,6 +7,7 @@ export default class EthereumTypeGenerator {
|
|
|
7
7
|
private outputDir;
|
|
8
8
|
constructor(options: TypeGeneratorOptions);
|
|
9
9
|
loadABIs(subgraph: immutable.Map<any, any>): Promise<any>;
|
|
10
|
+
isValidAbiConfig(abiConfig: any): boolean;
|
|
10
11
|
_loadABI(dataSource: any, name: string, maybeRelativePath: string, spinner: Spinner): {
|
|
11
12
|
dataSource: any;
|
|
12
13
|
abi: ABI;
|
|
@@ -17,19 +17,36 @@ class EthereumTypeGenerator {
|
|
|
17
17
|
this.outputDir = options.outputDir;
|
|
18
18
|
}
|
|
19
19
|
async loadABIs(subgraph) {
|
|
20
|
-
return await (0, spinner_1.withSpinner)('Load contract ABIs', 'Failed to load contract ABIs',
|
|
20
|
+
return await (0, spinner_1.withSpinner)('Load contract ABIs', 'Failed to load contract ABIs', 'Warnings while loading contract ABIs', async (spinner) => {
|
|
21
21
|
try {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
const dataSources = subgraph.get('dataSources');
|
|
23
|
+
if (!dataSources)
|
|
24
|
+
return immutable_1.default.List();
|
|
25
|
+
return dataSources.reduce((accumulatedAbis, dataSource) => {
|
|
26
|
+
// Get ABIs from the current data source's mapping
|
|
27
|
+
const sourceAbis = dataSource.getIn(['mapping', 'abis']);
|
|
28
|
+
if (!sourceAbis)
|
|
29
|
+
return accumulatedAbis;
|
|
30
|
+
// Process each ABI in the current data source
|
|
31
|
+
return sourceAbis.reduce((currentAbis, abiConfig) => {
|
|
32
|
+
// Skip invalid ABI configurations
|
|
33
|
+
if (!this.isValidAbiConfig(abiConfig)) {
|
|
34
|
+
return currentAbis;
|
|
35
|
+
}
|
|
36
|
+
// Load and add the ABI to our list
|
|
37
|
+
const loadedAbi = this._loadABI(dataSource, abiConfig.get('name'), abiConfig.get('file'), spinner);
|
|
38
|
+
return currentAbis.push(loadedAbi);
|
|
39
|
+
}, accumulatedAbis);
|
|
40
|
+
}, immutable_1.default.List());
|
|
27
41
|
}
|
|
28
42
|
catch (e) {
|
|
29
43
|
throw Error(`Failed to load contract ABIs: ${e.message}`);
|
|
30
44
|
}
|
|
31
45
|
});
|
|
32
46
|
}
|
|
47
|
+
isValidAbiConfig(abiConfig) {
|
|
48
|
+
return !!(abiConfig?.get('name') && abiConfig?.get('file'));
|
|
49
|
+
}
|
|
33
50
|
_loadABI(dataSource, name, maybeRelativePath, spinner) {
|
|
34
51
|
try {
|
|
35
52
|
if (this.sourceDir) {
|
|
@@ -8,7 +8,7 @@ export default class Protocol {
|
|
|
8
8
|
config: ProtocolConfig;
|
|
9
9
|
constructor(datasource: any);
|
|
10
10
|
static availableProtocols(): immutable.Collection<ProtocolName, string[]>;
|
|
11
|
-
static availableNetworks(): immutable.Map<"ethereum" | "arweave" | "near" | "cosmos" | "substreams" | "substreams/triggers", immutable.List<string>>;
|
|
11
|
+
static availableNetworks(): immutable.Map<"ethereum" | "arweave" | "near" | "cosmos" | "substreams" | "substreams/triggers" | "subgraph", immutable.List<string>>;
|
|
12
12
|
static normalizeName(name: ProtocolName): ProtocolName;
|
|
13
13
|
displayName(): string;
|
|
14
14
|
isValidKindName(kind: string): boolean;
|
|
@@ -24,8 +24,9 @@ export default class Protocol {
|
|
|
24
24
|
getContract(): ContractCtor | undefined;
|
|
25
25
|
getManifestScaffold(): any;
|
|
26
26
|
getMappingScaffold(): any;
|
|
27
|
+
isComposedSubgraph(): boolean;
|
|
27
28
|
}
|
|
28
|
-
export type ProtocolName = 'arweave' | 'ethereum' | 'near' | 'cosmos' | 'substreams' | 'substreams/triggers';
|
|
29
|
+
export type ProtocolName = 'arweave' | 'ethereum' | 'near' | 'cosmos' | 'substreams' | 'substreams/triggers' | 'subgraph';
|
|
29
30
|
export interface ProtocolConfig {
|
|
30
31
|
displayName: string;
|
|
31
32
|
abi?: any;
|
package/dist/protocols/index.js
CHANGED
|
@@ -45,8 +45,11 @@ const contract_2 = __importDefault(require("./near/contract"));
|
|
|
45
45
|
const NearManifestScaffold = __importStar(require("./near/scaffold/manifest"));
|
|
46
46
|
const NearMappingScaffold = __importStar(require("./near/scaffold/mapping"));
|
|
47
47
|
const subgraph_4 = __importDefault(require("./near/subgraph"));
|
|
48
|
+
const SubgraphDataSourceManifestScaffold = __importStar(require("./subgraph/scaffold/manifest"));
|
|
49
|
+
const SubgraphMappingScaffold = __importStar(require("./subgraph/scaffold/mapping"));
|
|
50
|
+
const subgraph_5 = __importDefault(require("./subgraph/subgraph"));
|
|
48
51
|
const SubstreamsManifestScaffold = __importStar(require("./substreams/scaffold/manifest"));
|
|
49
|
-
const
|
|
52
|
+
const subgraph_6 = __importDefault(require("./substreams/subgraph"));
|
|
50
53
|
const protocolDebug = (0, debug_1.default)('graph-cli:protocol');
|
|
51
54
|
class Protocol {
|
|
52
55
|
static fromDataSources(dataSourcesAndTemplates) {
|
|
@@ -60,6 +63,7 @@ class Protocol {
|
|
|
60
63
|
* some other places use datasource object
|
|
61
64
|
*/
|
|
62
65
|
const name = typeof datasource === 'string' ? datasource : datasource.kind;
|
|
66
|
+
protocolDebug('Initializing protocol with datasource %O', datasource);
|
|
63
67
|
this.name = Protocol.normalizeName(name);
|
|
64
68
|
protocolDebug('Initializing protocol %s', this.name);
|
|
65
69
|
switch (this.name) {
|
|
@@ -75,6 +79,9 @@ class Protocol {
|
|
|
75
79
|
case 'near':
|
|
76
80
|
this.config = nearProtocol;
|
|
77
81
|
break;
|
|
82
|
+
case 'subgraph':
|
|
83
|
+
this.config = subgraphProtocol;
|
|
84
|
+
break;
|
|
78
85
|
case 'substreams':
|
|
79
86
|
this.config = substreamsProtocol;
|
|
80
87
|
/**
|
|
@@ -99,6 +106,7 @@ class Protocol {
|
|
|
99
106
|
near: ['near'],
|
|
100
107
|
cosmos: ['cosmos'],
|
|
101
108
|
substreams: ['substreams'],
|
|
109
|
+
subgraph: ['subgraph'],
|
|
102
110
|
});
|
|
103
111
|
}
|
|
104
112
|
static availableNetworks() {
|
|
@@ -153,6 +161,7 @@ class Protocol {
|
|
|
153
161
|
'uni-3', // Juno testnet
|
|
154
162
|
],
|
|
155
163
|
substreams: ['mainnet'],
|
|
164
|
+
subgraph: ['mainnet'],
|
|
156
165
|
});
|
|
157
166
|
}
|
|
158
167
|
static normalizeName(name) {
|
|
@@ -178,7 +187,7 @@ class Protocol {
|
|
|
178
187
|
// A problem with hasEvents usage in the codebase is that it's almost every where
|
|
179
188
|
// where used, the ABI data is actually use after the conditional, so it seems
|
|
180
189
|
// both concept are related. So internally, we map to this condition.
|
|
181
|
-
return this.hasABIs();
|
|
190
|
+
return this.hasABIs() && !this.isComposedSubgraph();
|
|
182
191
|
}
|
|
183
192
|
hasTemplates() {
|
|
184
193
|
return this.config.getTemplateCodeGen != null;
|
|
@@ -213,6 +222,9 @@ class Protocol {
|
|
|
213
222
|
getMappingScaffold() {
|
|
214
223
|
return this.config.mappingScaffold;
|
|
215
224
|
}
|
|
225
|
+
isComposedSubgraph() {
|
|
226
|
+
return this.name === 'subgraph';
|
|
227
|
+
}
|
|
216
228
|
}
|
|
217
229
|
exports.default = Protocol;
|
|
218
230
|
const arweaveProtocol = {
|
|
@@ -255,6 +267,20 @@ const ethereumProtocol = {
|
|
|
255
267
|
manifestScaffold: EthereumManifestScaffold,
|
|
256
268
|
mappingScaffold: EthereumMappingScaffold,
|
|
257
269
|
};
|
|
270
|
+
const subgraphProtocol = {
|
|
271
|
+
displayName: 'Subgraph',
|
|
272
|
+
abi: abi_1.default,
|
|
273
|
+
contract: undefined,
|
|
274
|
+
getTemplateCodeGen: undefined,
|
|
275
|
+
getTypeGenerator(options) {
|
|
276
|
+
return new type_generator_1.default(options);
|
|
277
|
+
},
|
|
278
|
+
getSubgraph(options) {
|
|
279
|
+
return new subgraph_5.default(options);
|
|
280
|
+
},
|
|
281
|
+
manifestScaffold: SubgraphDataSourceManifestScaffold,
|
|
282
|
+
mappingScaffold: SubgraphMappingScaffold,
|
|
283
|
+
};
|
|
258
284
|
const nearProtocol = {
|
|
259
285
|
displayName: 'NEAR',
|
|
260
286
|
abi: undefined,
|
|
@@ -274,7 +300,7 @@ const substreamsProtocol = {
|
|
|
274
300
|
getTypeGenerator: undefined,
|
|
275
301
|
getTemplateCodeGen: undefined,
|
|
276
302
|
getSubgraph(options) {
|
|
277
|
-
return new
|
|
303
|
+
return new subgraph_6.default(options);
|
|
278
304
|
},
|
|
279
305
|
manifestScaffold: SubstreamsManifestScaffold,
|
|
280
306
|
mappingScaffold: undefined,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Each referenced type's in any of the types below must be listed
|
|
2
|
+
# here either as `scalar` or `type` for the validation code to work
|
|
3
|
+
# properly.
|
|
4
|
+
#
|
|
5
|
+
# That's why `String` is listed as a scalar even though it's built-in
|
|
6
|
+
# GraphQL basic types.
|
|
7
|
+
scalar String
|
|
8
|
+
scalar File
|
|
9
|
+
scalar BigInt
|
|
10
|
+
scalar Boolean
|
|
11
|
+
scalar JSON
|
|
12
|
+
|
|
13
|
+
union StringOrBigInt = String | BigInt
|
|
14
|
+
|
|
15
|
+
type SubgraphManifest {
|
|
16
|
+
specVersion: String!
|
|
17
|
+
features: [String!]
|
|
18
|
+
schema: Schema!
|
|
19
|
+
description: String
|
|
20
|
+
repository: String
|
|
21
|
+
graft: Graft
|
|
22
|
+
dataSources: [DataSource!]!
|
|
23
|
+
indexerHints: IndexerHints
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type Schema {
|
|
27
|
+
file: File!
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
type IndexerHints {
|
|
31
|
+
prune: StringOrBigInt
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type DataSource {
|
|
35
|
+
kind: String!
|
|
36
|
+
name: String!
|
|
37
|
+
network: String
|
|
38
|
+
context: JSON
|
|
39
|
+
source: ContractSource!
|
|
40
|
+
mapping: ContractMapping!
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type ContractSource {
|
|
44
|
+
address: String!
|
|
45
|
+
startBlock: BigInt
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type ContractMapping {
|
|
49
|
+
kind: String
|
|
50
|
+
apiVersion: String!
|
|
51
|
+
language: String!
|
|
52
|
+
file: File!
|
|
53
|
+
abis: [ContractABI!]
|
|
54
|
+
entities: [String!]!
|
|
55
|
+
handlers: [EntityHandler!]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
type ContractABI {
|
|
59
|
+
name: String!
|
|
60
|
+
file: File!
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
type EntityHandler {
|
|
64
|
+
handler: String!
|
|
65
|
+
entity: String!
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type Graft {
|
|
69
|
+
base: String!
|
|
70
|
+
block: BigInt!
|
|
71
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const source: ({ contract, startBlock, }: {
|
|
2
|
+
contract: string;
|
|
3
|
+
contractName: string;
|
|
4
|
+
startBlock: string;
|
|
5
|
+
}) => string;
|
|
6
|
+
export declare const mapping: ({ entities, contractName, }: {
|
|
7
|
+
entities: string[];
|
|
8
|
+
contractName: string;
|
|
9
|
+
}) => string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mapping = exports.source = void 0;
|
|
4
|
+
const source = ({ contract, startBlock, }) => `
|
|
5
|
+
address: '${contract}'
|
|
6
|
+
startBlock: ${startBlock}`;
|
|
7
|
+
exports.source = source;
|
|
8
|
+
const mapping = ({ entities, contractName, }) => `
|
|
9
|
+
kind: ethereum/events
|
|
10
|
+
apiVersion: 0.0.7
|
|
11
|
+
language: wasm/assemblyscript
|
|
12
|
+
entities:
|
|
13
|
+
- ExampleEntity
|
|
14
|
+
handlers:
|
|
15
|
+
${entities
|
|
16
|
+
.map(entity => `
|
|
17
|
+
- handler: handle${entity}
|
|
18
|
+
entity: ${entity}`)
|
|
19
|
+
.join(' ')}
|
|
20
|
+
file: ./src/${contractName}.ts
|
|
21
|
+
`;
|
|
22
|
+
exports.mapping = mapping;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generatePlaceholderHandlers = void 0;
|
|
4
|
+
const generatePlaceholderHandlers = ({ entities, contract, }) => `
|
|
5
|
+
import { ExampleEntity } from '../generated/schema'
|
|
6
|
+
import {${entities.join(', ')}} from '../generated/subgraph-${contract}'
|
|
7
|
+
import { EntityTrigger } from '@graphprotocol/graph-ts'
|
|
8
|
+
|
|
9
|
+
${entities
|
|
10
|
+
.map(entityName => `
|
|
11
|
+
export function handle${entityName}(entity: EntityTrigger<${entityName}>): void {
|
|
12
|
+
// Empty handler for ${entityName}
|
|
13
|
+
}`)
|
|
14
|
+
.join('\n')}
|
|
15
|
+
`;
|
|
16
|
+
exports.generatePlaceholderHandlers = generatePlaceholderHandlers;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import immutable from 'immutable';
|
|
2
|
+
import { Subgraph, SubgraphOptions } from '../subgraph';
|
|
3
|
+
export default class SubgraphDataSource implements Subgraph {
|
|
4
|
+
manifest: SubgraphOptions['manifest'];
|
|
5
|
+
resolveFile: SubgraphOptions['resolveFile'];
|
|
6
|
+
protocol: SubgraphOptions['protocol'];
|
|
7
|
+
constructor(options: SubgraphOptions);
|
|
8
|
+
validateManifest(): immutable.List<unknown>;
|
|
9
|
+
handlerTypes(): immutable.List<never>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
const immutable_1 = __importDefault(require("immutable"));
|
|
7
|
+
class SubgraphDataSource {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.manifest = options.manifest;
|
|
10
|
+
this.resolveFile = options.resolveFile;
|
|
11
|
+
this.protocol = options.protocol;
|
|
12
|
+
}
|
|
13
|
+
validateManifest() {
|
|
14
|
+
return immutable_1.default.List();
|
|
15
|
+
}
|
|
16
|
+
handlerTypes() {
|
|
17
|
+
return immutable_1.default.List([]);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.default = SubgraphDataSource;
|
package/dist/scaffold/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export interface ScaffoldOptions {
|
|
|
11
11
|
subgraphName?: string;
|
|
12
12
|
node?: string;
|
|
13
13
|
spkgPath?: string;
|
|
14
|
+
entities?: string[];
|
|
14
15
|
}
|
|
15
16
|
export default class Scaffold {
|
|
16
17
|
protocol: Protocol;
|
|
@@ -23,6 +24,7 @@ export default class Scaffold {
|
|
|
23
24
|
node?: string;
|
|
24
25
|
startBlock?: string;
|
|
25
26
|
spkgPath?: string;
|
|
27
|
+
entities?: string[];
|
|
26
28
|
constructor(options: ScaffoldOptions);
|
|
27
29
|
generatePackageJson(): Promise<string>;
|
|
28
30
|
generatePackageJsonForSubstreams(): Promise<string>;
|
package/dist/scaffold/index.js
CHANGED
package/dist/schema.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { DocumentNode } from 'graphql/language';
|
|
2
2
|
import SchemaCodeGenerator from './codegen/schema';
|
|
3
3
|
export default class Schema {
|
|
4
|
-
filename: string;
|
|
5
4
|
document: string;
|
|
6
5
|
ast: DocumentNode;
|
|
7
|
-
|
|
6
|
+
filename?: string | undefined;
|
|
7
|
+
constructor(document: string, ast: DocumentNode, filename?: string | undefined);
|
|
8
8
|
codeGenerator(): SchemaCodeGenerator;
|
|
9
9
|
static load(filename: string): Promise<Schema>;
|
|
10
|
+
static loadFromString(document: string): Promise<Schema>;
|
|
11
|
+
getEntityNames(): string[];
|
|
10
12
|
}
|
package/dist/schema.js
CHANGED
|
@@ -30,11 +30,11 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
30
30
|
const graphql = __importStar(require("graphql/language"));
|
|
31
31
|
const schema_1 = __importDefault(require("./codegen/schema"));
|
|
32
32
|
class Schema {
|
|
33
|
-
constructor(
|
|
34
|
-
this.filename = filename;
|
|
33
|
+
constructor(document, ast, filename) {
|
|
35
34
|
this.document = document;
|
|
36
35
|
this.ast = ast;
|
|
37
36
|
this.filename = filename;
|
|
37
|
+
this.filename = filename;
|
|
38
38
|
this.document = document;
|
|
39
39
|
this.ast = ast;
|
|
40
40
|
}
|
|
@@ -44,7 +44,22 @@ class Schema {
|
|
|
44
44
|
static async load(filename) {
|
|
45
45
|
const document = await fs_extra_1.default.readFile(filename, 'utf-8');
|
|
46
46
|
const ast = graphql.parse(document);
|
|
47
|
-
return new Schema(
|
|
47
|
+
return new Schema(document, ast, filename);
|
|
48
|
+
}
|
|
49
|
+
static async loadFromString(document) {
|
|
50
|
+
try {
|
|
51
|
+
const ast = graphql.parse(document);
|
|
52
|
+
return new Schema(document, ast);
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
throw new Error(`Failed to load schema from string: ${e.message}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
getEntityNames() {
|
|
59
|
+
return this.ast.definitions
|
|
60
|
+
.filter(def => def.kind === 'ObjectTypeDefinition' &&
|
|
61
|
+
def.directives?.find(directive => directive.name.value === 'entity') !== undefined)
|
|
62
|
+
.map(entity => entity.name.value);
|
|
48
63
|
}
|
|
49
64
|
}
|
|
50
65
|
exports.default = Schema;
|
package/dist/type-generator.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export interface TypeGeneratorOptions {
|
|
|
9
9
|
skipMigrations?: boolean;
|
|
10
10
|
uncrashable: boolean;
|
|
11
11
|
uncrashableConfig: string;
|
|
12
|
+
subgraphSources: string[];
|
|
13
|
+
ipfsUrl: string;
|
|
12
14
|
}
|
|
13
15
|
export default class TypeGenerator {
|
|
14
16
|
private sourceDir;
|
|
@@ -22,7 +24,14 @@ export default class TypeGenerator {
|
|
|
22
24
|
quiet: boolean;
|
|
23
25
|
}): Promise<any>;
|
|
24
26
|
loadSchema(subgraph: immutable.Map<any, any>): Promise<any>;
|
|
25
|
-
generateTypesForSchema(schema
|
|
27
|
+
generateTypesForSchema({ schema, fileName, // Default file name
|
|
28
|
+
outputDir, // Default output directory
|
|
29
|
+
generateStoreMethods, }: {
|
|
30
|
+
schema: any;
|
|
31
|
+
fileName?: string;
|
|
32
|
+
outputDir?: string;
|
|
33
|
+
generateStoreMethods?: boolean;
|
|
34
|
+
}): Promise<any>;
|
|
26
35
|
generateTypesForDataSourceTemplates(subgraph: immutable.Map<any, any>): Promise<any>;
|
|
27
36
|
getFilesToWatch(): Promise<string[]>;
|
|
28
37
|
watchAndGenerateTypes(): Promise<void>;
|
package/dist/type-generator.js
CHANGED
|
@@ -31,17 +31,21 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
31
31
|
const toolbox = __importStar(require("gluegun"));
|
|
32
32
|
const graphql = __importStar(require("graphql/language"));
|
|
33
33
|
const immutable_1 = __importDefault(require("immutable"));
|
|
34
|
+
const ipfs_http_client_1 = require("ipfs-http-client");
|
|
34
35
|
const prettier_1 = __importDefault(require("prettier"));
|
|
35
36
|
// @ts-expect-error TODO: type out if necessary
|
|
36
37
|
const Index_bs_js_1 = __importDefault(require("@float-capital/float-subgraph-uncrashable/src/Index.bs.js"));
|
|
37
38
|
const template_1 = __importDefault(require("./codegen/template"));
|
|
38
39
|
const typescript_1 = require("./codegen/typescript");
|
|
40
|
+
const compiler_1 = require("./command-helpers/compiler");
|
|
39
41
|
const fs_1 = require("./command-helpers/fs");
|
|
40
42
|
const spinner_1 = require("./command-helpers/spinner");
|
|
43
|
+
const constants_1 = require("./constants");
|
|
41
44
|
const debug_1 = __importDefault(require("./debug"));
|
|
42
45
|
const migrations_1 = require("./migrations");
|
|
43
46
|
const schema_1 = __importDefault(require("./schema"));
|
|
44
47
|
const subgraph_1 = __importDefault(require("./subgraph"));
|
|
48
|
+
const utils_1 = __importDefault(require("./utils"));
|
|
45
49
|
const watcher_1 = __importDefault(require("./watcher"));
|
|
46
50
|
const typeGenDebug = (0, debug_1.default)('graph-cli:type-generator');
|
|
47
51
|
class TypeGenerator {
|
|
@@ -66,6 +70,10 @@ class TypeGenerator {
|
|
|
66
70
|
process.exit(0);
|
|
67
71
|
return;
|
|
68
72
|
}
|
|
73
|
+
if (this.options.subgraphSources.length > 0) {
|
|
74
|
+
typeGenDebug.extend('generateTypes')('Subgraph uses subgraph datasources.');
|
|
75
|
+
toolbox.print.success('Subgraph uses subgraph datasources.');
|
|
76
|
+
}
|
|
69
77
|
try {
|
|
70
78
|
if (!this.options.skipMigrations && this.options.subgraphManifest) {
|
|
71
79
|
await (0, migrations_1.applyMigrations)({
|
|
@@ -89,7 +97,25 @@ class TypeGenerator {
|
|
|
89
97
|
}
|
|
90
98
|
const schema = await this.loadSchema(subgraph);
|
|
91
99
|
typeGenDebug.extend('generateTypes')('Generating types for schema');
|
|
92
|
-
await this.generateTypesForSchema(schema);
|
|
100
|
+
await this.generateTypesForSchema({ schema });
|
|
101
|
+
if (this.options.subgraphSources.length > 0) {
|
|
102
|
+
const ipfsClient = (0, ipfs_http_client_1.create)({
|
|
103
|
+
url: (0, compiler_1.appendApiVersionForGraph)(this.options.ipfsUrl.toString()),
|
|
104
|
+
headers: {
|
|
105
|
+
...constants_1.GRAPH_CLI_SHARED_HEADERS,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
await Promise.all(this.options.subgraphSources.map(async (manifest) => {
|
|
109
|
+
const subgraphSchemaFile = await (0, utils_1.default)(ipfsClient, manifest);
|
|
110
|
+
const subgraphSchema = await schema_1.default.loadFromString(subgraphSchemaFile);
|
|
111
|
+
typeGenDebug.extend('generateTypes')(`Generating types for subgraph datasource ${manifest}`);
|
|
112
|
+
await this.generateTypesForSchema({
|
|
113
|
+
schema: subgraphSchema,
|
|
114
|
+
fileName: `subgraph-${manifest}.ts`,
|
|
115
|
+
generateStoreMethods: false,
|
|
116
|
+
});
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
93
119
|
toolbox.print.success('\nTypes generated successfully\n');
|
|
94
120
|
if (this.options.uncrashable && this.options.uncrashableConfig) {
|
|
95
121
|
await this.generateUncrashableEntities(schema);
|
|
@@ -132,19 +158,21 @@ class TypeGenerator {
|
|
|
132
158
|
return schema_1.default.load(absolutePath);
|
|
133
159
|
});
|
|
134
160
|
}
|
|
135
|
-
async generateTypesForSchema(schema
|
|
161
|
+
async generateTypesForSchema({ schema, fileName = 'schema.ts', // Default file name
|
|
162
|
+
outputDir = this.options.outputDir, // Default output directory
|
|
163
|
+
generateStoreMethods = true, }) {
|
|
136
164
|
return await (0, spinner_1.withSpinner)(`Generate types for GraphQL schema`, `Failed to generate types for GraphQL schema`, `Warnings while generating types for GraphQL schema`, async (spinner) => {
|
|
137
165
|
// Generate TypeScript module from schema
|
|
138
166
|
const codeGenerator = schema.codeGenerator();
|
|
139
167
|
const code = await prettier_1.default.format([
|
|
140
168
|
typescript_1.GENERATED_FILE_NOTE,
|
|
141
169
|
...codeGenerator.generateModuleImports(),
|
|
142
|
-
...codeGenerator.generateTypes(),
|
|
170
|
+
...codeGenerator.generateTypes(generateStoreMethods),
|
|
143
171
|
...codeGenerator.generateDerivedLoaders(),
|
|
144
172
|
].join('\n'), {
|
|
145
173
|
parser: 'typescript',
|
|
146
174
|
});
|
|
147
|
-
const outputFile = path_1.default.join(
|
|
175
|
+
const outputFile = path_1.default.join(outputDir, fileName); // Use provided outputDir and fileName
|
|
148
176
|
(0, spinner_1.step)(spinner, 'Write types to', (0, fs_1.displayPath)(outputFile));
|
|
149
177
|
await fs_extra_1.default.mkdirs(path_1.default.dirname(outputFile));
|
|
150
178
|
await fs_extra_1.default.writeFile(outputFile, code);
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function loadSubgraphSchemaFromIPFS(ipfsClient: any, manifest: string): Promise<string>;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
7
|
+
const debug_1 = __importDefault(require("./debug"));
|
|
8
|
+
const utilsDebug = (0, debug_1.default)('graph-cli:utils');
|
|
9
|
+
async function loadSubgraphSchemaFromIPFS(ipfsClient, manifest) {
|
|
10
|
+
try {
|
|
11
|
+
const manifestBuffer = ipfsClient.cat(manifest);
|
|
12
|
+
let manifestFile = '';
|
|
13
|
+
for await (const chunk of manifestBuffer) {
|
|
14
|
+
manifestFile += Buffer.from(chunk).toString('utf8'); // Explicitly convert each chunk to UTF-8
|
|
15
|
+
}
|
|
16
|
+
const manifestYaml = js_yaml_1.default.safeLoad(manifestFile);
|
|
17
|
+
let schema = manifestYaml.schema.file['/'];
|
|
18
|
+
if (schema.startsWith('/ipfs/')) {
|
|
19
|
+
schema = schema.slice(6);
|
|
20
|
+
}
|
|
21
|
+
const schemaBuffer = ipfsClient.cat(schema);
|
|
22
|
+
let schemaFile = '';
|
|
23
|
+
for await (const chunk of schemaBuffer) {
|
|
24
|
+
schemaFile += Buffer.from(chunk).toString('utf8'); // Explicitly convert each chunk to UTF-8
|
|
25
|
+
}
|
|
26
|
+
return schemaFile;
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
utilsDebug.extend('loadSubgraphSchemaFromIPFS')(`Failed to load schema from IPFS ${manifest}`);
|
|
30
|
+
utilsDebug.extend('loadSubgraphSchemaFromIPFS')(e);
|
|
31
|
+
throw Error(`Failed to load schema from IPFS ${manifest}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.default = loadSubgraphSchemaFromIPFS;
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.91.0-alpha-20241202202221-345552f",
|
|
3
3
|
"commands": {
|
|
4
4
|
"add": {
|
|
5
5
|
"id": "add",
|
|
@@ -239,6 +239,14 @@
|
|
|
239
239
|
"summary": "Generate Float Subgraph Uncrashable helper file.",
|
|
240
240
|
"allowNo": false
|
|
241
241
|
},
|
|
242
|
+
"ipfs": {
|
|
243
|
+
"name": "ipfs",
|
|
244
|
+
"type": "option",
|
|
245
|
+
"char": "i",
|
|
246
|
+
"summary": "IPFS node to use for fetching subgraph data.",
|
|
247
|
+
"multiple": false,
|
|
248
|
+
"default": "https://api.thegraph.com/ipfs/api/v0"
|
|
249
|
+
},
|
|
242
250
|
"uncrashable-config": {
|
|
243
251
|
"name": "uncrashable-config",
|
|
244
252
|
"type": "option",
|
|
@@ -453,7 +461,8 @@
|
|
|
453
461
|
"ethereum",
|
|
454
462
|
"near",
|
|
455
463
|
"cosmos",
|
|
456
|
-
"substreams"
|
|
464
|
+
"substreams",
|
|
465
|
+
"subgraph"
|
|
457
466
|
]
|
|
458
467
|
},
|
|
459
468
|
"node": {
|
|
@@ -550,6 +559,14 @@
|
|
|
550
559
|
"dependsOn": [
|
|
551
560
|
"from-contract"
|
|
552
561
|
]
|
|
562
|
+
},
|
|
563
|
+
"ipfs": {
|
|
564
|
+
"name": "ipfs",
|
|
565
|
+
"type": "option",
|
|
566
|
+
"char": "i",
|
|
567
|
+
"summary": "IPFS node to use for fetching subgraph data.",
|
|
568
|
+
"multiple": false,
|
|
569
|
+
"default": "https://api.thegraph.com/ipfs/api/v0"
|
|
553
570
|
}
|
|
554
571
|
},
|
|
555
572
|
"args": {
|