-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathschema.graphql
687 lines (581 loc) · 23.8 KB
/
schema.graphql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
# noinspection GraphQLMissingType
########################
## Time series events ##
########################
# Generic activity stream events for history of actions including primary and secondary sales actions & triggers
# Used for listing out token history on the token pages
type TokenEvent @entity(immutable: true) {
id: ID! # Composite key made form multiple items
version: BigInt! # KODA 2 or 3
name: String!
token: Token!
edition: Edition!
buyer: Collector
bidder: Collector
currentOwner: Collector
ethValue: BigDecimal!
# Common event details
timestamp: BigInt!
transactionHash: Bytes!
transactionIndex: BigInt!
logIndex: BigInt!
eventAddress: Bytes!
eventTxFrom: Bytes!
eventTxTo: Bytes
blockNumber: BigInt!
}
# Token events for transfers
type TransferEvent @entity(immutable: true) {
id: ID!
version: BigInt! # KODA 2 or 3
from: Bytes! # address
to: Bytes! # address
tokenId: BigInt!
edition: Edition!
# Common event details
timestamp: BigInt!
transactionHash: Bytes!
transactionIndex: BigInt!
logIndex: BigInt!
eventAddress: Bytes!
eventTxFrom: Bytes!
eventTxTo: Bytes
blockNumber: BigInt!
}
# Edition primary sale auction events
type AuctionEvent @entity(immutable: true) {
id: ID!
version: BigInt! # KODA 2 or 3
edition: Edition!
name: String!
bidder: Bytes!
caller: Bytes!
ethValue: BigDecimal!
lockupUntil: BigInt # when set the bidder who set this is locked out
# Common event details
timestamp: BigInt!
transactionHash: Bytes!
transactionIndex: BigInt!
logIndex: BigInt!
eventAddress: Bytes!
eventTxFrom: Bytes!
eventTxTo: Bytes
blockNumber: BigInt!
}
# Common unified event stream spanning KODA versions and various types
type ActivityEvent @entity(immutable: true) {
id: ID!
type: String! # Token, Edition or Creator Contract
version: BigInt! # KODA 2 or 3
eventType: String! # Event types e.g. ['EditionCreated', 'Purchase', 'BidPlaced', 'BidAccepted', 'BidIncreased', 'BidRejected', 'BidWithdrawn']
edition: Edition # All events relate to an edition unless it's v3
token: Token # (nullable) the token this relates to
# accounts
creator: Bytes! # the original edition creator
creatorCommission: BigInt # % received as creator - only valid is event has value
collaborator: Bytes # (nullable) the original edition creator collaborator
collaboratorCommission: BigInt # (nullable) % received as creator - only valid is event has value
triggeredBy: Bytes # who fired the transaction
buyer: Bytes # (nullable) the buyer
seller: Bytes # (nullable) the seller
stakeholderAddresses: [Bytes!]! # the addresses that interacted during the event
contractAddress: Bytes # the address of the contract
# technicals
eventValueInWei: BigInt # (nullable) the WEI value
# Common event details
timestamp: BigInt!
transactionHash: Bytes!
transactionIndex: BigInt!
logIndex: BigInt!
eventAddress: Bytes!
eventTxFrom: Bytes!
eventTxTo: Bytes
blockNumber: BigInt!
}
#######################
## Free-text schemas ##
#######################
type _Schema_
@fulltext(
name: "listedTokenSearch",
language: en
algorithm: rank,
include: [
{
entity: "ListedToken",
fields: [
{ name: "metadataName" },
{ name: "metadataArtist" },
{ name: "metadataArtistAccount" },
{ name: "metadataTagString" },
{ name: "primaryAssetShortType" },
{ name: "primaryAssetActualType" },
]
}
]
)
@fulltext(
name: "editionSearch",
language: en
algorithm: rank,
include: [
{
entity: "Edition",
fields: [
{ name: "metadataName" },
{ name: "metadataArtist" },
{ name: "metadataArtistAccount" },
{ name: "metadataTagString" },
{ name: "metadataFormat" },
{ name: "metadataTheme" },
{ name: "primaryAssetShortType" },
{ name: "primaryAssetActualType" },
]
}
]
)
####################################################################################
## Main entities ##
## All entities below are NOT event based but are updated from a stream of events ##
####################################################################################
# Rolled up counts for a given day
type Day @entity {
id: ID!
date: String!
transferCount: BigInt!
editionsCount: BigInt!
# Bid/offer counts and values (primary & secondary)
bidsAcceptedCount: BigInt! # Offers accepted
bidsPlacedCount: BigInt! # Offers made
bidsRejectedCount: BigInt! # Offers reject
bidsWithdrawnCount: BigInt!
bidsIncreasedCount: BigInt!
totalValuePlaceInBids: BigDecimal!
totalValueCycledInBids: BigDecimal!
# Secondary sales value in ETH today
secondarySalesValue: BigDecimal!
# Sales/gifting counts and values
issuedCount: BigInt!
salesCount: BigInt!
totalValueInEth: BigDecimal!
highestValueInEth: BigDecimal!
highestValueToken: Token
issued: [Token!]!
editions: [Edition!]!
}
# N.B: Only for V3 atm
type PlatformConfig @entity {
id: ID!
# NFT
royaltiesRegistry: Bytes # address
tokenUriResolver: Bytes # address
# Marketplace
modulo: BigInt
primarySaleCommission: BigInt
secondarySaleRoyalty: BigInt
marketplaceSecondarySaleRoyalty: BigInt
minBidAmount: BigInt
# Minting factory
mintingPeriod: BigInt # Minting allowance period
maxMintsInPeriod: BigInt # Limit of mints with in the period
# Access controls
merkleProofRoot: Bytes
merkleProofIpfsHash: String
}
# A token and its details
type Token @entity {
id: ID!
version: BigInt! # KODA 2, 3 or 4
salesType: BigInt! # The current sales mechanic being used on this edition
tokenId: BigInt!
transferCount: BigInt!
editionNumber: String! # Composite ID from edition ID and optional contract address for CC
edition: Edition!
tokenURI: String!
metadata: MetaData
birthTimestamp: BigInt! # initial transfer from zero address
primaryValueInEth: BigDecimal! # when it sold from an edition on KO
totalPurchaseValue: BigDecimal! # tally of all purchases (primary & secondary)
totalPurchaseCount: BigInt! # tally of the number of purchases (primary & secondary)
largestSecondaryValueInEth: BigDecimal! # largest secondary sale in ETH
largestSalePriceEth: BigDecimal! # set to the highest sale price for the token, primary or secondary
lastSalePriceInEth: BigDecimal! # known last sale if we capture it (primary & secondary)
lastTransferTimestamp: BigInt! # updated on ever Transfer
currentOwner: Collector # the current owner - also has a derived field linking to this from Collector.tokens
allOwners: [Collector!]! # list (set) of all unique owners
transfers: [TransferEvent!]! # total number of token transfers made
tokenEvents: [TokenEvent!]! # list of token events such as secondary sales and transfers
openOffer: TokenOffer, # current top active offer on a token
currentTopBidder: Bytes # current active top bidder on the secondary market for this token
artistAccount: Bytes! # address
editionActive: Boolean!
revokedApproval: Boolean! # set to true once if the seller has revoked approved the marketplace
## Token secondary market
isListed: Boolean!
listPrice: BigDecimal
lister: Collector
listingTimestamp: BigInt
# Complete attached token
listing: ListedToken
creatorContract: CreatorContract # Optionally capture creator contract address if it is version 4
}
# For Token Secondary market (KODA V2/3 only)
type ListedToken @entity {
id: ID!
version: BigInt! # KODA 2 or 3
editionNumber: String!
revokedApproval: Boolean! # set to true once if the seller has revoked approved the marketplace
listPrice: BigDecimal!
lister: Collector!
listingTimestamp: BigInt!
seriesNumber: BigInt # i.e. edition no. in the series i.e. #10 from the an edition of 10
isFirstEdition: Boolean # i.e. token number 1 from edition of 10
isLastEdition: Boolean # i.e. token number 10 from edition of 10
isGenesisEdition: Boolean # i.e. the first artwork from an artist
#metadata fields flattened for search
metadataName: String!
metadataArtist: String!
metadataArtistAccount: String!
metadataTagString: String!
primaryAssetShortType: String!
primaryAssetActualType: String!
# Complete attached token
fullToken: Token!
# ---- Reserve auction fields --------- #
reserveAuctionSeller: Bytes! # edition seller
reserveAuctionBidder: Bytes! # current bidder
reservePrice: BigInt! # listed reserve price
reserveAuctionBid: BigInt! # current bid
reserveAuctionStartDate: BigInt! # auction start
previousReserveAuctionEndTimestamp: BigInt! # set to the same as reserve unless an extension is in flight
reserveAuctionEndTimestamp: BigInt! # when the auction will end
reserveAuctionNumTimesExtended: BigInt! # number of times auction has been extended
isReserveAuctionInSuddenDeath: Boolean! # set to true when in sudden death
reserveAuctionTotalExtensionLengthInSeconds: BigInt! # total extension
isReserveAuctionResulted: Boolean!
isReserveAuctionResultedDateTime: BigInt!
reserveAuctionResulter: Bytes!
reserveAuctionCanEmergencyExit: Boolean!
# ----- End of reserve auction fields - #
creatorContract: CreatorContract # Optionally capture creator contract address if this is version 4
}
# A composable is a combination of a V3 NFT and a set number of tokens
type Composable @entity {
id: ID! # toString for address
items: [ComposableItem!] # An array of composable items
}
# ComposableItem represents one token attached to a composable
type ComposableItem @entity {
id: ID! # ID made up of combined tokenID/composing contract/composing IDs
address: String! # Address of the ERC20/ERC721 token
tokenID: String! # ID of the token
type: String! # Type of token, ERC20, ERC721 etc
value: BigInt! # Number of tokens attached or the ERC721 token ID
}
# Maintain an list of approved collective handlers i.e. contracts which are cloned and used
type CollectiveHandlers @entity {
id: ID! # base address
active: Boolean!
lastUpdatedTimestamp: BigInt!
lastUpdatedTransactionHash: Bytes!
}
type Collective @entity {
id: ID! # deployed address
baseHandler: Bytes! # clone which this is based on
creator: Bytes! # who deployed it
recipients: [Bytes!]! # recipients for the deployed collab
splits: [BigInt!]! # splits for the deployed collab
createdTimestamp: BigInt!
transactionHash: Bytes!
editions: [Edition!]! # A list of editions assigned to
isDeployed: Boolean!
}
# A token/editions and its meta data
type Edition @entity {
id: ID! # Composite ID from edition ID and optional contract address for CC
version: BigInt! # KODA 2 or 3 or 4
editionNmber: String! # edition no. not composite key
editionType: BigInt! # legacy field from KODA V2
editionData: Bytes # bytes32 - legacy field from KODA V2 - some additional data about the edition
creatorContract: CreatorContract # address of creator contract that minted the edition if version 4
salesType: BigInt! # The current sales mechanic being used on this edition
revokedApproval: Boolean! # set to true once if the seller has revoked approved the marketplace
createdTimestamp: BigInt!
tokenIds: [String!]!
tokens: [Token!]! @derivedFrom(field: "edition")
tokenURI: String!
artistAccount: Bytes! # address
artistCommission: BigInt! # base artists commission
optionalCommissionAccount: Bytes # address - NOTE: deprecated - V2 only - use collaborators for
optionalCommissionRate: BigInt
collaborators: [Bytes!]! # list of addresses who have collaborated on this edition
collective: Collective # nullable V3 collective i.e. its split funds
offersOnly: Boolean!
# Token counters
totalSupply: BigInt! # Total purchases or mints i.e. total number of primary transfers
totalAvailable: BigInt! # Total number available to be purchased i.e. edition size
remainingSupply: BigInt! # Total remaining i.e. number of primary sale tokens left to buy from this edition
totalSold: BigInt! # sold = purchase/bid accepted with price > 0
totalBurnt: BigInt! # number of items send to 0xDead or 0x0 (only applicable for V3)
originalEditionSize: BigInt! # original edition size of the edition at mint - this field should NEVER change once set
secondaryRoyaltyV4EditionOverride: BigInt # At the edition level, the EIP2981 percentage requested by the creator(s)
sales: [Token!]!
totalEthSpentOnEdition: BigDecimal!,
active: Boolean!
metadata: MetaData
isGenesisEdition: Boolean! # set true if edition is an artists first edition
isEnhancedEdition: Boolean! # set true if any of the tokens are enhanced i.e. composed
isOpenEdition: Boolean # applicable to version 4 and editions where the artist does not mint all of the tokens up front
hasCoverImage: Boolean! # set to true if non-image asset with cover image
# Reference to the primary minter
artist: Artist
# date when the edition goes on sale
startDate: BigInt!
endDate: BigInt! # date when the edition is available until (only applicable for V2)
# ---- Reserve auction fields --------- #
reserveAuctionSeller: Bytes! # edition seller
reserveAuctionBidder: Bytes! # current bidder
reservePrice: BigInt! # listed reserve price
reserveAuctionBid: BigInt! # current bid
reserveAuctionStartDate: BigInt! # auction start
previousReserveAuctionEndTimestamp: BigInt! # set to the same as reserve unless an extension is in flight
reserveAuctionEndTimestamp: BigInt! # when the auction will end
reserveAuctionNumTimesExtended: BigInt! # number of times auction has been extended
isReserveAuctionInSuddenDeath: Boolean! # set to true when in sudden death
reserveAuctionTotalExtensionLengthInSeconds: BigInt! # total extension
isReserveAuctionResulted: Boolean!
isReserveAuctionResultedDateTime: BigInt!
reserveAuctionResulter: Bytes!
reserveAuctionCanEmergencyExit: Boolean!
# ----- End of reserve auction fields - #
# ----- Buy now price / current step price - #
priceInWei: BigInt!
# ----- Buy now price / current step price - #
# ----- step sale - #
stepSaleBasePrice: BigInt!
stepSaleStepPrice: BigInt!
currentStep: BigInt!
# ----- step sale - #
# ----- Offers logic - #
auctionEnabled: Boolean!
activeBid: AuctionEvent # if present, an active bid should be open
# ----- Offers logic - #
# ----- Gated sale config - #
gatedSale: GatedSale # the linked gated sale
# ----- Gated sale config - #
# Events and histories
biddingHistory: [AuctionEvent!]!
transfers: [TransferEvent!]! # total number of token transfers made for all tokens from the edition
allOwners: [Collector!]! # list (set) of all unique owners for all tokens
currentOwners: [Collector!]! # Current set of owners for this edition
primaryOwners: [Collector!]! # Owners (set) when sold in primary sale
# START: freetext search fields
metadataName: String!
metadataArtist: String!
metadataTagString: String!
metadataArtistAccount: String!
metadataPrice: BigInt! # A consolidated price for all sale types, making it orderable in lists
metadataFormat: String # null-able as V3 only
metadataTheme: String # null-able as V3 only
primaryAssetShortType: String # null-able leading mime-type field i.e. image or video etc
primaryAssetActualType: String # null-able ending mime-type field e.g. mp4, gif, png etc
# END: freetext search fields
}
# A token/editions and its meta data
type MetaData @entity(immutable: true) {
id: ID!
name: String
description: String
image: String
# only added july-2020
image_type: String
image_size_in_bytes: BigInt
# optional - only added july-2020
cover_image: String
cover_image_type: String
cover_image_size_in_bytes: BigInt
animation_url: String
# optional - only added Jan-21
image_sphere: Boolean
scarcity: String
artist: String
tags: [String!]
# New tags added in V3
production_year: String
format: String
theme: String
nsfw: Boolean
}
# Single high level entity capturing the top offer on the secondary marketplace
type TokenOffer @entity(immutable: true) {
id: ID!
version: BigInt! # KODA 2 or 3
token: Token!
edition: Edition!
ownerAtTimeOfBid: Collector!
bidder: Collector!
ethValue: BigDecimal!
timestamp: BigInt!
}
# Encapsulates all offers either on editions or tokens
type Offer @entity {
id: ID! # edition ID or token ID
version: BigInt! # KODA 2 or 3
type: String! # either Token or Edition
salesType: BigInt! # The current sales mechnic being used on this offer
token: Token # nullable token, as editions dont have tokens attached
edition: Edition! # All offers must be from an edition
currentOwner: Collector! # This is either the token holder or the edition artist
bidder: Collector! # Who is making the bid
ethValue: BigDecimal!
weiValue: BigInt!
timestamp: BigInt!
transactionHash: Bytes!
lockedUntil: BigInt # For V3 offers, they will be locked for a certain amount of time
isActive: Boolean! # Only active offers can be seen in the UI
}
# Store the total mints per user, per sale & phase
type PhaseMintCount @entity {
id: ID! # composite key (sale, edition, phase, minter) - unique per user and sale/phase
saleId: String! # The sale this phase relates to
editionId: String! # The edition this phase relates to
phaseId: String! # The actual phase number
minter: String! # The minter
count: BigInt! # How many have they minted
}
# A gate sale phase configuration
type Phase @entity {
id: ID!
saleId: String! # The sale this phase relates to
editionId: String! # The edition this phase relates to
phaseId: String! # The actual phase number
startTime: BigInt! # The start time of the sale as a whole
endTime: BigInt! # The end time of the sale phase, also the beginning of the next phase if applicable
walletMintLimit: BigInt! # The mint limit per wallet for the phase
priceInWei: BigInt! # Price in wei for one mint
mintCap: BigInt! # The maximum amount of mints for the phase
mintCount: BigInt! # The current amount of items minted in this phase
merkleRoot: Bytes # The merkle tree root for the phase
merkleIPFSHash: String # The IPFS hash referencing the merkle tree
}
# A gate sale configuration - one per edition
type GatedSale @entity {
id: ID! # The ID of the sale
editionId: String! # The ID of the edition the sale will mint
paused: Boolean! # Whether the sale is currently paused
primarySaleCommission: BigInt! # overridden sales commission for KO
artistAccount: String # The address of the artist associated with the given edition ID
mintCount: BigInt! # The total mint current for the sale
phases: [Phase!]! # associated sales
}
# Any KODA V4 Contract Deployed from the V4 factory
type CreatorContract @entity {
id: ID!
# Deployment information
blockNumber: BigInt!
timestamp: BigInt!
transactionHash: Bytes!
transactionIndex: BigInt!
logIndex: BigInt!
eventAddress: Bytes!
eventTxFrom: Bytes!
eventTxTo: Bytes
implementation: Bytes! # address of the contract cloned during the deployment of the creator contract
deployer: Bytes! # deployer may be different to creator in the case that platform deployed a contract
creator: Bytes!
# Current Settings
paused: Boolean!
owner: Bytes!
secondaryRoyaltyPercentage: BigInt! # Across all editions the currently specified secondary royalty EIP2981
minter: Bytes!
# Funds handler
defaultFundsHandler: Bytes!
defaultFundsRecipients: [Bytes!]!
defaultFundsShares: [BigInt!]!
# Interface ID
ERC165InterfaceID: Bytes # TODO - Assembly script casting issues fetching this from contract
isBatchBuyItNow: Boolean!
# banned - flagged by the creator contract factory
isHidden: Boolean!
#Transfer details - see transferStates.ts
transferState: BigInt!
# Global stats
totalNumOfEditions: BigInt!
totalNumOfTokensSold: BigInt!
totalEthValueOfSales: BigDecimal!
totalNumOfTransfers: BigInt!
# Editions created by contract
editions: [Edition!]!
# Contract metadata
name: String
symbol: String
filterRegistry: Bytes
}
type CreatorContractSetting @entity {
id: ID!
factoryContract: Bytes! # Creator contract factory
kodaSalesSettingsContract: Bytes! # Things like current primary sales settings
platform: Bytes! # Address
# Settings direct from KODA Settings contract
platformPrimaryCommission: BigInt!
platformSecondaryCommission: BigInt!
MODULO: BigInt!
}
##########################
## Accountable entities ##
##########################
type ArtistMintingConfig @entity {
id: ID!
mints: BigInt!
firstMintInPeriod: BigInt!
frequencyOverride: Boolean! # set to true if the user can mint as much as possible
}
# An artists who has created editions/tokens
type Artist @entity {
id: ID!
address: Bytes! # address
name: String
editionsCount: BigInt!
ccEditionsCount: BigInt!
supply: BigInt!
issuedCount: BigInt!
totalValueInEth: BigDecimal!
salesCount: BigInt!
totalPrimarySales: BigInt!
totalPrimarySalesInEth: BigDecimal!
totalSecondarySales: BigInt!
totalSecondarySalesInEth: BigDecimal!
highestSaleValueInEth: BigDecimal!
highestSaleToken: Token
firstEdition: Edition
firstEditionTimestamp: BigInt!
lastEdition: Edition
lastEditionTimestamp: BigInt!
# all artist editions - derivedFrom only work at query time, not runtime!
editions: [Edition!]! @derivedFrom(field: "artist")
editionIds: [Edition!]!
mintingConfig: ArtistMintingConfig!
creatorContracts: [CreatorContract!]
}
# A single collector who has at sometime held a KO asset
type Collector @entity {
id: ID! # toString for address
address: Bytes! # address
firstSeen: BigInt!
firstPurchaseTimeStamp: BigInt!
lastPurchaseTimeStamp: BigInt!
# Primary sales counts
primaryPurchaseCount: BigInt!
primaryPurchaseEthSpent: BigDecimal!
# Secondary sales counts
secondarySaleCount: BigInt!
secondarySaleEthTotal: BigDecimal!
secondaryPurchaseCount: BigInt!
secondaryPurchaseEthSpent: BigDecimal!
# Primary & secondary sales counts
totalPurchaseCount: BigInt!
totalPurchaseEthSpent: BigDecimal!
# all tokens currently owned by this account - derivedFrom only work at query time, not runtime!
tokens: [Token!]! @derivedFrom(field: "currentOwner")
tokenIds: [Token!]!
}