Skip to content

Commit 01cc21b

Browse files
committedApr 3, 2022
fork init
1 parent fd6f3a9 commit 01cc21b

23 files changed

+7029
-100
lines changed
 

‎.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
readme.md

‎.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "graphprotocol-utils"]
2+
path = packages/graphprotocol-utils
3+
url = git@github.com:Amxx/graphprotocol-utils.git

‎build/Contract/Contract.wasm

18 KB
Binary file not shown.

‎build/Contract/abis/Contract.json

+633
Large diffs are not rendered by default.

‎build/schema.graphql

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
type Contract @entity {
2+
id: ID!
3+
asERC721: TokenRegistry
4+
}
5+
6+
type Account @entity {
7+
id: ID!
8+
tokens: [Token!]! @derivedFrom(field: "owner")
9+
transfersFrom: [Transfer!]! @derivedFrom(field: "from")
10+
transfersTo: [Transfer!]! @derivedFrom(field: "to")
11+
}
12+
13+
type TokenRegistry @entity {
14+
id: ID!
15+
supportsMetadata: Boolean
16+
name: String
17+
symbol: String
18+
tokens: [Token!]! @derivedFrom(field: "registry")
19+
}
20+
21+
type Token @entity {
22+
id: ID!
23+
registry: TokenRegistry!
24+
identifier: BigInt!
25+
owner: Account!
26+
approval: Account!
27+
uri: String
28+
transfers: [Transfer!]! @derivedFrom(field: "token")
29+
approvals: [Approval!]! @derivedFrom(field: "token")
30+
}
31+
32+
type OperatorDelegation @entity {
33+
id: ID!
34+
registry: TokenRegistry!
35+
owner: Account!
36+
operator: Account!
37+
approved: Boolean!
38+
events: [ApprovalForAll!]! @derivedFrom(field: "delegation")
39+
}
40+
41+
type Transfer implements Event @entity {
42+
id: ID!
43+
transaction: Transaction!
44+
timestamp: BigInt!
45+
token: Token!
46+
from: Account!
47+
to: Account!
48+
}
49+
50+
type Approval implements Event @entity {
51+
id: ID!
52+
transaction: Transaction!
53+
timestamp: BigInt!
54+
token: Token!
55+
owner: Account!
56+
approved: Account!
57+
}
58+
59+
type ApprovalForAll implements Event @entity {
60+
id: ID!
61+
transaction: Transaction!
62+
timestamp: BigInt!
63+
delegation: OperatorDelegation!
64+
owner: Account!
65+
operator: Account!
66+
approved: Boolean!
67+
}
68+
69+
type Transaction @entity {
70+
id: ID!
71+
timestamp: BigInt!
72+
blockNumber: BigInt!
73+
}

‎build/subgraph.yaml

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
specVersion: 0.0.2
2+
schema:
3+
file: schema.graphql
4+
dataSources:
5+
- kind: ethereum
6+
name: Contract
7+
network: mainnet
8+
source:
9+
address: "0xDb3B2e1F699CaF230eE75bfBE7d97d70F81bC945"
10+
abi: Contract
11+
mapping:
12+
kind: ethereum/events
13+
apiVersion: 0.0.5
14+
language: wasm/assemblyscript
15+
entities:
16+
- Approval
17+
- ApprovalForAll
18+
- OwnershipTransferred
19+
- Transfer
20+
abis:
21+
- name: Contract
22+
file: Contract\abis\Contract.json
23+
eventHandlers:
24+
- event: Approval(indexed address,indexed address,indexed uint256)
25+
handler: handleApproval
26+
- event: ApprovalForAll(indexed address,indexed address,bool)
27+
handler: handleApprovalForAll
28+
- event: OwnershipTransferred(indexed address,indexed address)
29+
handler: handleOwnershipTransferred
30+
- event: Transfer(indexed address,indexed address,indexed uint256)
31+
handler: handleTransfer
32+
file: Contract\Contract.wasm

‎generated/Contract/Contract.ts

+971
Large diffs are not rendered by default.

‎generated/IERC721/IERC721.ts

+389
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,389 @@
1+
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2+
3+
import {
4+
ethereum,
5+
JSONValue,
6+
TypedMap,
7+
Entity,
8+
Bytes,
9+
Address,
10+
BigInt
11+
} from "@graphprotocol/graph-ts";
12+
13+
export class Approval extends ethereum.Event {
14+
get params(): Approval__Params {
15+
return new Approval__Params(this);
16+
}
17+
}
18+
19+
export class Approval__Params {
20+
_event: Approval;
21+
22+
constructor(event: Approval) {
23+
this._event = event;
24+
}
25+
26+
get owner(): Address {
27+
return this._event.parameters[0].value.toAddress();
28+
}
29+
30+
get approved(): Address {
31+
return this._event.parameters[1].value.toAddress();
32+
}
33+
34+
get tokenId(): BigInt {
35+
return this._event.parameters[2].value.toBigInt();
36+
}
37+
}
38+
39+
export class ApprovalForAll extends ethereum.Event {
40+
get params(): ApprovalForAll__Params {
41+
return new ApprovalForAll__Params(this);
42+
}
43+
}
44+
45+
export class ApprovalForAll__Params {
46+
_event: ApprovalForAll;
47+
48+
constructor(event: ApprovalForAll) {
49+
this._event = event;
50+
}
51+
52+
get owner(): Address {
53+
return this._event.parameters[0].value.toAddress();
54+
}
55+
56+
get operator(): Address {
57+
return this._event.parameters[1].value.toAddress();
58+
}
59+
60+
get approved(): boolean {
61+
return this._event.parameters[2].value.toBoolean();
62+
}
63+
}
64+
65+
export class Transfer extends ethereum.Event {
66+
get params(): Transfer__Params {
67+
return new Transfer__Params(this);
68+
}
69+
}
70+
71+
export class Transfer__Params {
72+
_event: Transfer;
73+
74+
constructor(event: Transfer) {
75+
this._event = event;
76+
}
77+
78+
get from(): Address {
79+
return this._event.parameters[0].value.toAddress();
80+
}
81+
82+
get to(): Address {
83+
return this._event.parameters[1].value.toAddress();
84+
}
85+
86+
get tokenId(): BigInt {
87+
return this._event.parameters[2].value.toBigInt();
88+
}
89+
}
90+
91+
export class IERC721 extends ethereum.SmartContract {
92+
static bind(address: Address): IERC721 {
93+
return new IERC721("IERC721", address);
94+
}
95+
96+
balanceOf(owner: Address): BigInt {
97+
let result = super.call("balanceOf", "balanceOf(address):(uint256)", [
98+
ethereum.Value.fromAddress(owner)
99+
]);
100+
101+
return result[0].toBigInt();
102+
}
103+
104+
try_balanceOf(owner: Address): ethereum.CallResult<BigInt> {
105+
let result = super.tryCall("balanceOf", "balanceOf(address):(uint256)", [
106+
ethereum.Value.fromAddress(owner)
107+
]);
108+
if (result.reverted) {
109+
return new ethereum.CallResult();
110+
}
111+
let value = result.value;
112+
return ethereum.CallResult.fromValue(value[0].toBigInt());
113+
}
114+
115+
getApproved(tokenId: BigInt): Address {
116+
let result = super.call("getApproved", "getApproved(uint256):(address)", [
117+
ethereum.Value.fromUnsignedBigInt(tokenId)
118+
]);
119+
120+
return result[0].toAddress();
121+
}
122+
123+
try_getApproved(tokenId: BigInt): ethereum.CallResult<Address> {
124+
let result = super.tryCall(
125+
"getApproved",
126+
"getApproved(uint256):(address)",
127+
[ethereum.Value.fromUnsignedBigInt(tokenId)]
128+
);
129+
if (result.reverted) {
130+
return new ethereum.CallResult();
131+
}
132+
let value = result.value;
133+
return ethereum.CallResult.fromValue(value[0].toAddress());
134+
}
135+
136+
isApprovedForAll(owner: Address, operator: Address): boolean {
137+
let result = super.call(
138+
"isApprovedForAll",
139+
"isApprovedForAll(address,address):(bool)",
140+
[ethereum.Value.fromAddress(owner), ethereum.Value.fromAddress(operator)]
141+
);
142+
143+
return result[0].toBoolean();
144+
}
145+
146+
try_isApprovedForAll(
147+
owner: Address,
148+
operator: Address
149+
): ethereum.CallResult<boolean> {
150+
let result = super.tryCall(
151+
"isApprovedForAll",
152+
"isApprovedForAll(address,address):(bool)",
153+
[ethereum.Value.fromAddress(owner), ethereum.Value.fromAddress(operator)]
154+
);
155+
if (result.reverted) {
156+
return new ethereum.CallResult();
157+
}
158+
let value = result.value;
159+
return ethereum.CallResult.fromValue(value[0].toBoolean());
160+
}
161+
162+
ownerOf(tokenId: BigInt): Address {
163+
let result = super.call("ownerOf", "ownerOf(uint256):(address)", [
164+
ethereum.Value.fromUnsignedBigInt(tokenId)
165+
]);
166+
167+
return result[0].toAddress();
168+
}
169+
170+
try_ownerOf(tokenId: BigInt): ethereum.CallResult<Address> {
171+
let result = super.tryCall("ownerOf", "ownerOf(uint256):(address)", [
172+
ethereum.Value.fromUnsignedBigInt(tokenId)
173+
]);
174+
if (result.reverted) {
175+
return new ethereum.CallResult();
176+
}
177+
let value = result.value;
178+
return ethereum.CallResult.fromValue(value[0].toAddress());
179+
}
180+
181+
supportsInterface(interfaceId: Bytes): boolean {
182+
let result = super.call(
183+
"supportsInterface",
184+
"supportsInterface(bytes4):(bool)",
185+
[ethereum.Value.fromFixedBytes(interfaceId)]
186+
);
187+
188+
return result[0].toBoolean();
189+
}
190+
191+
try_supportsInterface(interfaceId: Bytes): ethereum.CallResult<boolean> {
192+
let result = super.tryCall(
193+
"supportsInterface",
194+
"supportsInterface(bytes4):(bool)",
195+
[ethereum.Value.fromFixedBytes(interfaceId)]
196+
);
197+
if (result.reverted) {
198+
return new ethereum.CallResult();
199+
}
200+
let value = result.value;
201+
return ethereum.CallResult.fromValue(value[0].toBoolean());
202+
}
203+
}
204+
205+
export class ApproveCall extends ethereum.Call {
206+
get inputs(): ApproveCall__Inputs {
207+
return new ApproveCall__Inputs(this);
208+
}
209+
210+
get outputs(): ApproveCall__Outputs {
211+
return new ApproveCall__Outputs(this);
212+
}
213+
}
214+
215+
export class ApproveCall__Inputs {
216+
_call: ApproveCall;
217+
218+
constructor(call: ApproveCall) {
219+
this._call = call;
220+
}
221+
222+
get to(): Address {
223+
return this._call.inputValues[0].value.toAddress();
224+
}
225+
226+
get tokenId(): BigInt {
227+
return this._call.inputValues[1].value.toBigInt();
228+
}
229+
}
230+
231+
export class ApproveCall__Outputs {
232+
_call: ApproveCall;
233+
234+
constructor(call: ApproveCall) {
235+
this._call = call;
236+
}
237+
}
238+
239+
export class SafeTransferFromCall extends ethereum.Call {
240+
get inputs(): SafeTransferFromCall__Inputs {
241+
return new SafeTransferFromCall__Inputs(this);
242+
}
243+
244+
get outputs(): SafeTransferFromCall__Outputs {
245+
return new SafeTransferFromCall__Outputs(this);
246+
}
247+
}
248+
249+
export class SafeTransferFromCall__Inputs {
250+
_call: SafeTransferFromCall;
251+
252+
constructor(call: SafeTransferFromCall) {
253+
this._call = call;
254+
}
255+
256+
get from(): Address {
257+
return this._call.inputValues[0].value.toAddress();
258+
}
259+
260+
get to(): Address {
261+
return this._call.inputValues[1].value.toAddress();
262+
}
263+
264+
get tokenId(): BigInt {
265+
return this._call.inputValues[2].value.toBigInt();
266+
}
267+
}
268+
269+
export class SafeTransferFromCall__Outputs {
270+
_call: SafeTransferFromCall;
271+
272+
constructor(call: SafeTransferFromCall) {
273+
this._call = call;
274+
}
275+
}
276+
277+
export class SafeTransferFrom1Call extends ethereum.Call {
278+
get inputs(): SafeTransferFrom1Call__Inputs {
279+
return new SafeTransferFrom1Call__Inputs(this);
280+
}
281+
282+
get outputs(): SafeTransferFrom1Call__Outputs {
283+
return new SafeTransferFrom1Call__Outputs(this);
284+
}
285+
}
286+
287+
export class SafeTransferFrom1Call__Inputs {
288+
_call: SafeTransferFrom1Call;
289+
290+
constructor(call: SafeTransferFrom1Call) {
291+
this._call = call;
292+
}
293+
294+
get from(): Address {
295+
return this._call.inputValues[0].value.toAddress();
296+
}
297+
298+
get to(): Address {
299+
return this._call.inputValues[1].value.toAddress();
300+
}
301+
302+
get tokenId(): BigInt {
303+
return this._call.inputValues[2].value.toBigInt();
304+
}
305+
306+
get data(): Bytes {
307+
return this._call.inputValues[3].value.toBytes();
308+
}
309+
}
310+
311+
export class SafeTransferFrom1Call__Outputs {
312+
_call: SafeTransferFrom1Call;
313+
314+
constructor(call: SafeTransferFrom1Call) {
315+
this._call = call;
316+
}
317+
}
318+
319+
export class SetApprovalForAllCall extends ethereum.Call {
320+
get inputs(): SetApprovalForAllCall__Inputs {
321+
return new SetApprovalForAllCall__Inputs(this);
322+
}
323+
324+
get outputs(): SetApprovalForAllCall__Outputs {
325+
return new SetApprovalForAllCall__Outputs(this);
326+
}
327+
}
328+
329+
export class SetApprovalForAllCall__Inputs {
330+
_call: SetApprovalForAllCall;
331+
332+
constructor(call: SetApprovalForAllCall) {
333+
this._call = call;
334+
}
335+
336+
get operator(): Address {
337+
return this._call.inputValues[0].value.toAddress();
338+
}
339+
340+
get _approved(): boolean {
341+
return this._call.inputValues[1].value.toBoolean();
342+
}
343+
}
344+
345+
export class SetApprovalForAllCall__Outputs {
346+
_call: SetApprovalForAllCall;
347+
348+
constructor(call: SetApprovalForAllCall) {
349+
this._call = call;
350+
}
351+
}
352+
353+
export class TransferFromCall extends ethereum.Call {
354+
get inputs(): TransferFromCall__Inputs {
355+
return new TransferFromCall__Inputs(this);
356+
}
357+
358+
get outputs(): TransferFromCall__Outputs {
359+
return new TransferFromCall__Outputs(this);
360+
}
361+
}
362+
363+
export class TransferFromCall__Inputs {
364+
_call: TransferFromCall;
365+
366+
constructor(call: TransferFromCall) {
367+
this._call = call;
368+
}
369+
370+
get from(): Address {
371+
return this._call.inputValues[0].value.toAddress();
372+
}
373+
374+
get to(): Address {
375+
return this._call.inputValues[1].value.toAddress();
376+
}
377+
378+
get tokenId(): BigInt {
379+
return this._call.inputValues[2].value.toBigInt();
380+
}
381+
}
382+
383+
export class TransferFromCall__Outputs {
384+
_call: TransferFromCall;
385+
386+
constructor(call: TransferFromCall) {
387+
this._call = call;
388+
}
389+
}

‎generated/IERC721/IERC721Metadata.ts

+438
Large diffs are not rendered by default.

‎generated/constants.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { BigDecimal, BigInt } from '@graphprotocol/graph-ts'
2+
3+
export namespace constants {
4+
export let BIGINT_ZERO = BigInt.fromI32(0)
5+
export let BIGINT_ONE = BigInt.fromI32(1)
6+
export let BIGDECIMAL_ZERO = new BigDecimal(constants.BIGINT_ZERO)
7+
export let BIGDECIMAL_ONE = new BigDecimal(constants.BIGINT_ONE)
8+
export const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000'
9+
export const BYTES32_ZERO = '0x0000000000000000000000000000000000000000000000000000000000000000'
10+
}

‎generated/schema.graphql

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
type Contract @entity {
2+
id: ID!
3+
asERC721: TokenRegistry
4+
}
5+
6+
type Account @entity {
7+
id: ID!
8+
tokens: [Token!]! @derivedFrom(field: "owner")
9+
transfersFrom: [Transfer!]! @derivedFrom(field: "from")
10+
transfersTo: [Transfer!]! @derivedFrom(field: "to")
11+
}
12+
13+
type TokenRegistry @entity {
14+
id: ID!
15+
supportsMetadata: Boolean
16+
name: String
17+
symbol: String
18+
tokens: [Token!]! @derivedFrom(field: "registry")
19+
}
20+
21+
type Token @entity {
22+
id: ID!
23+
registry: TokenRegistry!
24+
identifier: BigInt!
25+
owner: Account!
26+
approval: Account!
27+
uri: String
28+
transfers: [Transfer!]! @derivedFrom(field: "token")
29+
approvals: [Approval!]! @derivedFrom(field: "token")
30+
}
31+
32+
type OperatorDelegation @entity {
33+
id: ID!
34+
registry: TokenRegistry!
35+
owner: Account!
36+
operator: Account!
37+
approved: Boolean!
38+
events: [ApprovalForAll!]! @derivedFrom(field: "delegation")
39+
}
40+
41+
type Transfer implements Event @entity {
42+
id: ID!
43+
transaction: Transaction!
44+
timestamp: BigInt!
45+
token: Token!
46+
from: Account!
47+
to: Account!
48+
}
49+
50+
type Approval implements Event @entity {
51+
id: ID!
52+
transaction: Transaction!
53+
timestamp: BigInt!
54+
token: Token!
55+
owner: Account!
56+
approved: Account!
57+
}
58+
59+
type ApprovalForAll implements Event @entity {
60+
id: ID!
61+
transaction: Transaction!
62+
timestamp: BigInt!
63+
delegation: OperatorDelegation!
64+
owner: Account!
65+
operator: Account!
66+
approved: Boolean!
67+
}
68+
69+
type Transaction @entity {
70+
id: ID!
71+
timestamp: BigInt!
72+
blockNumber: BigInt!
73+
}

‎generated/schema.ts

+719
Large diffs are not rendered by default.

‎package-lock.json

+3,419
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
},
1212
"dependencies": {
1313
"@graphprotocol/graph-cli": "0.25.0",
14-
"@graphprotocol/graph-ts": "0.24.1"
14+
"@graphprotocol/graph-ts": "0.24.1",
15+
"@openzeppelin/contracts": "^4.5.0"
1516
}
1617
}

‎schema.graphql

+72-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,73 @@
1-
type ExampleEntity @entity {
2-
id: ID!
3-
count: BigInt!
4-
owner: Bytes! # address
5-
approved: Bytes! # address
1+
type Contract @entity {
2+
id: ID!
3+
asERC721: TokenRegistry
64
}
5+
6+
type Account @entity {
7+
id: ID!
8+
tokens: [Token!]! @derivedFrom(field: "owner")
9+
transfersFrom: [Transfer!]! @derivedFrom(field: "from")
10+
transfersTo: [Transfer!]! @derivedFrom(field: "to")
11+
}
12+
13+
type TokenRegistry @entity {
14+
id: ID!
15+
supportsMetadata: Boolean
16+
name: String
17+
symbol: String
18+
tokens: [Token!]! @derivedFrom(field: "registry")
19+
}
20+
21+
type Token @entity {
22+
id: ID!
23+
registry: TokenRegistry!
24+
identifier: BigInt!
25+
owner: Account!
26+
approval: Account!
27+
uri: String
28+
transfers: [Transfer!]! @derivedFrom(field: "token")
29+
approvals: [Approval!]! @derivedFrom(field: "token")
30+
}
31+
32+
type OperatorDelegation @entity {
33+
id: ID!
34+
registry: TokenRegistry!
35+
owner: Account!
36+
operator: Account!
37+
approved: Boolean!
38+
events: [ApprovalForAll!]! @derivedFrom(field: "delegation")
39+
}
40+
41+
type Transfer implements Event @entity {
42+
id: ID!
43+
transaction: Transaction!
44+
timestamp: BigInt!
45+
token: Token!
46+
from: Account!
47+
to: Account!
48+
}
49+
50+
type Approval implements Event @entity {
51+
id: ID!
52+
transaction: Transaction!
53+
timestamp: BigInt!
54+
token: Token!
55+
owner: Account!
56+
approved: Account!
57+
}
58+
59+
type ApprovalForAll implements Event @entity {
60+
id: ID!
61+
transaction: Transaction!
62+
timestamp: BigInt!
63+
delegation: OperatorDelegation!
64+
owner: Account!
65+
operator: Account!
66+
approved: Boolean!
67+
}
68+
69+
type Transaction @entity {
70+
id: ID!
71+
timestamp: BigInt!
72+
blockNumber: BigInt!
73+
}

‎src/eip721/index.ts

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {
2+
Account,
3+
Transfer,
4+
} from '../../generated/schema'
5+
6+
import {
7+
Transfer as TransferEvent,
8+
} from '../../generated/IERC721/IERC721'
9+
10+
import {
11+
fetchRegistry,
12+
fetchToken,
13+
} from '../utils/erc721'
14+
15+
import {
16+
events,
17+
transactions,
18+
} from '../../src/graphprotocol-utils'
19+
20+
export function handleTransfer(event: TransferEvent): void {
21+
let registry = fetchRegistry(event.address)
22+
if (registry != null)
23+
{
24+
let token = fetchToken(registry, event.params.tokenId)
25+
let from = new Account(event.params.from.toHex())
26+
let to = new Account(event.params.to.toHex())
27+
28+
token.owner = to.id
29+
30+
registry.save()
31+
token.save()
32+
from.save()
33+
to.save()
34+
35+
let ev = new Transfer(events.id(event))
36+
ev.transaction = transactions.log(event).id
37+
ev.timestamp = event.block.timestamp
38+
ev.token = token.id
39+
ev.from = from.id
40+
ev.to = to.id
41+
ev.save()
42+
}
43+
}

‎src/graphprotocol-utils.ts

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import {
2+
ethereum,
3+
} from '../node_modules/@graphprotocol/graph-ts'
4+
5+
export namespace events {
6+
export function id(event: ethereum.Event): string {
7+
return event.block.number.toString().concat('-').concat(event.logIndex.toString())
8+
}
9+
}
10+
11+
import { BigDecimal, BigInt } from '@graphprotocol/graph-ts'
12+
13+
export namespace constants {
14+
export let BIGINT_ZERO = BigInt.fromI32(0)
15+
export let BIGINT_ONE = BigInt.fromI32(1)
16+
export let BIGDECIMAL_ZERO = new BigDecimal(constants.BIGINT_ZERO)
17+
export let BIGDECIMAL_ONE = new BigDecimal(constants.BIGINT_ONE)
18+
export const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000'
19+
export const BYTES32_ZERO = '0x0000000000000000000000000000000000000000000000000000000000000000'
20+
}
21+
22+
import {
23+
Transaction,
24+
} from '../generated/schema'
25+
26+
export namespace transactions {
27+
export function log(event: ethereum.Event): Transaction {
28+
let tx = new Transaction(event.transaction.hash.toHex())
29+
tx.timestamp = event.block.timestamp
30+
tx.blockNumber = event.block.number
31+
tx.save()
32+
return tx as Transaction
33+
}
34+
export type Tx = Transaction
35+
}

‎src/mapping.ts

-74
This file was deleted.

‎src/utils/erc165.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ethereum, Bytes } from '@graphprotocol/graph-ts'
2+
3+
export function supportsInterface(contract: ethereum.SmartContract, interfaceId: string, expected: boolean = true): boolean {
4+
let result = ethereum.call(new ethereum.SmartContractCall(
5+
contract._name, // '',
6+
contract._address, // address,
7+
'supportsInterface', // '',
8+
'supportsInterface(bytes4):(bool)',
9+
[ethereum.Value.fromFixedBytes(Bytes.fromHexString(interfaceId) as Bytes)]
10+
))
11+
return result != null && (result as Array<ethereum.Value>)[0].toBoolean() == expected
12+
}

‎src/utils/erc721.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './erc721FetchRegistry'
2+
export * from './erc721FetchToken'

‎src/utils/erc721FetchRegistry.ts

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import {
2+
Address,
3+
} from '@graphprotocol/graph-ts'
4+
5+
import {
6+
Contract,
7+
TokenRegistry,
8+
} from '../../generated/schema'
9+
10+
import {
11+
IERC721Metadata,
12+
} from '../../generated/IERC721/IERC721Metadata'
13+
14+
import {
15+
supportsInterface,
16+
} from './erc165'
17+
18+
export function fetchRegistry(address: Address): TokenRegistry {
19+
let erc721 = IERC721Metadata.bind(address)
20+
let contract = Contract.load(address.toHex())
21+
22+
if (contract == null) {
23+
contract = new Contract(address.toHex())
24+
let introspection_01ffc9a7 = supportsInterface(erc721, '01ffc9a7') // ERC165
25+
let introspection_80ac58cd = supportsInterface(erc721, '80ac58cd') // ERC721
26+
let introspection_00000000 = supportsInterface(erc721, '00000000', false)
27+
let isERC721 = introspection_01ffc9a7 && introspection_80ac58cd && introspection_00000000
28+
contract.asERC721 = isERC721 ? contract.id : null
29+
contract.save()
30+
}
31+
32+
if (contract.asERC721 != null)
33+
{
34+
let registry = TokenRegistry.load(contract.id)
35+
if (registry == null) {
36+
registry = new TokenRegistry(contract.id)
37+
let try_name = erc721.try_name()
38+
let try_symbol = erc721.try_symbol()
39+
registry.name = try_name.reverted ? '' : try_name.value
40+
registry.symbol = try_symbol.reverted ? '' : try_symbol.value
41+
registry.supportsMetadata = supportsInterface(erc721, '5b5e139f') // ERC721Metadata
42+
}
43+
return registry as TokenRegistry
44+
}
45+
46+
return null as TokenRegistry
47+
}

‎src/utils/erc721FetchToken.ts

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {
2+
Address,
3+
BigInt,
4+
} from '@graphprotocol/graph-ts'
5+
6+
import {
7+
Account,
8+
TokenRegistry,
9+
Token,
10+
} from '../../generated/schema'
11+
12+
import {
13+
IERC721Metadata,
14+
} from '../../generated/IERC721/IERC721Metadata'
15+
16+
import {
17+
constants,
18+
} from '../../src/graphprotocol-utils'
19+
20+
export function fetchToken(registry: TokenRegistry, id: BigInt): Token {
21+
let tokenid = registry.id.concat('-').concat(id.toHex())
22+
let token = Token.load(tokenid)
23+
if (token == null) {
24+
let account_zero = new Account(constants.ADDRESS_ZERO)
25+
account_zero.save()
26+
27+
token = new Token(tokenid)
28+
token.registry = registry.id
29+
token.identifier = id
30+
token.approval = account_zero.id
31+
32+
if (registry.supportsMetadata) {
33+
let erc721 = IERC721Metadata.bind(Address.fromString(registry.id))
34+
let try_tokenURI = erc721.try_tokenURI(id)
35+
token.uri = try_tokenURI.reverted ? '' : try_tokenURI.value
36+
}
37+
}
38+
return token as Token
39+
}

‎subgraph.yaml

+15-20
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,27 @@
1-
specVersion: 0.0.1
1+
specVersion: 0.0.2
2+
description: eip721
3+
repository: https://github.com/amxx/subgraphs
24
schema:
3-
file: ./schema.graphql
5+
file: ./generated/schema.graphql
46
dataSources:
5-
- kind: ethereum
6-
name: Contract
7+
- kind: ethereum/contract
8+
name: IERC721
79
network: mainnet
810
source:
9-
address: "0xDb3B2e1F699CaF230eE75bfBE7d97d70F81bC945"
10-
abi: Contract
11+
abi: IERC721
12+
startBlock: 5806610
1113
mapping:
1214
kind: ethereum/events
13-
apiVersion: 0.0.5
15+
apiVersion: 0.0.6
1416
language: wasm/assemblyscript
1517
entities:
16-
- Approval
17-
- ApprovalForAll
18-
- OwnershipTransferred
19-
- Transfer
18+
- Token
2019
abis:
21-
- name: Contract
22-
file: ./abis/Contract.json
20+
- name: IERC721
21+
file: ./node_modules/@openzeppelin/contracts/build/contracts/IERC721.json
22+
- name: IERC721Metadata
23+
file: ./node_modules/@openzeppelin/contracts/build/contracts/IERC721Metadata.json
2324
eventHandlers:
24-
- event: Approval(indexed address,indexed address,indexed uint256)
25-
handler: handleApproval
26-
- event: ApprovalForAll(indexed address,indexed address,bool)
27-
handler: handleApprovalForAll
28-
- event: OwnershipTransferred(indexed address,indexed address)
29-
handler: handleOwnershipTransferred
3025
- event: Transfer(indexed address,indexed address,indexed uint256)
3126
handler: handleTransfer
32-
file: ./src/mapping.ts
27+
file: ./src/eip721/index.ts

0 commit comments

Comments
 (0)
Please sign in to comment.