type Token @entity {
    id: ID!                                               
    symbol: String                                      
    name: String                                          
    decimals: Int!                                        
    address: String!                                      
    cap: BigDecimal                                       
    supply: BigDecimal                                    
    isDatatoken: Boolean!                                 
    
    "address of ERC721 that owns the token, valid only for datatokens"
    nft: Nft    

    "array of addresses with minter role, can be user wallet address, dispenser etc."                                 
    minter: [User!] 

    "TODO: maybe we change name , depends on audit results . It's the address that collects the payments (NOT fees)"                                      
    feeManager: String   

    "address of the market where the datatoken was created. This address collects market fees."                       
    publishMarketFeeAddress: String 

    "adreess of fee token (can be Ocean, ETH, etc.)"                     
    publishMarketFeeToken: String   

    "fee amount. Fixed value, expressed in wei in contracts, needs conversion in decimals."             
    publishMarketFeeAmmount: BigDecimal   

    "template ID of the datatoken"                               
    templateId: Int                                       

    "number of addresses holding a balance of datatoken , TODO: can we actually calculate this? what happens when users trade the dts"
    holderCount: BigInt!   

    "number of orders executed for this datatoken"                                
    orderCount: BigInt!                                    

    "block time datatoken was created"
    createdTimestamp: Int!        

    "datatoken creation transaction id"                         
    tx: String!        

    "block number when it was created"                                   
    block: Int!                                            
}

"utility type"
type TokenValuePair @entity {
   id : ID!
   token : Token!
   value : BigDecimal!
}

type Nft @entity{
    "nft address"
    id: ID!                                                
    symbol: String!                                       
    name: String!                                          
    tokenUri: String! 
  
    "address of the owner of the nft"                                     
    owner: String!     

    "same as id, it's just for easy discoverability"                                    
    address: String!     

    "provider url that can decrypt the ddo"                                  
    providerUrl: String  

    "state of the asset (described in docs)"                                  
    assetState: Int!                                       

    managerRole: [String!]
    erc20DeployerRole: [String!]
    storeUpdateRole: [String!] 
    "addresses that can update the metadata"
    metadataRole: [String!]                                 

    "template address"
    template: String!           


    "block time nft was created"
    createdTimestamp: Int!                                  
    "nft creation transaction id"
    tx: String!   
    "block number when it was created"                                            
    block: Int                                              
}

type Pool @entity {
    "pool address"
    id: ID!    

    "owner address, pool controller"                                   
    controller: String!

    "only finalized pools are relevant to us"                             
    isFinalized: Boolean!                                   
    
    "pool token symbol"
    symbol: String      

    "pool token name"                                    
    name: String    

    "maximum supply if any, converted from wei"                                        
    cap: BigDecimal                                              

    baseToken: Token! 
    baseTokenLiquidity: BigDecimal!
    baseTokenWeight: BigDecimal!
    
    datatoken: Token!
    datatokenLiquidity: BigDecimal!
    datatokenWeight: BigDecimal!

    "pool Fee percent, fee goes to all liquidity providers : SWAP, JOIN , EXIT"
    poolFee: BigDecimal! 

    "OPF Fee percent, fee that goes to Ocean Protocol Foundation : SWAP"                                    
    opfFee: BigDecimal!   

    "market fee percent, fee that goes to the market where the pool was created : SWAP"                                  
    marketFee: BigDecimal!     

    "actual value of fee collected in both tokens"                             
    totalPoolFee: [TokenValuePair!]!  

    "actual value of fee collected in both tokens"                          
    totalOpfFee: [TokenValuePair!]!   

    "actual value of fee collected in both tokens"                          
    totalMarketFee: [TokenValuePair!]!                            

    "fee after collection =  totalFee - colectedFee"
    availableOpfFee: [TokenValuePair!]!     

    "fee after collection totalFee - colectedFee"                      
    availableMarketFee: [TokenValuePair!]!                        

    "total pool token shares"                           
    totalShares: BigDecimal!   

    "total tokens that were swaped"                             
    totalSwapVolume: [TokenValuePair!]!                         

    spotPrice: BigDecimal!                                  

    "count for when liquidity has been added"
    joinCount: BigInt!             

    "count for when liquidity has been removed"                     
    exitCount: BigInt!              

    "count for when tokens were swapped"                             
    swapCount: BigInt!

    "number of transactions in this pool involving liquidity changes"
    transactionCount: BigInt!                               
   
    "block time when pool was created"
    createdTimestamp: Int!      
    "pool creation transaction id"                            
    tx: String!    
    "block number when it was created"                                          
    block: Int                                              

    shares: [PoolShare!] @derivedFrom(field: "pool")
    transactions: [PoolTransaction!] @derivedFrom(field: "pool")
}

# we will need to track pool share tx between users -  bpool transfer tx event
type PoolShare @entity {
  "poolAddress + userAddress"
  id: ID!                                                   
  user: User!
  pool: Pool!
  shares: BigDecimal!
}

 enum PoolTransactionType {
  JOIN,
  EXIT,
  SWAP,
  SETUP
}

type PoolTransaction @entity {
  "tx address + caller address" 
  id: ID!        
  "pool related to this tx"                                            
  pool: Pool!   
  "user that initiates the tx"                                             
  user: User!                                              
  type: PoolTransactionType!                                                  
  
  "number of shares transfered"
  sharesTransferAmount: BigDecimal!                           
 
  "pool fee value, fee goes to all liquidity providers : SWAP, JOIN , EXIT"
  poolFee: BigDecimal!     

  "OPF Fee value, fee that goes to Ocean Protocol Foundation : SWAP"                                  
  opfFee: BigDecimal!        

  "market fee value, fee that goes to the publishing market"                                
  marketFee: BigDecimal!  

  "block time when pool was created"
  timestamp: Int!      
  "pool creation transaction id"                            
  tx: String!    
  "block number when it was created"                                          
  block: Int       

  gasLimit: BigDecimal!  
  "price expressed in eth"                                    
  gasPrice: BigDecimal!                                      

  "base tokens transfered"
  baseToken: Token 

  "number of base tokens transfered, if value is negative it means it was removed"       
  baseTokenValue: BigDecimal

  "datatokens transfered"                        
  datatoken: Token

  "number of datatokens transfered, if value is negative it means it was removed"
  datatokenValue: BigDecimal
}

type Order @entity {  
  "transaction hash - token address - from address"                                       
  id: ID!                                                    
  token: Token!

  consumer: User!
  payer: User!
  amount: BigDecimal!
  serviceId: Int!


  # the fees will be updated from an event that will be created after (todo)
  publishingMarket: User
  publishingMarketToken: Token                                #
  publishingMarketAmmount: BigDecimal                         #call contract to get fee ammount

  consumerMarket: User
  consumerMarketToken: Token                                  #
  consumerMarketAmmount: BigDecimal                           #call contract to get fee ammount

  createdTimestamp: Int!
  tx: String!
  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!
  createdTimestamp: Int!
  tx: String!
}

type User @entity {
  id: ID!
  sharesOwned: [PoolShare!] @derivedFrom(field: "user")
  tokenBalancesOwned: [TokenValuePair!]
  tokensOwned: [Token!] @derivedFrom(field: "minter")
  poolTransactions: [PoolTransaction!] @derivedFrom(field: "user")
  orders: [Order!] @derivedFrom(field: "payer")
  freSwaps: [FixedRateExchangeSwap!] @derivedFrom(field: "by")
}

type FixedRateExchange @entity {
  "fixed rate exchange id"
  id: ID!                                                    
  owner: User!
  datatoken: Token!
  baseToken: Token!
  price: BigDecimal!
  active: Boolean!
  "amount of total basetokens spent"
  totalSwapValue: BigDecimal!  
  "address that is allowed to  swap tokens"                              
  allowedSwapper: String                                     
  "if the owner allowes the fre to mint"
  withMint: Boolean  
  "if the fre has the minter role on the datatoken"                                        
  isMinter: Boolean                                          

  updates: [FixedRateExchangeUpdate!] @derivedFrom(field: "exchangeId")
  swaps: [FixedRateExchangeSwap!] @derivedFrom(field: "exchangeId")

  createdTimestamp: Int!
  tx: String!
  block: Int!
}

type FixedRateExchangeUpdate @entity {
  id: ID!
  exchangeId: FixedRateExchange!

  oldPrice: BigDecimal
  newPrice: BigDecimal

  oldActive: Boolean
  newActive: Boolean

  oldAllowedSwapper: String
  newAllowedSwapper: String

  block: Int!
  createdTimestamp: Int!
  tx: String!
}

type FixedRateExchangeSwap @entity {
  id: ID!
  exchangeId: FixedRateExchange!
  by: User!
  baseTokenAmount: BigDecimal!
  dataTokenAmount: BigDecimal!
  block: Int!
  createdTimestamp: Int!
  tx: String!
}


type Dispenser @entity {
  "token address"
  id: ID!                                                      
  active: Boolean!   
  "if using the enterprise template the owner will always be the erc721 factory, for normal template it will a user"                         
  owner: String
  token: Token!

  allowedSwapper: String
  isMinter: Boolean   
  "max tokens that can be dispensed"                                         
  maxTokens: BigDecimal! 
  "max balance of requester. If the balance is higher, the dispense is rejected"                              
  maxBalance: BigDecimal!    
  "how many tokens are left"                                   
  balance: BigDecimal!                        


  block: Int!
  createdTimestamp: Int!
  tx: String!                 
  
  dispenses: [DispenserTransaction!] @derivedFrom(field: "dispenser")
}

type DispenserTransaction @entity {
  id: ID!                                                      
  dispenser: Dispenser!
  user: User!
  amount: BigDecimal!

  block: Int!
  createdTimestamp: Int!
  tx: String!
}

type PoolSnapshot @entity {
  id: ID!
  pool: Pool!
  "total pool shares at the end of the 24h interval"
  totalShares: BigDecimal!
  "swap value 24h"
  swapVolume: BigDecimal!   
  "swap fee value 24h"                                          
  swapFees: BigDecimal! 
  "date without time"                                              
  date: Int!         
  "last spot price in the 24h interval"                                 
  spotPrice: BigDecimal!                                         
  
  baseToken: Token!
  baseTokenLiquidity: BigDecimal!

  datatoken: Token!
  datatokenLiquidity: BigDecimal! 

}
type GlobalStats @entity {
    id: ID!

    "total liquidity for each base token"                  
    totalLiquidity: [TokenValuePair!]!                        
    "total swap volume for each base token. pools and fre"
    totalSwapVolume: [TokenValuePair!]!                                
     
    "number of total consumes, pools + fre+ free"
    orderCount: BigInt!                                    

    "total nfts created"
    nftCount: BigInt!
    "total datatokens created"
    datatokenCount:BigInt!
    "number of pools"
    poolCount: Int!     
}


 enum NftUpdateType {
  METADATA_CREATED,
  METADATA_UPDATED,
  STATE_UPDATED,
  TOKENURI_UPDATED
}

type NftUpdate @entity {
  id: ID! # update tx +  nft address
  
  nft: Nft!

 "user that made the update"
  userAddress: String!

  "state of the asset in this update"
  assetState: Int!

  "type of the update: metadata created, metadata update, state update, token uri update"
  type: NftUpdateType!

  block: Int!
  timestamp: Int!
  tx: String!
}