@graphprotocol/graph-cli 0.26.0 → 0.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +6 -6
  2. package/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/chain/ethereum.ts +1 -1
  3. package/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/chain/tendermint.ts +554 -0
  4. package/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/common/collections.ts +52 -2
  5. package/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/common/numbers.ts +11 -0
  6. package/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/common/value.ts +47 -0
  7. package/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/global/global.ts +150 -1
  8. package/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/index.ts +2 -0
  9. package/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/package.json +2 -1
  10. package/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/test/test.js +2 -0
  11. package/examples/basic-event-handlers/package.json +5 -5
  12. package/examples/basic-event-handlers/yarn.lock +12 -12
  13. package/examples/example-subgraph/package.json +1 -1
  14. package/examples/example-subgraph/yarn.lock +4 -4
  15. package/package.json +27 -24
  16. package/src/codegen/schema.js +104 -25
  17. package/src/codegen/schema.test.js +3 -7
  18. package/src/commands/codegen.js +1 -1
  19. package/src/commands/deploy.js +4 -2
  20. package/src/commands/init.js +3 -0
  21. package/src/commands/test.js +82 -59
  22. package/src/protocols/ethereum/codegen/abi.js +72 -2
  23. package/src/protocols/ethereum/manifest.graphql +92 -0
  24. package/src/protocols/index.js +51 -7
  25. package/src/protocols/near/manifest.graphql +57 -0
  26. package/src/protocols/tendermint/manifest.graphql +64 -0
  27. package/src/protocols/tendermint/subgraph.js +20 -0
  28. package/src/scaffold/index.js +1 -1
  29. package/src/subgraph.js +22 -13
  30. package/src/validation/manifest.js +29 -8
  31. package/src/validation/schema.js +120 -119
  32. package/tests/cli/validation/example-values-found.stderr +2 -2
  33. package/tests/cli/validation/invalid-manifest/subgraph.yaml +2 -1
  34. package/tests/cli/validation/invalid-manifest-cannot-infer-protocol/subgraph.yaml +12 -0
  35. package/tests/cli/validation/invalid-manifest-cannot-infer-protocol.stderr +5 -0
  36. package/tests/cli/validation/invalid-manifest.stderr +0 -3
  37. package/tests/cli/validation.test.js +8 -0
  38. package/manifest-schema.graphql +0 -122
@@ -0,0 +1,92 @@
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
+
11
+ type SubgraphManifest {
12
+ specVersion: String!
13
+ features: [String!]
14
+ schema: Schema!
15
+ description: String
16
+ repository: String
17
+ graft: Graft
18
+ dataSources: [DataSource!]!
19
+ templates: [DataSourceTemplate!]
20
+ }
21
+
22
+ type Schema {
23
+ file: File!
24
+ }
25
+
26
+ type DataSource {
27
+ kind: String!
28
+ name: String!
29
+ network: String
30
+ source: ContractSource!
31
+ mapping: ContractMapping!
32
+ }
33
+
34
+ type ContractSource {
35
+ address: String
36
+ abi: String!
37
+ startBlock: BigInt
38
+ }
39
+
40
+ type ContractMapping {
41
+ kind: String
42
+ apiVersion: String!
43
+ language: String!
44
+ file: File!
45
+ entities: [String!]!
46
+ abis: [ContractAbi!]!
47
+ blockHandlers: [BlockHandler!]
48
+ callHandlers: [CallHandler!]
49
+ eventHandlers: [ContractEventHandler!]
50
+ }
51
+
52
+ type ContractAbi {
53
+ name: String!
54
+ file: File!
55
+ }
56
+
57
+ type BlockHandler {
58
+ handler: String!
59
+ filter: BlockFilter
60
+ }
61
+
62
+ type BlockFilter {
63
+ kind: String!
64
+ }
65
+
66
+ type CallHandler {
67
+ function: String!
68
+ handler: String!
69
+ }
70
+
71
+ type ContractEventHandler {
72
+ event: String!
73
+ topic0: String
74
+ handler: String!
75
+ }
76
+
77
+ type Graft {
78
+ base: String!
79
+ block: BigInt!
80
+ }
81
+
82
+ type DataSourceTemplate {
83
+ kind: String!
84
+ name: String!
85
+ network: String
86
+ source: ContractSourceTemplate!
87
+ mapping: ContractMapping!
88
+ }
89
+
90
+ type ContractSourceTemplate {
91
+ abi: String!
92
+ }
@@ -4,6 +4,7 @@ const EthereumTemplateCodeGen = require('./ethereum/codegen/template')
4
4
  const EthereumABI = require('./ethereum/abi')
5
5
  const EthereumSubgraph = require('./ethereum/subgraph')
6
6
  const NearSubgraph = require('./near/subgraph')
7
+ const TendermintSubgraph = require('./tendermint/subgraph')
7
8
  const EthereumContract = require('./ethereum/contract')
8
9
  const NearContract = require('./near/contract')
9
10
  const EthereumManifestScaffold = require('./ethereum/scaffold/manifest')
@@ -27,6 +28,7 @@ module.exports = class Protocol {
27
28
  // New networks (or protocol perhaps) shouldn't have the `/contract` anymore (unless a new case makes use of it).
28
29
  ethereum: ['ethereum', 'ethereum/contract'],
29
30
  near: ['near'],
31
+ tendermint: ['tendermint']
30
32
  })
31
33
  }
32
34
 
@@ -60,10 +62,8 @@ module.exports = class Protocol {
60
62
  'aurora',
61
63
  'aurora-testnet',
62
64
  ],
63
- near: [
64
- 'near-mainnet',
65
- 'near-testnet'
66
- ],
65
+ near: ['near-mainnet', 'near-testnet'],
66
+ tendermint: ['cosmoshub-4']
67
67
  })
68
68
  }
69
69
 
@@ -79,6 +79,8 @@ module.exports = class Protocol {
79
79
  return 'Ethereum'
80
80
  case 'near':
81
81
  return 'NEAR'
82
+ case 'tendermint':
83
+ return 'Tendermint'
82
84
  }
83
85
  }
84
86
 
@@ -96,6 +98,19 @@ module.exports = class Protocol {
96
98
  return true
97
99
  case 'near':
98
100
  return false
101
+ case 'tendermint':
102
+ return false
103
+ }
104
+ }
105
+
106
+ hasContract() {
107
+ switch (this.name) {
108
+ case 'ethereum':
109
+ return true
110
+ case 'near':
111
+ return true
112
+ case 'tendermint':
113
+ return false
99
114
  }
100
115
  }
101
116
 
@@ -105,6 +120,19 @@ module.exports = class Protocol {
105
120
  return true
106
121
  case 'near':
107
122
  return false
123
+ case 'tendermint':
124
+ return false
125
+ }
126
+ }
127
+
128
+ hasTemplates() {
129
+ switch (this.name) {
130
+ case 'ethereum':
131
+ return true
132
+ case 'near':
133
+ return false
134
+ case 'tendermint':
135
+ return false
108
136
  }
109
137
  }
110
138
 
@@ -114,17 +142,23 @@ module.exports = class Protocol {
114
142
  return new EthereumTypeGenerator(options)
115
143
  case 'near':
116
144
  return null
145
+ case 'tendermint':
146
+ return null
117
147
  }
118
148
  }
119
149
 
120
150
  getTemplateCodeGen(template) {
151
+ if (!this.hasTemplates()) {
152
+ throw new Error(
153
+ `Template data sources with kind '${this.name}' are not supported yet`,
154
+ )
155
+ }
156
+
121
157
  switch (this.name) {
122
158
  case 'ethereum':
123
159
  return new EthereumTemplateCodeGen(template)
124
160
  default:
125
- throw new Error(
126
- `Template data sources with kind '${this.name}' are not supported yet`,
127
- )
161
+ throw new Error(`Template data sources with kind '${this.name}' is unknown`)
128
162
  }
129
163
  }
130
164
 
@@ -134,6 +168,8 @@ module.exports = class Protocol {
134
168
  return EthereumABI
135
169
  case 'near':
136
170
  return null
171
+ case 'tendermint':
172
+ return null
137
173
  }
138
174
  }
139
175
 
@@ -145,6 +181,8 @@ module.exports = class Protocol {
145
181
  return new EthereumSubgraph(optionsWithProtocol)
146
182
  case 'near':
147
183
  return new NearSubgraph(optionsWithProtocol)
184
+ case 'tendermint':
185
+ return new TendermintSubgraph(optionsWithProtocol)
148
186
  default:
149
187
  throw new Error(`Data sources with kind '${this.name}' are not supported yet`)
150
188
  }
@@ -156,6 +194,8 @@ module.exports = class Protocol {
156
194
  return EthereumContract
157
195
  case 'near':
158
196
  return NearContract
197
+ case 'tendermint':
198
+ return null
159
199
  }
160
200
  }
161
201
 
@@ -165,6 +205,8 @@ module.exports = class Protocol {
165
205
  return EthereumManifestScaffold
166
206
  case 'near':
167
207
  return NearManifestScaffold
208
+ case 'tendermint':
209
+ return null
168
210
  }
169
211
  }
170
212
 
@@ -174,6 +216,8 @@ module.exports = class Protocol {
174
216
  return EthereumMappingScaffold
175
217
  case 'near':
176
218
  return NearMappingScaffold
219
+ case 'tendermint':
220
+ return null
177
221
  }
178
222
  }
179
223
  }
@@ -0,0 +1,57 @@
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
+
11
+ type SubgraphManifest {
12
+ specVersion: String!
13
+ schema: Schema!
14
+ description: String
15
+ repository: String
16
+ graft: Graft
17
+ dataSources: [DataSource!]!
18
+ }
19
+
20
+ type Schema {
21
+ file: File!
22
+ }
23
+
24
+ type DataSource {
25
+ kind: String!
26
+ name: String!
27
+ network: String
28
+ source: ContractSource!
29
+ mapping: ContractMapping!
30
+ }
31
+
32
+ type ContractSource {
33
+ account: String
34
+ startBlock: BigInt
35
+ }
36
+
37
+ type ContractMapping {
38
+ apiVersion: String!
39
+ language: String!
40
+ file: File!
41
+ entities: [String!]!
42
+ blockHandlers: [BlockHandler!]
43
+ receiptHandlers: [ReceiptHandler!]
44
+ }
45
+
46
+ type BlockHandler {
47
+ handler: String!
48
+ }
49
+
50
+ type ReceiptHandler {
51
+ handler: String!
52
+ }
53
+
54
+ type Graft {
55
+ base: String!
56
+ block: BigInt!
57
+ }
@@ -0,0 +1,64 @@
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
+
11
+ type SubgraphManifest {
12
+ specVersion: String!
13
+ schema: Schema!
14
+ description: String
15
+ repository: String
16
+ graft: Graft
17
+ dataSources: [DataSource!]!
18
+ }
19
+
20
+ type Schema {
21
+ file: File!
22
+ }
23
+
24
+ type DataSource {
25
+ kind: String!
26
+ name: String!
27
+ network: String
28
+ source: ContractSource!
29
+ mapping: ContractMapping!
30
+ }
31
+
32
+ type ContractSource {
33
+ startBlock: BigInt
34
+ }
35
+
36
+ type ContractMapping {
37
+ apiVersion: String!
38
+ language: String!
39
+ file: File!
40
+ entities: [String!]!
41
+ blockHandlers: [BlockHandler!]
42
+ eventHandlers: [EventHandler!]
43
+ }
44
+
45
+ type BlockHandler {
46
+ handler: String!
47
+ }
48
+
49
+ enum EventOrigin {
50
+ BeginBlock
51
+ DeliverTx
52
+ EndBlock
53
+ }
54
+
55
+ type EventHandler {
56
+ event: String!
57
+ origin: EventOrigin
58
+ handler: String!
59
+ }
60
+
61
+ type Graft {
62
+ base: String!
63
+ block: BigInt!
64
+ }
@@ -0,0 +1,20 @@
1
+ const immutable = require('immutable')
2
+
3
+ module.exports = class TendermintSubgraph {
4
+ constructor(options = {}) {
5
+ this.manifest = options.manifest
6
+ this.resolveFile = options.resolveFile
7
+ this.protocol = options.protocol
8
+ }
9
+
10
+ validateManifest() {
11
+ return immutable.List()
12
+ }
13
+
14
+ handlerTypes() {
15
+ return immutable.List([
16
+ 'blockHandlers',
17
+ 'eventHandlers',
18
+ ])
19
+ }
20
+ }
@@ -50,7 +50,7 @@ module.exports = class Scaffold {
50
50
  },
51
51
  dependencies: {
52
52
  '@graphprotocol/graph-cli': GRAPH_CLI_VERSION,
53
- '@graphprotocol/graph-ts': `0.24.1`,
53
+ '@graphprotocol/graph-ts': `0.26.0`,
54
54
  },
55
55
  }),
56
56
  { parser: 'json' },
package/src/subgraph.js CHANGED
@@ -27,7 +27,7 @@ const buildCombinedWarning = (filename, warnings) =>
27
27
  ? warnings.reduce(
28
28
  (msg, w) =>
29
29
  `${msg}
30
-
30
+
31
31
  Path: ${w.get('path').size === 0 ? '/' : w.get('path').join(' > ')}
32
32
  ${w
33
33
  .get('message')
@@ -39,9 +39,21 @@ const buildCombinedWarning = (filename, warnings) =>
39
39
 
40
40
  module.exports = class Subgraph {
41
41
  static async validate(data, protocol, { resolveFile }) {
42
+ if (protocol.name == null) {
43
+ return immutable.fromJS([
44
+ {
45
+ path: [],
46
+ message: `Unable to determine for which protocol manifest file is built for. Ensure you have at least one 'dataSources' and/or 'templates' elements defined in your subgraph.`,
47
+ },
48
+ ])
49
+ }
50
+
42
51
  // Parse the default subgraph schema
43
52
  let schema = graphql.parse(
44
- await fs.readFile(path.join(__dirname, '..', 'manifest-schema.graphql'), 'utf-8'),
53
+ await fs.readFile(
54
+ path.join(__dirname, 'protocols', protocol.name, `manifest.graphql`),
55
+ 'utf-8',
56
+ ),
45
57
  )
46
58
 
47
59
  // Obtain the root `SubgraphManifest` type from the schema
@@ -146,10 +158,11 @@ At least one such handler must be defined.`,
146
158
  }
147
159
 
148
160
  static validateContractValues(manifest, protocol) {
149
- return validation.validateContractValues(
150
- manifest,
151
- protocol,
152
- )
161
+ if (!protocol.hasContract()){
162
+ return immutable.List()
163
+ }
164
+
165
+ return validation.validateContractValues(manifest, protocol)
153
166
  }
154
167
 
155
168
  // Validate that data source names are unique, so they don't overwrite each other.
@@ -200,17 +213,13 @@ More than one template named '${name}', template names must be unique.`,
200
213
  return yaml.stringify(manifest.toJS())
201
214
  }
202
215
 
203
- static async load(
204
- filename,
205
- { protocol, skipValidation } = { skipValidation: false }
206
- ) {
216
+ static async load(filename, { protocol, skipValidation } = { skipValidation: false }) {
207
217
  // Load and validate the manifest
208
218
  let data = null
209
219
 
210
- if(filename.match(/.js$/)) {
220
+ if (filename.match(/.js$/)) {
211
221
  data = require(path.resolve(filename))
212
- }
213
- else {
222
+ } else {
214
223
  data = yaml.parse(await fs.readFile(filename, 'utf-8'))
215
224
  }
216
225
 
@@ -52,8 +52,7 @@ const validators = immutable.fromJS({
52
52
  validators.get(ctx.getIn(['type', 'name', 'value']))(value, ctx),
53
53
 
54
54
  UnionTypeDefinition: (value, ctx) => {
55
- const unionVariants = ctx
56
- .getIn(['type', 'types'])
55
+ const unionVariants = ctx.getIn(['type', 'types'])
57
56
 
58
57
  let errors = List()
59
58
 
@@ -78,7 +77,10 @@ const validators = immutable.fromJS({
78
77
 
79
78
  NonNullType: (value, ctx) =>
80
79
  value !== null && value !== undefined
81
- ? validateValue(value, ctx.update('type', type => type.get('type')))
80
+ ? validateValue(
81
+ value,
82
+ ctx.update('type', type => type.get('type')),
83
+ )
82
84
  : immutable.fromJS([
83
85
  {
84
86
  path: ctx.get('path'),
@@ -126,7 +128,7 @@ const validators = immutable.fromJS({
126
128
  ),
127
129
  )
128
130
  : errors.push(
129
- key == 'templates'
131
+ key == 'templates' && ctx.get('protocol').hasTemplates()
130
132
  ? immutable.fromJS({
131
133
  path: ctx.get('path'),
132
134
  message:
@@ -149,6 +151,23 @@ const validators = immutable.fromJS({
149
151
  ])
150
152
  },
151
153
 
154
+ EnumTypeDefinition: (value, ctx) => {
155
+ const enumValues = ctx.getIn(['type', 'values']).map((v) => {
156
+ return v.getIn(['name', 'value'])
157
+ })
158
+
159
+ const allowedValues = enumValues.toArray().join(', ')
160
+
161
+ return enumValues.includes(value)
162
+ ? List()
163
+ : immutable.fromJS([
164
+ {
165
+ path: ctx.get('path'),
166
+ message: `Unexpected enum value: ${value}, allowed values: ${allowedValues}`,
167
+ },
168
+ ])
169
+ },
170
+
152
171
  String: (value, ctx) =>
153
172
  typeof value === 'string'
154
173
  ? List()
@@ -211,7 +230,8 @@ const validateValue = (value, ctx) => {
211
230
  }
212
231
 
213
232
  const validateDataSourceForNetwork = (dataSources, protocol) =>
214
- dataSources.filter(dataSource => protocol.isValidKindName(dataSource.kind))
233
+ dataSources
234
+ .filter(dataSource => protocol.isValidKindName(dataSource.kind))
215
235
  .reduce(
216
236
  (networks, dataSource) =>
217
237
  networks.update(dataSource.network, dataSources =>
@@ -235,11 +255,11 @@ const validateDataSourceNetworks = (value, protocol) => {
235
255
  ${networks
236
256
  .map(
237
257
  (dataSources, network) =>
238
- ` ${
258
+ ` ${
239
259
  network === undefined
240
260
  ? 'Data sources and templates having no network set'
241
- : `Data sources and templates using '${network}'`
242
- }:\n${dataSources.map(ds => ` - ${ds}`).join('\n')}`,
261
+ : `Data sources and templates using '${network}'`
262
+ }:\n${dataSources.map(ds => ` - ${ds}`).join('\n')}`,
243
263
  )
244
264
  .join('\n')}
245
265
  Recommendation: Make all data sources and templates use the same network name.`,
@@ -262,6 +282,7 @@ const validateManifest = (value, type, schema, protocol, { resolveFile }) => {
262
282
  path: [],
263
283
  errors: [],
264
284
  resolveFile,
285
+ protocol,
265
286
  }),
266
287
  )
267
288
  : immutable.fromJS([