type Token @entity { id: ID! # symbol: String # name: String # decimals: Int! # address: String! # cap: BigDecimal # supply: BigDecimal # isDatatoken: Boolean! # factory: DatatokenFactory # owner: String # address of ERC721 that owns the token, valid only for datatokens minter: [String] # array of addresses with minter role, can be user wallet address, dispenser etc. feeManager: String # TODO: maybe we change name , depends on audit results . It's the address that collects the payments (NOT fees) publishMarketFeeAddress: String # address of the market where the datatoken was created. This address collects market fees. publishMarketFeeToken: String # adreess of fee token (can be Ocean, ETH, etc.) publishMarketFeeAmmount: BigDecimal # fee amount. Fixed value, expressed in wei in contracts, needs conversion in decimals. templateId: Int # template ID of the datatoken holderCount: BigInt # Number of addresses holding a balance of datatoken orderCount: BigInt # Number of orders executed for this datatoken createTime: Int # Block time datatoken was created tx: Bytes # Datatoken creation transaction id block: Int # Block number when it was created } type TokenValue { token : Token! value : BigDecimal! } type NftToken @entity{ id: ID! # symbol: String! # name: String! # address: String! tokenUri: String! # owner: String! providerUrl: String # provider url that can decrypt the ddo assetState: Int! # state of the asset (described in docs) managerRole: [String] erc20DeployerRole: [String] storeUpdateRole: [String] metadataRole: [String] # addresses that can update the metadata } #TODO: do we need factories in general? We can move statistics on global object, check if we use them in a way type PoolFactory @entity { id: ID! totalValueLocked: [TokenValue] # total value locked represented in the base token totalLiquidity: [TokenValue] # total liquidity for each base token totalSwapVolume: [TokenValue] # total swap volume for each base token totalSwapFee: [TokenValue] # All the swap fee in Ocean poolCount: Int! # Number of pools finalizedPoolCount: Int! # Number of finalized pools orderCount: BigInt # Number of total consumes totalOrderVolume: BigDecimal # probably remove due to inconsistencies and imposibility to calculate pools: [Pool!] @derivedFrom(field: "factoryID") } type DatatokenFactory @entity { id: ID! tokenCount: Int! # Number of datatokens datatokens: [Tokens!] @derivedFrom(field: "factory") } type Pool @entity { id: ID! # Pool address poolFactory: PoolFactory! # Pool factory owner: String! # Owner address, pool controller isPublicSwap: Boolean! # if swap/trade is activated, probably always true isFinalized: Boolean! # only finalized pools are relevant to us symbol: String # Pool token symbol name: String # Pool token name cap: BigDecimal # Maximum supply if any, converted from wei isActive: Boolean! # pool is active poolFee: BigDecimal! # Pool Fee percent, fee goes to all liquidity providers : SWAP, JOIN , EXIT opfFee: BigDecimal! # OPF Fee percent, fee that goes to Ocean Protocol Foundation : SWAP marketFee: BigDecimal! # Market fee percent, fee that goes to the market where the pool was created : SWAP totalPoolFee: [TokenValue!]! # actual value of fee collected in both tokens totalOpfFee: [TokenValue!]! # actual value of fee collected in both tokens totalMarketFee: [TokenValue!]! # actual value of fee collected in both tokens currentOpfFee: [TokenValue!]! # fee after collection totalFee - colectedFee currentMarketFee: [TokenValue!]! # fee after collection totalFee - colectedFee totalWeight: BigDecimal! # it's always 100 totalShares: BigDecimal! # Total pool token shares totalSwapVolume: [TokenValue!]! # total tokens that were swaped spotPrice: BigDecimal! # spot price joinCount: BigInt! # liquidity has been added exitCount: BigInt! # liquidity has been removed swapCount: BigInt! transactionCount: BigInt! # Number of transactions in this pool involving liquidity changes createTime: Int! # Block time pool was created tx: Bytes # Pool creation transaction id block: Int # Block number when it was created # split in basetokne and datatoken like in fre tokens: [PoolToken!] @derivedFrom(field: "poolId") shares: [PoolShare!] @derivedFrom(field: "poolId") transactions: [PoolTransaction!] @derivedFrom(field: "pool") } # should not pe @entity type PoolToken @entity { id: ID! # poolId + token address pool: Pool! # token: Token! balance: BigDecimal! # balance of the token in this pool denormWeight: BigDecimal! # weight of token in the pool (50% for our pools) } # we will need to track pool share tx between users - bpool transfer tx event type PoolShare @entity { id: ID! # poolId + userAddress user: User! pool: Pool! balance: BigDecimal! } #check balancer v2 graph TX type PoolTransaction @entity { id: ID! # tx + caller pool: Pool! # Pool related to this tx user: User! # User that initiates the tx type: Int # 0 - JOIN, 1 - EXIT , 2 - SWAP, maybe change to enum sharesTransferAmount: BigDecimal # Number of shares transfered poolFee: BigDecimal! # Pool Fee percent, fee goes to all liquidity providers : SWAP, JOIN , EXIT opfFee: BigDecimal! # OPF Fee percent, fee that goes to Ocean Protocol Foundation : SWAP marketFee: BigDecimal! tx: Bytes! event: String block: Int! timestamp: Int! gasUsed: BigDecimal! gasPrice: BigDecimal! # change to baseToken and dataToken tokens: [TokenValue!] # tokens transfered , if value is negative it means it was removed. } type Order @entity { # renamed from TokenOrder to Order id: ID! # datatokenId + userAddress + tx token: Token! consumer: User! payer: User! amount: BigDecimal! serviceId: Int! # the fees will be updated from an event that will be created after (todo) publishingMarketAddress: User publishingMarketToken: Token # publishingMarketAmmount: BigDecimal #call contract to get fee ammount consumerMarketAddress: User consumerMarketToken: Token # consumerMarketAmmount: BigDecimal #call contract to get fee ammount timestamp: Int! tx: Bytes block: Int! } # to be removed, mabye for pool shares only type TokenTransaction @entity { id: ID! # Log ID event: String token: Token user: User block: Int! gasUsed: BigDecimal! gasPrice: BigDecimal! timestamp: Int! tx: Bytes! } type User @entity { id: ID! sharesOwned: [PoolShare!] @derivedFrom(field: "user") tokenBalancesOwned: [TokenValue!] tokensOwned: [Token!] @derivedFrom(field: "minter") poolTransactions: [PoolTransaction!] @derivedFrom(field: "user") orders: [Order!] @derivedFrom(field: "payer") freSwaps: [FixedRateExchangeSwap!] @derivedFrom(field: "by") } type FixedRateExchange @entity { id: ID! # fixed rate exchange id exchangeOwner: User! datatoken: Token! baseToken: Token! price: BigDecimal! active: Boolean! totalSwapValue: BigDecimal! # amount of total basetokens spent allowedSwapper: String # address that is allowed to swap tokens supply: Int! withMint: Boolean # if the owner allowes the fre to mint isMinter: Boolean # if the fre has the minter role on the datatoken updates: [FixedRateExchangeUpdate!] @derivedFrom(field: "exchangeId") swaps: [FixedRateExchangeSwap!] @derivedFrom(field: "exchangeId") } type FixedRateExchangeUpdate @entity { id: ID! exchangeId: FixedRateExchange! oldPrice: BigDecimal! newPrice: BigDecimal! oldActive: Boolean! newActive: Boolean! oldAllowedSwapper: String newAllowedSwapper: String block: Int! timestamp: Int! tx: Bytes! } type FixedRateExchangeSwap @entity { id: ID! exchangeId: FixedRateExchange! by: User! baseTokenAmount: BigDecimal! dataTokenAmount: BigDecimal! block: Int! timestamp: Int! tx: Bytes! } # since in the template that we will use minterApproved is sort of "bundled" with isTrueMinter i think we should have only one field here to easily check if dispenser cand mint type Dispenser @entity { id: ID! # it's the datatoken address active: Boolean! owner: User! datatoken: Token! withMint: Boolean # if the owner allowes the fre to mint isMinter: Boolean # if the fre has the minter role on the datatoken maxTokens: BigDecimal! # max tokens that can be dispensed maxBalance: BigDecimal! # max balance of requester. If the balance is higher, the dispense is rejected balance: BigDecimal! # how many tokens are left dispenses: [DispenserTransaction!] @derivedFrom(field: "dispenserId") } type DispenserTransaction @entity { id: ID! dispenser: Dispenser! datatoken: Token! user: User! amount: BigDecimal! block: Int! timestamp: Int! tx: Bytes! } type PoolSnapshot @entity { id: ID! pool: Pool! totalShares: BigDecimal! swapVolume: BigDecimal! # swap value 24h swapFees: BigDecimal! # swap fee value 24h timestamp: Int! # date without time spotPrice: BigDecimal! # TODO: last spot price or first one? tokens: [PoolSnapshotTokenValue!] @derivedFrom(field: "poolSnapshot") } type PoolSnapshotTokenValue @entity { id: ID! # pool tx + tokenAddress token: Token! value: BigDecimal! tokenReserve: BigDecimal! # how many tokens are left in pool poolSnapshot: PoolSnapshot! } type Global @entity { id: ID! totalValueLocked: [TokenValuePair] # total value locked represented in the base token , basically 2x liqudity for each base token totalLiquidity: [TokenValuePair] # total liquidity for each base token totalSwapVolume: [TokenValuePair] # total swap volume for each base token. pools and fre orderCount: BigInt # Number of total consumes, pools + fre poolCount: Int! # Number of pools for all factories finalizedPoolCount: Int! # Number of finalized pools for all factories } type MetadataUpdate @entity { id: ID! # update tx + datatokenAddress datatokenId: Datatoken! datatokenAddress: String! userAddress: String! block: Int! timestamp: Int! tx: Bytes! }