@@ -4,130 +4,148 @@ import {
4
4
BigInt ,
5
5
Bytes ,
6
6
DataSourceContext ,
7
+ store ,
8
+ log ,
7
9
} from "@graphprotocol/graph-ts" ;
8
10
import { TestEvent } from "../generated/Contract/Contract" ;
9
- import { IpfsFile , IpfsFile1 , SpawnTestEntity } from "../generated/schema" ;
10
-
11
- // CID of `file-data-sources/abis/Contract.abi` after being processed by graph-cli.
12
- const KNOWN_CID = "QmQ2REmceVtzawp7yrnxLQXgNNCtFHEnig6fL9aqE1kcWq" ;
13
-
14
- export function handleBlock ( block : ethereum . Block ) : void {
15
- let entity = new IpfsFile ( "onchain" ) ;
16
- entity . content = "onchain" ;
17
- entity . save ( ) ;
18
-
19
- // This will create the same data source twice, once at block 0 and another at block 2.
20
- // The creation at block 2 should be detected as a duplicate and therefore a noop.
21
- if ( block . number == BigInt . fromI32 ( 0 ) || block . number == BigInt . fromI32 ( 2 ) ) {
22
- dataSource . create ( "File" , [ KNOWN_CID ] ) ;
11
+ import { FileEntity , Foo } from "../generated/schema" ;
12
+
13
+ const ONCHAIN_FROM_OFFCHAIN = "CREATE_ONCHAIN_DATASOURCE_FROM_OFFCHAIN_HANDLER" ;
14
+ const CREATE_FILE = "CREATE_FILE" ;
15
+ // const CREATE_FILE_FROM_HANDLE_FILE = "CREATE_FILE_FROM_HANDLE_FILE";
16
+ const CREATE_UNDEFINED_ENTITY = "CREATE_UNDEFINED_ENTITY" ;
17
+ const CREATE_CONFLICTING_ENTITY = "CREATE_CONFLICTING_ENTITY" ;
18
+ const SPAWN_FDS_FROM_OFFCHAIN_HANDLER = "SPAWN_FDS_FROM_OFFCHAIN_HANDLER" ;
19
+ const ACCESS_AND_UPDATE_OFFCHAIN_ENTITY_IN_ONCHAIN_HANDLER =
20
+ "ACCESS_AND_UPDATE_OFFCHAIN_ENTITY_IN_ONCHAIN_HANDLER" ;
21
+ const ACCESS_FILE_ENTITY_THROUGH_DERIVED_FIELD =
22
+ "ACCESS_FILE_ENTITY_THROUGH_DERIVED_FIELD" ;
23
+
24
+ const CREATE_FOO = "CREATE_FOO" ;
25
+ export function handleTestEvent ( event : TestEvent ) : void {
26
+ if ( event . params . testCommand == CREATE_FILE ) {
27
+ dataSource . createWithContext (
28
+ "File" ,
29
+ [ event . params . data ] ,
30
+ new DataSourceContext ( ) ,
31
+ ) ;
23
32
}
24
33
25
- if ( block . number == BigInt . fromI32 ( 1 ) ) {
26
- let entity = IpfsFile . load ( "onchain" ) ! ;
27
- assert ( entity . content == "onchain" ) ;
28
-
29
- // The test assumes file data sources are processed in the block in which they are created.
30
- // So the ds created at block 0 will have been processed.
31
- //
32
- // Test that onchain data sources cannot read offchain data.
33
- assert ( IpfsFile . load ( KNOWN_CID ) == null ) ;
34
+ if ( event . params . testCommand == SPAWN_FDS_FROM_OFFCHAIN_HANDLER ) {
35
+ let comma_separated_hash = event . params . data ;
36
+ let hash1 = comma_separated_hash . split ( "," ) [ 0 ] ;
37
+ let hash2 = comma_separated_hash . split ( "," ) [ 1 ] ;
38
+ let context = new DataSourceContext ( ) ;
39
+ context . setString ( "command" , SPAWN_FDS_FROM_OFFCHAIN_HANDLER ) ;
40
+ context . setString ( "hash" , hash2 ) ;
34
41
35
- // Test that using an invalid CID will be ignored
36
- dataSource . create ( "File" , [ "hi, I'm not valid" ] ) ;
42
+ log . info (
43
+ "Creating file data source from handleFile, command : {} ,hash1: {}, hash2: {}" ,
44
+ [ SPAWN_FDS_FROM_OFFCHAIN_HANDLER , hash1 , hash2 ] ,
45
+ ) ;
46
+ dataSource . createWithContext ( "File" , [ hash1 ] , context ) ;
37
47
}
38
48
39
- // This will invoke File1 data source with same CID, which will be used
40
- // to test whether same cid is triggered across different data source.
41
- if ( block . number == BigInt . fromI32 ( 3 ) ) {
42
- // Test that onchain data sources cannot read offchain data (again, but this time more likely to hit the DB than the write queue).
43
- assert ( IpfsFile . load ( KNOWN_CID ) == null ) ;
44
-
45
- dataSource . create ( "File1" , [ KNOWN_CID ] ) ;
49
+ if ( event . params . testCommand == ONCHAIN_FROM_OFFCHAIN ) {
50
+ let context = new DataSourceContext ( ) ;
51
+ context . setString ( "command" , ONCHAIN_FROM_OFFCHAIN ) ;
52
+ context . setString ( "address" , "0x0000000000000000000000000000000000000000" ) ;
53
+ dataSource . createWithContext ( "File" , [ event . params . data ] , context ) ;
46
54
}
47
- }
48
55
49
- export function handleTestEvent ( event : TestEvent ) : void {
50
- let command = event . params . testCommand ;
51
-
52
- if ( command == "createFile2" ) {
53
- // Will fail the subgraph when processed due to mismatch in the entity type and 'entities'.
54
- dataSource . create ( "File2" , [ KNOWN_CID ] ) ;
55
- } else if ( command == "saveConflictingEntity" ) {
56
- // Will fail the subgraph because the same entity has been created in a file data source.
57
- let entity = new IpfsFile ( KNOWN_CID ) ;
58
- entity . content = "empty" ;
59
- entity . save ( ) ;
60
- } else if ( command == "createFile1" ) {
61
- // Will fail the subgraph with a conflict between two entities created by offchain data sources.
62
- let context = new DataSourceContext ( ) ;
63
- context . setBytes ( "hash" , event . block . hash ) ;
64
- dataSource . createWithContext ( "File1" , [ KNOWN_CID ] , context ) ;
65
- } else if ( command == "spawnOffChainHandlerTest" ) {
66
- // Used to test the spawning of a file data source from another file data source handler.
67
- // `SpawnTestHandler` will spawn a file data source that will be handled by `spawnOffChainHandlerTest`,
68
- // which creates another file data source `OffChainDataSource`, which will be handled by `handleSpawnedTest`.
56
+ if ( event . params . testCommand == CREATE_UNDEFINED_ENTITY ) {
57
+ log . info ( "Creating undefined entity" , [ ] ) ;
69
58
let context = new DataSourceContext ( ) ;
70
- context . setString ( "command" , command ) ;
71
- dataSource . createWithContext ( "SpawnTestHandler" , [ KNOWN_CID ] , context ) ;
72
- } else if ( command == "spawnOnChainHandlerTest" ) {
73
- // Used to test the failure of spawning of on-chain data source from a file data source handler.
74
- // `SpawnTestHandler` will spawn a file data source that will be handled by `spawnTestHandler`,
75
- // which creates an `OnChainDataSource`, which should fail since spawning onchain datasources
76
- // from offchain handlers is not allowed.
77
- let context = new DataSourceContext ( ) ;
78
- context . setString ( "command" , command ) ;
79
- dataSource . createWithContext ( "SpawnTestHandler" , [ KNOWN_CID ] , context ) ;
80
- } else {
81
- assert ( false , "Unknown command: " + command ) ;
59
+ context . setString ( "command" , CREATE_UNDEFINED_ENTITY ) ;
60
+ dataSource . createWithContext ( "File" , [ event . params . data ] , context ) ;
82
61
}
83
- }
84
62
85
- export function handleFile ( data : Bytes ) : void {
86
- // Test that offchain data sources cannot read onchain data.
87
- assert ( IpfsFile . load ( "onchain" ) == null ) ;
63
+ if ( event . params . testCommand == CREATE_CONFLICTING_ENTITY ) {
64
+ log . info ( "Creating conflicting entity" , [ ] ) ;
65
+ let entity = new FileEntity ( event . params . data ) ;
66
+ entity . content = "content" ;
67
+ entity . save ( ) ;
68
+ }
88
69
89
70
if (
90
- dataSource . stringParam ( ) != "QmVkvoPGi9jvvuxsHDVJDgzPEzagBaWSZRYoRDzU244HjZ"
71
+ event . params . testCommand ==
72
+ ACCESS_AND_UPDATE_OFFCHAIN_ENTITY_IN_ONCHAIN_HANDLER
91
73
) {
92
- // Test that an offchain data source cannot read from another offchain data source.
93
- assert (
94
- IpfsFile . load ( "QmVkvoPGi9jvvuxsHDVJDgzPEzagBaWSZRYoRDzU244HjZ" ) == null
95
- ) ;
74
+ let hash = event . params . data ;
75
+ log . info ( "Creating file data source from handleFile: {}" , [ hash ] ) ;
76
+ let entity = FileEntity . load ( event . params . data ) ;
77
+ if ( entity == null ) {
78
+ log . info ( "Entity not found" , [ ] ) ;
79
+ } else {
80
+ // This should never be logged if the entity was created in the offchain handler
81
+ // Such entities are not accessible in onchain handlers and will return null on load
82
+ log . info ( "Updating entity content" , [ ] ) ;
83
+ entity . content = "updated content" ;
84
+ entity . save ( ) ;
85
+ }
96
86
}
97
87
98
- let entity = new IpfsFile ( dataSource . stringParam ( ) ) ;
99
- entity . content = data . toString ( ) ;
100
- entity . save ( ) ;
101
-
102
- // Test that an offchain data source can load its own entities
103
- let loaded_entity = IpfsFile . load ( dataSource . stringParam ( ) ) ! ;
104
- assert ( loaded_entity . content == entity . content ) ;
105
- }
88
+ if ( event . params . testCommand == CREATE_FOO ) {
89
+ let entity = new Foo ( event . params . data ) ;
90
+ entity . save ( ) ;
91
+ let context = new DataSourceContext ( ) ;
92
+ context . setString ( "command" , CREATE_FOO ) ;
93
+ dataSource . createWithContext ( "File" , [ event . params . data ] , context ) ;
94
+ }
106
95
107
- export function handleFile1 ( data : Bytes ) : void {
108
- let entity = new IpfsFile1 ( dataSource . stringParam ( ) ) ;
109
- entity . content = data . toString ( ) ;
110
- entity . save ( ) ;
111
- }
96
+ if ( event . params . testCommand == ACCESS_FILE_ENTITY_THROUGH_DERIVED_FIELD ) {
97
+ let entity = Foo . load ( event . params . data ) ;
98
+ if ( entity == null ) {
99
+ log . info ( "Entity not found" , [ ] ) ;
100
+ } else {
101
+ log . info ( "Accessing file entity through derived field" , [ ] ) ;
102
+ let fileEntity = entity . ipfs . load ( ) ;
112
103
113
- // Used to test spawning a file data source from another file data source handler.
114
- // This function spawns a file data source that will be handled by `handleSpawnedTest`.
115
- export function spawnTestHandler ( data : Bytes ) : void {
116
- let context = new DataSourceContext ( ) ;
117
- context . setString ( "file" , "fromSpawnTestHandler" ) ;
118
- let command = dataSource . context ( ) . getString ( "command" ) ;
119
- if ( command == "spawnOffChainHandlerTest" ) {
120
- dataSource . createWithContext ( "OffChainDataSource" , [ KNOWN_CID ] , context ) ;
121
- } else if ( command == "spawnOnChainHandlerTest" ) {
122
- dataSource . createWithContext ( "OnChainDataSource" , [ KNOWN_CID ] , context ) ;
104
+ assert ( fileEntity . length == 0 , "Expected exactly one file entity" ) ;
105
+ }
123
106
}
124
107
}
125
108
126
- // This is the handler for the data source spawned by `spawnOffChainHandlerTest`.
127
- export function handleSpawnedTest ( data : Bytes ) : void {
128
- let entity = new SpawnTestEntity ( dataSource . stringParam ( ) ) ;
129
- let context = dataSource . context ( ) . getString ( "file" ) ;
130
- entity . content = data . toString ( ) ;
131
- entity . context = context ;
132
- entity . save ( ) ;
109
+ export function handleFile ( data : Bytes ) : void {
110
+ log . info ( "handleFile {}" , [ dataSource . stringParam ( ) ] ) ;
111
+ let context = dataSource . context ( ) ;
112
+
113
+ if ( context . isSet ( "command" ) ) {
114
+ let contextCommand = context . getString ( "command" ) ;
115
+
116
+ if ( contextCommand == SPAWN_FDS_FROM_OFFCHAIN_HANDLER ) {
117
+ let hash = context . getString ( "hash" ) ;
118
+ log . info ( "Creating file data source from handleFile: {}" , [ hash ] ) ;
119
+ dataSource . createWithContext ( "File" , [ hash ] , new DataSourceContext ( ) ) ;
120
+ }
121
+
122
+ if ( contextCommand == ONCHAIN_FROM_OFFCHAIN ) {
123
+ log . info ( "Creating onchain data source from offchain handler" , [ ] ) ;
124
+ let address = context . getString ( "address" ) ;
125
+ dataSource . create ( "OnChainDataSource" , [ address ] ) ;
126
+ }
127
+
128
+ if ( contextCommand == CREATE_UNDEFINED_ENTITY ) {
129
+ log . info ( "Creating undefined entity" , [ ] ) ;
130
+ let entity = new Foo ( dataSource . stringParam ( ) ) ;
131
+ entity . save ( ) ;
132
+ }
133
+
134
+ if ( contextCommand == CREATE_FOO ) {
135
+ log . info ( "Creating FileEntity with relation to Foo" , [ ] ) ;
136
+ let entity = new FileEntity ( dataSource . stringParam ( ) ) ;
137
+ entity . foo = dataSource . stringParam ( ) ;
138
+ entity . content = data . toString ( ) ;
139
+ entity . save ( ) ;
140
+ }
141
+ } else {
142
+ log . info ( "Creating FileEntity from handleFile: {} , content : {}" , [
143
+ dataSource . stringParam ( ) ,
144
+ data . toString ( ) ,
145
+ ] ) ;
146
+
147
+ let entity = new FileEntity ( dataSource . stringParam ( ) ) ;
148
+ entity . content = data . toString ( ) ;
149
+ entity . save ( ) ;
150
+ }
133
151
}
0 commit comments