@graphprotocol/graph-cli 0.24.1 → 0.25.3
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/examples/basic-event-handlers/node_modules/chalk/node_modules/supports-color/index.js +50 -0
- package/examples/basic-event-handlers/node_modules/chalk/node_modules/supports-color/license +21 -0
- package/examples/basic-event-handlers/node_modules/chalk/node_modules/supports-color/package.json +49 -0
- package/examples/basic-event-handlers/node_modules/chalk/node_modules/supports-color/readme.md +36 -0
- package/examples/basic-event-handlers/node_modules/cliui/node_modules/ansi-regex/index.js +10 -0
- package/examples/basic-event-handlers/node_modules/cliui/node_modules/ansi-regex/license +9 -0
- package/examples/basic-event-handlers/node_modules/cliui/node_modules/ansi-regex/package.json +53 -0
- package/examples/basic-event-handlers/node_modules/cliui/node_modules/ansi-regex/readme.md +46 -0
- package/examples/basic-event-handlers/node_modules/cliui/node_modules/strip-ansi/index.js +4 -0
- package/examples/basic-event-handlers/node_modules/cliui/node_modules/strip-ansi/license +9 -0
- package/examples/basic-event-handlers/node_modules/cliui/node_modules/strip-ansi/package.json +52 -0
- package/examples/basic-event-handlers/node_modules/cliui/node_modules/strip-ansi/readme.md +39 -0
- package/examples/basic-event-handlers/node_modules/keccak/build/Makefile +342 -0
- package/examples/basic-event-handlers/node_modules/keccak/build/Release/.deps/Release/obj.target/keccak/src/addon.o.d.raw +27 -0
- package/examples/basic-event-handlers/node_modules/keccak/build/binding.Makefile +6 -0
- package/examples/basic-event-handlers/node_modules/keccak/build/config.gypi +207 -0
- package/examples/basic-event-handlers/node_modules/keccak/build/gyp-mac-tool +615 -0
- package/examples/basic-event-handlers/node_modules/keccak/build/keccak.target.mk +209 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/.coveralls.yml +1 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/.eslintrc +14 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/.travis.yml +20 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/CHANGELOG.md +395 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/LICENSE +19 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/Makefile +58 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/README.md +368 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/karma.conf.js +70 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/node.js +1 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/package.json +43 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/src/browser.js +195 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/src/debug.js +225 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/src/index.js +10 -0
- package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/src/node.js +186 -0
- package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/LICENSE +15 -0
- package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/README.md +368 -0
- package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/changelog.md +67 -0
- package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/common.js +240 -0
- package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/glob.js +790 -0
- package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/package.json +43 -0
- package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/sync.js +486 -0
- package/examples/basic-event-handlers/node_modules/string-width/node_modules/ansi-regex/index.js +10 -0
- package/examples/basic-event-handlers/node_modules/string-width/node_modules/ansi-regex/license +9 -0
- package/examples/basic-event-handlers/node_modules/string-width/node_modules/ansi-regex/package.json +53 -0
- package/examples/basic-event-handlers/node_modules/string-width/node_modules/ansi-regex/readme.md +46 -0
- package/examples/basic-event-handlers/node_modules/string-width/node_modules/strip-ansi/index.js +4 -0
- package/examples/basic-event-handlers/node_modules/string-width/node_modules/strip-ansi/license +9 -0
- package/examples/basic-event-handlers/node_modules/string-width/node_modules/strip-ansi/package.json +52 -0
- package/examples/basic-event-handlers/node_modules/string-width/node_modules/strip-ansi/readme.md +39 -0
- package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/index.js +46 -0
- package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/license +21 -0
- package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/package.json +45 -0
- package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/readme.md +39 -0
- package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/string-width/index.js +37 -0
- package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/string-width/license +21 -0
- package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/string-width/package.json +56 -0
- package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/string-width/readme.md +42 -0
- package/package.json +2 -2
- package/src/codegen/schema.js +15 -5
- package/src/codegen/schema.test.js +368 -0
- package/src/codegen/types/defaults.js +34 -0
- package/src/codegen/types/index.js +8 -1
- package/src/codegen/typescript.js +7 -11
- package/src/command-helpers/scaffold.js +66 -0
- package/src/command-helpers/version.js +1 -1
- package/src/command-helpers/version.test.js +1 -1
- package/src/commands/init.js +129 -92
- package/src/commands/test.js +210 -27
- package/src/protocols/ethereum/contract.js +22 -0
- package/src/protocols/ethereum/scaffold/manifest.js +32 -0
- package/src/protocols/ethereum/scaffold/mapping.js +76 -0
- package/src/protocols/ethereum/subgraph.js +0 -14
- package/src/protocols/index.js +94 -12
- package/src/protocols/near/contract.js +46 -0
- package/src/protocols/near/scaffold/manifest.js +16 -0
- package/src/protocols/near/scaffold/mapping.js +39 -0
- package/src/protocols/near/subgraph.js +1 -23
- package/src/{scaffold.test.js → scaffold/ethereum.test.js} +27 -19
- package/src/scaffold/index.js +149 -0
- package/src/scaffold/mapping.js +49 -0
- package/src/scaffold/near.test.js +89 -0
- package/src/scaffold/schema.js +62 -0
- package/src/subgraph.js +8 -0
- package/src/validation/contract.js +56 -0
- package/src/validation/index.js +2 -1
- package/src/validation/manifest.js +0 -29
- package/tests/cli/init/{abis → ethereum/abis}/Marketplace.json +0 -0
- package/tests/cli/init/{abis → ethereum/abis}/OverloadedElements.json +0 -0
- package/tests/cli/init/{abis → ethereum/abis}/SoloMargin.json +0 -0
- package/tests/cli/init/{from-contract-with-abi-and-structs.stderr → ethereum/from-contract-with-abi-and-structs.stderr} +1 -1
- package/tests/cli/init/{from-contract-with-abi-and-structs.stdout → ethereum/from-contract-with-abi-and-structs.stdout} +0 -0
- package/tests/cli/init/{from-contract-with-abi.stderr → ethereum/from-contract-with-abi.stderr} +1 -1
- package/tests/cli/init/{from-contract-with-abi.stdout → ethereum/from-contract-with-abi.stdout} +0 -0
- package/tests/cli/init/{from-contract-with-overloaded-elements.stderr → ethereum/from-contract-with-overloaded-elements.stderr} +1 -1
- package/tests/cli/init/{from-contract-with-overloaded-elements.stdout → ethereum/from-contract-with-overloaded-elements.stdout} +0 -0
- package/tests/cli/init/{from-contract.stderr → ethereum/from-contract.stderr} +1 -1
- package/tests/cli/init/{from-contract.stdout → ethereum/from-contract.stdout} +0 -0
- package/tests/cli/init/{from-example.stderr → ethereum/from-example.stderr} +0 -0
- package/tests/cli/init/{from-example.stdout → ethereum/from-example.stdout} +0 -0
- package/tests/cli/init/near/from-contract.stderr +12 -0
- package/tests/cli/init/near/from-contract.stdout +12 -0
- package/tests/cli/init.test.js +143 -112
- package/tests/cli/util.js +56 -41
- package/tests/cli/validation/near-is-valid/subgraph.yaml +1 -0
- package/examples/basic-event-handlers/node_modules/mocha/lib/reporters/base.js.orig +0 -498
- package/examples/basic-event-handlers/node_modules/node-fetch/lib/index.js +0 -1416
- package/src/scaffold.js +0 -364
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const generatePlaceholderHandlers = () =>
|
|
2
|
+
`
|
|
3
|
+
import { near, BigInt } from '@graphprotocol/graph-ts'
|
|
4
|
+
import { ExampleEntity } from '../generated/schema'
|
|
5
|
+
|
|
6
|
+
export function handleReceipt(receiptWithOutcome: near.ReceiptWithOutcome): void {
|
|
7
|
+
// Entities can be loaded from the store using a string ID; this ID
|
|
8
|
+
// needs to be unique across all entities of the same type
|
|
9
|
+
let entity = ExampleEntity.load(receiptWithOutcome.receipt.id.toHex())
|
|
10
|
+
|
|
11
|
+
// Entities only exist after they have been saved to the store;
|
|
12
|
+
// \`null\` checks allow to create entities on demand
|
|
13
|
+
if (!entity) {
|
|
14
|
+
entity = new ExampleEntity(receiptWithOutcome.receipt.id.toHex())
|
|
15
|
+
|
|
16
|
+
// Entity fields can be set using simple assignments
|
|
17
|
+
entity.count = BigInt.fromI32(0)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// BigInt and BigDecimal math are supported
|
|
21
|
+
entity.count = entity.count + BigInt.fromI32(1)
|
|
22
|
+
|
|
23
|
+
// Entity fields can be set based on receipt information
|
|
24
|
+
entity.block = receiptWithOutcome.block.header.hash
|
|
25
|
+
|
|
26
|
+
// Entities can be written to the store with \`.save()\`
|
|
27
|
+
entity.save()
|
|
28
|
+
|
|
29
|
+
// Note: If a handler doesn't require existing field values, it is faster
|
|
30
|
+
// _not_ to load the entity from the store. Instead, create it fresh with
|
|
31
|
+
// \`new Entity(...)\`, set the fields that should be updated and save the
|
|
32
|
+
// entity back to the store. Fields that were not set or unset remain
|
|
33
|
+
// unchanged, allowing for partial updates to be applied.
|
|
34
|
+
}
|
|
35
|
+
`
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
generatePlaceholderHandlers,
|
|
39
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const immutable = require('immutable')
|
|
2
|
-
const { validateContractValues } = require('../../validation')
|
|
3
2
|
|
|
4
3
|
module.exports = class NearSubgraph {
|
|
5
4
|
constructor(options = {}) {
|
|
@@ -9,28 +8,7 @@ module.exports = class NearSubgraph {
|
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
validateManifest() {
|
|
12
|
-
return
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
validateContractAccounts() {
|
|
16
|
-
// Reference: https://docs.near.org/docs/concepts/account#account-id-rules
|
|
17
|
-
const MINIMUM_ACCOUNT_ID_LENGTH = 2
|
|
18
|
-
const MAXIMUM_ACCOUNT_ID_LENGTH = 64
|
|
19
|
-
const validateLength = accountId =>
|
|
20
|
-
accountId.length >= MINIMUM_ACCOUNT_ID_LENGTH &&
|
|
21
|
-
accountId.length <= MAXIMUM_ACCOUNT_ID_LENGTH
|
|
22
|
-
const nearAccountIdPattern = /^(([a-z\d]+[\-_])*[a-z\d]+\.)*([a-z\d]+[\-_])*[a-z\d]+$/
|
|
23
|
-
|
|
24
|
-
return validateContractValues(
|
|
25
|
-
this.manifest,
|
|
26
|
-
this.protocol,
|
|
27
|
-
'account',
|
|
28
|
-
accountId => validateLength(accountId) && nearAccountIdPattern.test(accountId),
|
|
29
|
-
`Must be between '${MINIMUM_ACCOUNT_ID_LENGTH}' and '${MAXIMUM_ACCOUNT_ID_LENGTH}' characters
|
|
30
|
-
An Account ID consists of Account ID parts separated by '.' (dots)
|
|
31
|
-
Each Account ID part consists of lowercase alphanumeric symbols separated by either a '_' (underscore) or '-' (dash)
|
|
32
|
-
For further information look for: https://docs.near.org/docs/concepts/account#account-id-rules`,
|
|
33
|
-
)
|
|
11
|
+
return immutable.List()
|
|
34
12
|
}
|
|
35
13
|
|
|
36
14
|
handlerTypes() {
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
const ABI = require('
|
|
1
|
+
const ABI = require('../protocols/ethereum/abi')
|
|
2
2
|
const immutable = require('immutable')
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
generateManifest,
|
|
6
|
-
generateMapping,
|
|
7
|
-
generateSchema,
|
|
8
|
-
} = require('./scaffold')
|
|
3
|
+
const Scaffold = require('./')
|
|
4
|
+
const Protocol = require('../protocols')
|
|
9
5
|
|
|
10
6
|
const TEST_EVENT = {
|
|
11
7
|
name: 'ExampleEvent',
|
|
@@ -73,21 +69,33 @@ const TEST_ABI = new ABI(
|
|
|
73
69
|
]),
|
|
74
70
|
)
|
|
75
71
|
|
|
76
|
-
|
|
72
|
+
const protocol = new Protocol('ethereum')
|
|
73
|
+
|
|
74
|
+
const scaffoldOptions = {
|
|
75
|
+
protocol,
|
|
76
|
+
abi: TEST_ABI,
|
|
77
|
+
contract: '0xf87e31492faf9a91b02ee0deaad50d51d56d5d4d',
|
|
78
|
+
network: 'kovan',
|
|
79
|
+
contractName: 'Contract',
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const scaffold = new Scaffold(scaffoldOptions)
|
|
83
|
+
|
|
84
|
+
const scaffoldWithIndexEvents = new Scaffold({
|
|
85
|
+
...scaffoldOptions,
|
|
86
|
+
indexEvents: true,
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
describe('Ethereum subgraph scaffolding', () => {
|
|
77
90
|
test('Manifest', () => {
|
|
78
91
|
expect(
|
|
79
|
-
generateManifest(
|
|
80
|
-
abi: TEST_ABI,
|
|
81
|
-
network: 'kovan',
|
|
82
|
-
address: '0xf87e31492faf9a91b02ee0deaad50d51d56d5d4d',
|
|
83
|
-
contractName: 'Contract'
|
|
84
|
-
}),
|
|
92
|
+
scaffold.generateManifest(),
|
|
85
93
|
).toEqual(`\
|
|
86
94
|
specVersion: 0.0.1
|
|
87
95
|
schema:
|
|
88
96
|
file: ./schema.graphql
|
|
89
97
|
dataSources:
|
|
90
|
-
- kind: ethereum
|
|
98
|
+
- kind: ethereum
|
|
91
99
|
name: Contract
|
|
92
100
|
network: kovan
|
|
93
101
|
source:
|
|
@@ -113,7 +121,7 @@ dataSources:
|
|
|
113
121
|
})
|
|
114
122
|
|
|
115
123
|
test('Schema (default)', () => {
|
|
116
|
-
expect(generateSchema(
|
|
124
|
+
expect(scaffold.generateSchema()).toEqual(`\
|
|
117
125
|
type ExampleEntity @entity {
|
|
118
126
|
id: ID!
|
|
119
127
|
count: BigInt!
|
|
@@ -124,7 +132,7 @@ type ExampleEntity @entity {
|
|
|
124
132
|
})
|
|
125
133
|
|
|
126
134
|
test('Schema (for indexing events)', () => {
|
|
127
|
-
expect(generateSchema(
|
|
135
|
+
expect(scaffoldWithIndexEvents.generateSchema()).toEqual(`\
|
|
128
136
|
type ExampleEvent @entity {
|
|
129
137
|
id: ID!
|
|
130
138
|
a: BigInt! # uint256
|
|
@@ -147,7 +155,7 @@ type ExampleEvent1 @entity {
|
|
|
147
155
|
})
|
|
148
156
|
|
|
149
157
|
test('Mapping (default)', () => {
|
|
150
|
-
expect(generateMapping(
|
|
158
|
+
expect(scaffold.generateMapping()).toEqual(`\
|
|
151
159
|
import { BigInt } from "@graphprotocol/graph-ts"
|
|
152
160
|
import {
|
|
153
161
|
Contract,
|
|
@@ -204,7 +212,7 @@ export function handleExampleEvent1(event: ExampleEvent1): void {}
|
|
|
204
212
|
})
|
|
205
213
|
|
|
206
214
|
test('Mapping (for indexing events)', () => {
|
|
207
|
-
expect(generateMapping(
|
|
215
|
+
expect(scaffoldWithIndexEvents.generateMapping()).toEqual(`\
|
|
208
216
|
import {
|
|
209
217
|
ExampleEvent as ExampleEventEvent,
|
|
210
218
|
ExampleEvent1 as ExampleEvent1Event
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
const prettier = require('prettier')
|
|
2
|
+
const pkginfo = require('pkginfo')(module)
|
|
3
|
+
|
|
4
|
+
const GRAPH_CLI_VERSION = process.env.GRAPH_CLI_TESTS
|
|
5
|
+
// JSON.stringify should remove this key, we will install the local
|
|
6
|
+
// graph-cli for the tests using `npm link` instead of fetching from npm.
|
|
7
|
+
? undefined
|
|
8
|
+
// For scaffolding real subgraphs
|
|
9
|
+
: `${module.exports.version}`
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
abiEvents,
|
|
13
|
+
generateEventType,
|
|
14
|
+
generateExampleEntityType,
|
|
15
|
+
} = require('./schema')
|
|
16
|
+
const { generateEventIndexingHandlers } = require('./mapping')
|
|
17
|
+
const { getSubgraphBasename } = require('../command-helpers/subgraph')
|
|
18
|
+
|
|
19
|
+
module.exports = class Scaffold {
|
|
20
|
+
constructor(options = {}) {
|
|
21
|
+
this.protocol = options.protocol
|
|
22
|
+
this.abi = options.abi
|
|
23
|
+
this.indexEvents = options.indexEvents
|
|
24
|
+
this.contract = options.contract
|
|
25
|
+
this.network = options.network
|
|
26
|
+
this.contractName = options.contractName
|
|
27
|
+
this.subgraphName = options.subgraphName
|
|
28
|
+
this.node = options.node
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
generatePackageJson() {
|
|
32
|
+
return prettier.format(
|
|
33
|
+
JSON.stringify({
|
|
34
|
+
name: getSubgraphBasename(this.subgraphName),
|
|
35
|
+
license: 'UNLICENSED',
|
|
36
|
+
scripts: {
|
|
37
|
+
codegen: 'graph codegen',
|
|
38
|
+
build: 'graph build',
|
|
39
|
+
deploy:
|
|
40
|
+
`graph deploy ` +
|
|
41
|
+
`--node ${this.node} ` +
|
|
42
|
+
this.subgraphName,
|
|
43
|
+
'create-local': `graph create --node http://localhost:8020/ ${this.subgraphName}`,
|
|
44
|
+
'remove-local': `graph remove --node http://localhost:8020/ ${this.subgraphName}`,
|
|
45
|
+
'deploy-local':
|
|
46
|
+
`graph deploy ` +
|
|
47
|
+
`--node http://localhost:8020/ ` +
|
|
48
|
+
`--ipfs http://localhost:5001 ` +
|
|
49
|
+
this.subgraphName,
|
|
50
|
+
},
|
|
51
|
+
dependencies: {
|
|
52
|
+
'@graphprotocol/graph-cli': GRAPH_CLI_VERSION,
|
|
53
|
+
'@graphprotocol/graph-ts': `0.24.1`,
|
|
54
|
+
},
|
|
55
|
+
}),
|
|
56
|
+
{ parser: 'json' },
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
generateManifest() {
|
|
61
|
+
const protocolManifest = this.protocol.getManifestScaffold()
|
|
62
|
+
|
|
63
|
+
return prettier.format(`
|
|
64
|
+
specVersion: 0.0.1
|
|
65
|
+
schema:
|
|
66
|
+
file: ./schema.graphql
|
|
67
|
+
dataSources:
|
|
68
|
+
- kind: ${this.protocol.name}
|
|
69
|
+
name: ${this.contractName}
|
|
70
|
+
network: ${this.network}
|
|
71
|
+
source: ${protocolManifest.source(this)}
|
|
72
|
+
mapping: ${protocolManifest.mapping(this)}
|
|
73
|
+
`,
|
|
74
|
+
{ parser: 'yaml' },
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
generateSchema() {
|
|
79
|
+
const hasEvents = this.protocol.hasEvents()
|
|
80
|
+
const events = hasEvents
|
|
81
|
+
? abiEvents(this.abi).toJS()
|
|
82
|
+
: []
|
|
83
|
+
|
|
84
|
+
return prettier.format(
|
|
85
|
+
hasEvents && this.indexEvents
|
|
86
|
+
? events.map(
|
|
87
|
+
event => generateEventType(event, this.protocol.name)
|
|
88
|
+
)
|
|
89
|
+
.join('\n\n')
|
|
90
|
+
: generateExampleEntityType(this.protocol, events),
|
|
91
|
+
{
|
|
92
|
+
parser: 'graphql',
|
|
93
|
+
},
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
generateTsConfig() {
|
|
98
|
+
return prettier.format(
|
|
99
|
+
JSON.stringify({
|
|
100
|
+
extends: '@graphprotocol/graph-ts/types/tsconfig.base.json',
|
|
101
|
+
include: ['src'],
|
|
102
|
+
}),
|
|
103
|
+
{ parser: 'json' },
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
generateMapping() {
|
|
108
|
+
const hasEvents = this.protocol.hasEvents()
|
|
109
|
+
const events = hasEvents
|
|
110
|
+
? abiEvents(this.abi).toJS()
|
|
111
|
+
: []
|
|
112
|
+
|
|
113
|
+
const protocolMapping = this.protocol.getMappingScaffold()
|
|
114
|
+
|
|
115
|
+
return prettier.format(
|
|
116
|
+
hasEvents && this.indexEvents
|
|
117
|
+
? generateEventIndexingHandlers(
|
|
118
|
+
events,
|
|
119
|
+
this.contractName,
|
|
120
|
+
)
|
|
121
|
+
: protocolMapping.generatePlaceholderHandlers({
|
|
122
|
+
...this,
|
|
123
|
+
events,
|
|
124
|
+
}),
|
|
125
|
+
{ parser: 'typescript', semi: false },
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
generateABIs() {
|
|
130
|
+
return this.protocol.hasABIs()
|
|
131
|
+
? {
|
|
132
|
+
[`${this.contractName}.json`]: prettier.format(JSON.stringify(this.abi.data), {
|
|
133
|
+
parser: 'json',
|
|
134
|
+
}),
|
|
135
|
+
}
|
|
136
|
+
: undefined
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
generate() {
|
|
140
|
+
return {
|
|
141
|
+
'package.json': this.generatePackageJson(),
|
|
142
|
+
'subgraph.yaml': this.generateManifest(),
|
|
143
|
+
'schema.graphql': this.generateSchema(),
|
|
144
|
+
'tsconfig.json': this.generateTsConfig(),
|
|
145
|
+
src: { 'mapping.ts': this.generateMapping() },
|
|
146
|
+
abis: this.generateABIs(),
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
|
|
3
|
+
const util = require('../codegen/util')
|
|
4
|
+
|
|
5
|
+
const generateFieldAssignment = path =>
|
|
6
|
+
`entity.${path.join('_')} = event.params.${path.join('.')}`
|
|
7
|
+
|
|
8
|
+
const generateFieldAssignments = ({ index, input }) =>
|
|
9
|
+
input.type === 'tuple'
|
|
10
|
+
? util
|
|
11
|
+
.unrollTuple({ value: input, index, path: [input.name || `param${index}`] })
|
|
12
|
+
.map(({ path }) => generateFieldAssignment(path))
|
|
13
|
+
: generateFieldAssignment([input.name || `param${index}`])
|
|
14
|
+
|
|
15
|
+
const generateEventFieldAssignments = event =>
|
|
16
|
+
event.inputs.reduce(
|
|
17
|
+
(acc, input, index) => acc.concat(generateFieldAssignments({ input, index })),
|
|
18
|
+
[],
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
const generateEventIndexingHandlers = (events, contractName) =>
|
|
22
|
+
`
|
|
23
|
+
import { ${events.map(
|
|
24
|
+
event => `${event._alias} as ${event._alias}Event`,
|
|
25
|
+
)}} from '../generated/${contractName}/${contractName}'
|
|
26
|
+
import { ${events.map(event => event._alias)} } from '../generated/schema'
|
|
27
|
+
|
|
28
|
+
${events
|
|
29
|
+
.map(
|
|
30
|
+
event =>
|
|
31
|
+
`
|
|
32
|
+
export function handle${event._alias}(event: ${event._alias}Event): void {
|
|
33
|
+
let entity = new ${
|
|
34
|
+
event._alias
|
|
35
|
+
}(event.transaction.hash.toHex() + '-' + event.logIndex.toString())
|
|
36
|
+
${generateEventFieldAssignments(event).join('\n')}
|
|
37
|
+
entity.save()
|
|
38
|
+
}
|
|
39
|
+
`,
|
|
40
|
+
)
|
|
41
|
+
.join('\n')}
|
|
42
|
+
`
|
|
43
|
+
|
|
44
|
+
module.exports = {
|
|
45
|
+
generateFieldAssignment,
|
|
46
|
+
generateFieldAssignments,
|
|
47
|
+
generateEventFieldAssignments,
|
|
48
|
+
generateEventIndexingHandlers,
|
|
49
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const immutable = require('immutable')
|
|
2
|
+
const Scaffold = require('./')
|
|
3
|
+
const Protocol = require('../protocols')
|
|
4
|
+
|
|
5
|
+
const protocol = new Protocol('near')
|
|
6
|
+
|
|
7
|
+
const scaffoldOptions = {
|
|
8
|
+
protocol,
|
|
9
|
+
contract: 'abc.def.near',
|
|
10
|
+
network: 'near-mainnet',
|
|
11
|
+
contractName: 'Contract',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const scaffold = new Scaffold(scaffoldOptions)
|
|
15
|
+
|
|
16
|
+
describe('NEAR subgraph scaffolding', () => {
|
|
17
|
+
test('Manifest', () => {
|
|
18
|
+
expect(
|
|
19
|
+
scaffold.generateManifest(),
|
|
20
|
+
).toEqual(`\
|
|
21
|
+
specVersion: 0.0.1
|
|
22
|
+
schema:
|
|
23
|
+
file: ./schema.graphql
|
|
24
|
+
dataSources:
|
|
25
|
+
- kind: near
|
|
26
|
+
name: Contract
|
|
27
|
+
network: near-mainnet
|
|
28
|
+
source:
|
|
29
|
+
account: "abc.def.near"
|
|
30
|
+
mapping:
|
|
31
|
+
apiVersion: 0.0.5
|
|
32
|
+
language: wasm/assemblyscript
|
|
33
|
+
entities:
|
|
34
|
+
- ExampleEntity
|
|
35
|
+
receiptHandlers:
|
|
36
|
+
- handler: handleReceipt
|
|
37
|
+
file: ./src/mapping.ts
|
|
38
|
+
`)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test('Schema (default)', () => {
|
|
42
|
+
expect(scaffold.generateSchema()).toEqual(`\
|
|
43
|
+
type ExampleEntity @entity {
|
|
44
|
+
id: ID!
|
|
45
|
+
block: Bytes!
|
|
46
|
+
count: BigInt!
|
|
47
|
+
}
|
|
48
|
+
`)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('Mapping (default)', () => {
|
|
52
|
+
expect(scaffold.generateMapping()).toEqual(`\
|
|
53
|
+
import { near, BigInt } from "@graphprotocol/graph-ts"
|
|
54
|
+
import { ExampleEntity } from "../generated/schema"
|
|
55
|
+
|
|
56
|
+
export function handleReceipt(
|
|
57
|
+
receiptWithOutcome: near.ReceiptWithOutcome
|
|
58
|
+
): void {
|
|
59
|
+
// Entities can be loaded from the store using a string ID; this ID
|
|
60
|
+
// needs to be unique across all entities of the same type
|
|
61
|
+
let entity = ExampleEntity.load(receiptWithOutcome.receipt.id.toHex())
|
|
62
|
+
|
|
63
|
+
// Entities only exist after they have been saved to the store;
|
|
64
|
+
// \`null\` checks allow to create entities on demand
|
|
65
|
+
if (!entity) {
|
|
66
|
+
entity = new ExampleEntity(receiptWithOutcome.receipt.id.toHex())
|
|
67
|
+
|
|
68
|
+
// Entity fields can be set using simple assignments
|
|
69
|
+
entity.count = BigInt.fromI32(0)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// BigInt and BigDecimal math are supported
|
|
73
|
+
entity.count = entity.count + BigInt.fromI32(1)
|
|
74
|
+
|
|
75
|
+
// Entity fields can be set based on receipt information
|
|
76
|
+
entity.block = receiptWithOutcome.block.header.hash
|
|
77
|
+
|
|
78
|
+
// Entities can be written to the store with \`.save()\`
|
|
79
|
+
entity.save()
|
|
80
|
+
|
|
81
|
+
// Note: If a handler doesn't require existing field values, it is faster
|
|
82
|
+
// _not_ to load the entity from the store. Instead, create it fresh with
|
|
83
|
+
// \`new Entity(...)\`, set the fields that should be updated and save the
|
|
84
|
+
// entity back to the store. Fields that were not set or unset remain
|
|
85
|
+
// unchanged, allowing for partial updates to be applied.
|
|
86
|
+
}
|
|
87
|
+
`)
|
|
88
|
+
})
|
|
89
|
+
})
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const { ascTypeForProtocol, valueTypeForAsc } = require('../codegen/types')
|
|
2
|
+
const util = require('../codegen/util')
|
|
3
|
+
|
|
4
|
+
const abiEvents = abi =>
|
|
5
|
+
util.disambiguateNames({
|
|
6
|
+
values: abi.data.filter(item => item.get('type') === 'event'),
|
|
7
|
+
getName: event => event.get('name'),
|
|
8
|
+
setName: (event, name) => event.set('_alias', name),
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
const protocolTypeToGraphQL = (protocol, name) => {
|
|
12
|
+
let ascType = ascTypeForProtocol(protocol, name)
|
|
13
|
+
return valueTypeForAsc(ascType)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const generateField = ({ name, type, protocolName }) =>
|
|
17
|
+
`${name}: ${protocolTypeToGraphQL(protocolName, type)}! # ${type}`
|
|
18
|
+
|
|
19
|
+
const generateEventFields = ({ index, input, protocolName }) =>
|
|
20
|
+
input.type == 'tuple'
|
|
21
|
+
? util
|
|
22
|
+
.unrollTuple({ value: input, path: [input.name || `param${index}`], index })
|
|
23
|
+
.map(({ path, type }) => generateField({ name: path.join('_'), type, protocolName }))
|
|
24
|
+
: [generateField({ name: input.name || `param${index}`, type: input.type, protocolName })]
|
|
25
|
+
|
|
26
|
+
const generateEventType = (event, protocolName) => `type ${event._alias} @entity {
|
|
27
|
+
id: ID!
|
|
28
|
+
${event.inputs
|
|
29
|
+
.reduce(
|
|
30
|
+
(acc, input, index) => acc.concat(generateEventFields({ input, index, protocolName })),
|
|
31
|
+
[],
|
|
32
|
+
)
|
|
33
|
+
.join('\n')}
|
|
34
|
+
}`
|
|
35
|
+
|
|
36
|
+
const generateExampleEntityType = (protocol, events) => {
|
|
37
|
+
if (protocol.hasABIs() && events.length > 0) {
|
|
38
|
+
return `type ExampleEntity @entity {
|
|
39
|
+
id: ID!
|
|
40
|
+
count: BigInt!
|
|
41
|
+
${events[0].inputs
|
|
42
|
+
.reduce((acc, input, index) => acc.concat(generateEventFields({ input, index, protocolName: protocol.name })), [])
|
|
43
|
+
.slice(0, 2)
|
|
44
|
+
.join('\n')}
|
|
45
|
+
}`
|
|
46
|
+
} else {
|
|
47
|
+
return `type ExampleEntity @entity {
|
|
48
|
+
id: ID!
|
|
49
|
+
block: Bytes!
|
|
50
|
+
count: BigInt!
|
|
51
|
+
}`
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = {
|
|
56
|
+
abiEvents,
|
|
57
|
+
protocolTypeToGraphQL,
|
|
58
|
+
generateField,
|
|
59
|
+
generateEventFields,
|
|
60
|
+
generateEventType,
|
|
61
|
+
generateExampleEntityType,
|
|
62
|
+
}
|
package/src/subgraph.js
CHANGED
|
@@ -145,6 +145,13 @@ At least one such handler must be defined.`,
|
|
|
145
145
|
}, immutable.List())
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
static validateContractValues(manifest, protocol) {
|
|
149
|
+
return validation.validateContractValues(
|
|
150
|
+
manifest,
|
|
151
|
+
protocol,
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
148
155
|
// Validate that data source names are unique, so they don't overwrite each other.
|
|
149
156
|
static validateUniqueDataSourceNames(manifest) {
|
|
150
157
|
let names = []
|
|
@@ -231,6 +238,7 @@ More than one template named '${name}', template names must be unique.`,
|
|
|
231
238
|
? immutable.List()
|
|
232
239
|
: immutable.List.of(
|
|
233
240
|
...protocolSubgraph.validateManifest(),
|
|
241
|
+
...Subgraph.validateContractValues(manifest, protocol),
|
|
234
242
|
...Subgraph.validateUniqueDataSourceNames(manifest),
|
|
235
243
|
...Subgraph.validateUniqueTemplateNames(manifest),
|
|
236
244
|
...Subgraph.validateHandlers(manifest, protocol, protocolSubgraph),
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const immutable = require('immutable')
|
|
2
|
+
|
|
3
|
+
const validateContract = (value, ProtocolContract) => {
|
|
4
|
+
const contract = new ProtocolContract(value)
|
|
5
|
+
|
|
6
|
+
const { valid, error } = contract.validate()
|
|
7
|
+
|
|
8
|
+
if (!valid) {
|
|
9
|
+
return {
|
|
10
|
+
valid,
|
|
11
|
+
error: `Contract ${ProtocolContract.identifierName()} is invalid: ${value}\n${error}`,
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return { valid, error }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const validateContractValues = (manifest, protocol) => {
|
|
19
|
+
const ProtocolContract = protocol.getContract()
|
|
20
|
+
|
|
21
|
+
const fieldName = ProtocolContract.identifierName()
|
|
22
|
+
|
|
23
|
+
return manifest
|
|
24
|
+
.get('dataSources')
|
|
25
|
+
.filter(dataSource => protocol.isValidKindName(dataSource.get('kind')))
|
|
26
|
+
.reduce((errors, dataSource, dataSourceIndex) => {
|
|
27
|
+
let path = ['dataSources', dataSourceIndex, 'source', fieldName]
|
|
28
|
+
|
|
29
|
+
// No need to validate if the source has no contract field
|
|
30
|
+
if (!dataSource.get('source').has(fieldName)) {
|
|
31
|
+
return errors
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let contractValue = dataSource.getIn(['source', fieldName])
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
const { valid, error } = validateContract(contractValue, ProtocolContract)
|
|
38
|
+
|
|
39
|
+
// Validate whether the contract is valid for the protocol
|
|
40
|
+
if (valid) {
|
|
41
|
+
return errors
|
|
42
|
+
} else {
|
|
43
|
+
return errors.push(
|
|
44
|
+
immutable.fromJS({
|
|
45
|
+
path,
|
|
46
|
+
message: error,
|
|
47
|
+
}),
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
}, immutable.List())
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = {
|
|
54
|
+
validateContract,
|
|
55
|
+
validateContractValues,
|
|
56
|
+
}
|
package/src/validation/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
validateSchema: require('./schema').validateSchema,
|
|
3
3
|
validateManifest: require('./manifest').validateManifest,
|
|
4
|
-
validateContractValues: require('./
|
|
4
|
+
validateContractValues: require('./contract').validateContractValues,
|
|
5
|
+
validateContract: require('./contract').validateContract,
|
|
5
6
|
}
|
|
@@ -282,35 +282,6 @@ const validateManifest = (value, type, schema, protocol, { resolveFile }) => {
|
|
|
282
282
|
return validateDataSourceNetworks(value, protocol)
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
const validateContractValues = (manifest, protocol, fieldName, validator, errorMessage) =>
|
|
286
|
-
manifest
|
|
287
|
-
.get('dataSources')
|
|
288
|
-
.filter(dataSource => protocol.isValidKindName(dataSource.get('kind')))
|
|
289
|
-
.reduce((errors, dataSource, dataSourceIndex) => {
|
|
290
|
-
let path = ['dataSources', dataSourceIndex, 'source', fieldName]
|
|
291
|
-
|
|
292
|
-
// No need to validate if the source has no contract field
|
|
293
|
-
if (!dataSource.get('source').has(fieldName)) {
|
|
294
|
-
return errors
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
let contractValue = dataSource.getIn(['source', fieldName])
|
|
298
|
-
|
|
299
|
-
// Validate whether the contract is valid
|
|
300
|
-
if (validator(contractValue)) {
|
|
301
|
-
return errors
|
|
302
|
-
} else {
|
|
303
|
-
return errors.push(
|
|
304
|
-
immutable.fromJS({
|
|
305
|
-
path,
|
|
306
|
-
message: `\
|
|
307
|
-
Contract ${fieldName} is invalid: ${contractValue}${errorMessage ? `\n${errorMessage}` : ''}`,
|
|
308
|
-
}),
|
|
309
|
-
)
|
|
310
|
-
}
|
|
311
|
-
}, immutable.List())
|
|
312
|
-
|
|
313
285
|
module.exports = {
|
|
314
286
|
validateManifest,
|
|
315
|
-
validateContractValues,
|
|
316
287
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/tests/cli/init/{from-contract-with-abi.stdout → ethereum/from-contract-with-abi.stdout}
RENAMED
|
File without changes
|