# this supports both ERC20 and ERC721 tokens, as union types aren't currently supported
type Token @entity {
  # token address
  id: Bytes!
  # token symbol
  symbol: String!
  # token name
  name: String!
  # token decimals
  decimals: Int
  # indicates whether the token is ERC20 or ERC721
  tokenType: String! # ERC20 or ERC721
  # number of pools including this token
  poolCount: BigInt!
  # list of pools including this token
  pools: [Pool!]!
  # total supply of the token
  totalSupply: BigInt
  # transactions across all pools that include this token
  txCount: BigInt!
}


  # # # # # # # # #
  # Pool ENTITIES #
  # # # # # # # # #

type PoolFactory @entity {
  # factory address
  id: Bytes!
  # indicates type of collateral (ERC20 or ERC721)
  poolType: String!
  # number of pools deployed by the factory
  poolCount: BigInt!
  # list of pools deployed by the factory
  pools: [Pool!]!
  # total number of transactions sent to the factory
  txCount: BigInt!
}

type Pool @entity {
  # pool address
  id: Bytes!
  # block pool was created at
  createdAtBlockNumber: BigInt!
  # creation timestamp
  createdAtTimestamp: BigInt!
  # address of the pool's collateral token
  collateralToken: Token!
  # address of the pool's quote token
  quoteToken: Token!
  # amount of deposit in the pool
  poolSize: BigDecimal! 
  # debt in T0 terms, useful when the caller knows the pending inflator
  t0debt: BigDecimal!
  # pool inflator snapshot
  inflator: BigDecimal!
  # interest rate paid by borrowers, excluding fees
  borrowRate: BigDecimal!
  # interest rate awarded to lenders, excluding fees
  lendRate: BigDecimal!
  # origination fee paid by borrower on newly drawn debt
  borrowFeeRate: BigDecimal!
  # fee charged to lenders depositing below the highest threshold price
  depositFeeRate: BigDecimal!
  # total collateral pledged to the pool
  pledgedCollateral: BigDecimal!
  # total interest earned by all lenders in the pool
  totalInterestEarned: BigDecimal!
  # total number of transactions sent to the pool
  txCount: BigInt!
  # type of pool: "Fungible", Collection", "Subset"
  poolType: String!

  # LOANS INFORMATION
  loansCount: BigInt! # total number of loans in the pool
  maxBorrower: Bytes! # address of the borrower with the highest TP in the pool
  # normalized total amount of tokens flashloaned from the pool
  quoteTokenFlashloaned: BigDecimal!
  collateralFlashloaned: BigDecimal!

  # PRICES INFORMATION
  hpb: BigDecimal! # current highest price bucket
  hpbIndex: Int! # current highest price bucket index
  htp: BigDecimal! # current highest threshold price
  htpIndex: Int! # current highest threshold price index
  lup: BigDecimal! # current lowest utilized price
  lupIndex: Int! # current lowest utilized price index  

  # RESERVES INFORMATION
  # current reserves contractQuoteBalance + poolDebt - pool.depositSize()
  reserves: BigDecimal!
  # current pool claimable reserves
  claimableReserves: BigDecimal!
  # remaining claimable reserves not yet taken
  claimableReservesRemaining: BigDecimal!
  # current burn epoch
  burnEpoch: BigInt!
  # total ajna burned in the pool
  totalAjnaBurned: BigDecimal!
  # list of all reserve auctions for this pool
  reserveAuctions: [ReserveAuction!]! 

  # UTILIZATION INFORMATION
  # current pool minimum debt amount for a new borrow
  minDebtAmount: BigDecimal!
  # current pool utilization across all borrowers
  actualUtilization: BigDecimal!
  # current pool target utilization rate
  targetUtilization: BigDecimal!

  # LIQUIDATION INFORMATION
  # liquidation bond currently escrowed in the pool
  totalBondEscrowed: BigDecimal!
  # list of active liquidation auctions in the pool, sorted by kick time
  liquidationAuctions: [LiquidationAuction!]!

  # normalized contract balances, used for TVL
  quoteTokenBalance: BigDecimal!
  collateralBalance: BigDecimal!

  # ERC721 POOL INFORMATION
  # pool subsetHash
  subsetHash: Bytes!
  # list of tokenIds pledged by the borrower
  tokenIdsPledged: [BigInt!]!
  # list of tokenIds available to lenders
  bucketTokenIds: [BigInt!]!
  # list of tokenIds allowed by a subset pool
  tokenIdsAllowed: [BigInt!]!
}

type Bucket @entity {
  # bucket id: $poolAddress + '#' + $bucketIndex
  id: Bytes!
  # bucket index
  bucketIndex: Int!
  # bucket price
  bucketPrice: BigDecimal!
  # current exchange rate of the bucket
  exchangeRate: BigDecimal!
  # pool address
  poolAddress: String!
  # pool in which the bucket belongs
  pool: Pool!
  # total collateral available in the bucket
  collateral: BigDecimal!
  # total quote tokens deposited in the bucket, inclusive of interest
  deposit: BigDecimal!
  # total LP for all lenders in the bucket
  lpb: BigDecimal!
  # list of lends associated with the bucket
  lends: [Lend!]!
  # list of PositionLends associated with the bucket
  positionLends: [PositionLend!]!
}

# lend occurs per bucket in a pool
type Lend @entity {
  # Lend id: $bucketId + '|' + $accountId
  id: Bytes!
  # bucket to which a lend was made
  bucket: Bucket!
  # index of the bucket, for querying
  bucketIndex: Int!
  # pool address
  poolAddress: String!
  # address of the lender
  lender: Bytes!
  # pool pointer
  pool: Pool!
  # amount of LPB lender has in the bucket
  lpb: BigDecimal!
  # quote equivalent value of the lend's LPB in the bucket (regardless of available deposit in bucket)
  lpbValueInQuote: BigDecimal!
  # time at which the lend was made
  depositTime: BigInt!
}

# each borrower has only one loan with a pool
type Loan @entity {
  # Loan id: $poolAddress + '|' + $borrowerId
  id: Bytes!
  # pool address
  poolAddress: String!
  # borrower address
  borrower: Bytes!
  # pool pointer
  pool: Pool!
  # boolean indicating whether the loan is in liquidations
  inLiquidation: Boolean!
  # most recent liquidation, whether active or inactive
  liquidationAuction: LiquidationAuction
  # collateral tokens deposited in a pool by the borrower
  collateralPledged: BigDecimal!
  # borrower's threshold price
  thresholdPrice: BigDecimal!
  # list of tokenIds pledged by the borrower
  tokenIdsPledged: [BigInt!]!
  # debt in T0 terms, useful when the caller knows the pending inflator
  t0debt: BigDecimal!
  # borrowers t0 neutral price
  t0Np: BigDecimal!
}

type Account @entity {
  # address of the account
  id: Bytes!
  # list of pools in which an account is present
  pools: [Pool!]!

  # kicks executed by the account
  kicks: [Kick!]!
  # buckets in a pool to which the account has lent quote
  lends: [Lend!]!
  # loans which the account has taken from pools
  loans: [Loan!]!
  # liquidation auctions settled
  settles: [Settle!]!
  # liquidation auctions taken
  takes: [Take!]!

  # reserve auctions which the account has interacted in
  reserveAuctions: [ReserveAuction!]!

  # ecosystem coordination proposals created
  proposalsCreated: [Proposal!]!
  # ecosystem coordination proposals passed and funded 
  proposalsExecuted: [Proposal!]!
  # account to which this account is delegating votes
  delegatedTo: Account
  # accounts from which votes are delegated
  delegatedFrom: [Account!]!
  # delegation rewards claimed across all distribution periods
  rewardsClaimed: BigDecimal!
  # voting state for each distribution period
  distributionPeriodVotes: [DistributionPeriodVote!]!
  # amount of tokens delegated to this account
  tokensDelegated: BigDecimal!

  # positions associated with the account
  positions: [Position!]!

  # total number of transactions sent by the account
  txCount: BigInt!
}

type LiquidationAuction @entity {
  id: Bytes!                       # $poolAddress + '|' + $loanId + '|' + blockNumber
  pool: Pool!                      # pool in which the liquidation occurred
  borrower: Bytes!                 # address of the borrower being liquidated
  lastTakePrice: BigDecimal!       # price of auction upon most recent take
  collateral: BigDecimal!          # initial collateral up for auction
  collateralRemaining: BigDecimal! # collateral which has not been taken
  debt: BigDecimal!                # initial debt to be covered by the auction
  debtRemaining: BigDecimal!       # debt which has not been covered
  loan: Loan!                      # loan being liquidated
  kicker: Bytes!                   # address of the kicker
  kick: Kick!                      # kick which triggered the liquidation
  kickTime: BigInt!                # block timestamp at which the kick was executed
  takes: [Take!]!                  # list of takes which occured using outside liquidity
  bucketTakes: [BucketTake!]!      # list of takes which involved the pool's book
  settles: [Settle!]!              # list of possibly-intermediate settles performed on the auction
  settle: AuctionSettle            # final settlement of the auction
  settleTime: BigInt               # block timestamp at which the liquidation was settled
  settled: Boolean!                # boolean indicating whether the auction has been settled
  bondSize: BigDecimal!            # bond provided by kicker to initate auction
  bondFactor: BigDecimal!          # bond factor determining the reward or penalty for the kicker
  neutralPrice: BigDecimal!        # price at which kicker will have their bond returned without penalty or reward
  referencePrice: BigDecimal!      # max(HTP, NP) used in auction price curve
  thresholdPrice: BigDecimal!      # Threshold price stamped on the liquidation at time of kick
}

# tracks the reserve auction process across multiple takes in a single auction
# used as start and take events are emitted as ReserveAuction
type ReserveAuction @entity {
  id: Bytes!                    # $poolAddress + '|' + $burnEpoch
  pool: Pool!                   # Pool in which the reserve auction occurred
  claimableReservesRemaining: BigDecimal! # uint256 claimable reserves remaining at start or at latest take
  lastTakePrice: BigDecimal!    # uint256 price of auction upon most recent take, denominated in AJNA
  burnEpoch: BigInt!            # uint256 burn epoch at which the reserve auction was started
  kick: ReserveAuctionKick!     # kick information
  takes: [ReserveAuctionTake!]! # list of reserve auction takes that occured during this auction process
  ajnaBurned: BigDecimal!       # total amount of ajna burned across all takes in the reserve auction
}

# LP transferors approved by a lender for a pool, updated upon Approve/RevokeLpTransferors
type LPTransferorList @entity {
  id: Bytes! # $poolAddress + '|' + $lender
  pool: Pool! # pool in which these transferors have been approved
  lender: Bytes! # address of the lender who has approved transferors
  transferors: [Bytes!]! # addresses of approved transferors
}

# represents a LP allowance for a single bucket
type LPAllowance @entity {
  id: Bytes!          # LPAllowanceList.id + '|' + $index
  index: Int!         # bucket index where an allowance has been granted
  amount: BigDecimal! # size of the allowance (measured in LP)
}

# updated upon Increase/Decrease/RevokeLPAllowance
type LPAllowanceList @entity {
  id: Bytes! # $poolAddress + '|' + $lender + '|' + $spender
  pool: Pool! # pool in which LP allowances have been granted
  lender: Bytes! # address of the lender who has granted an allowance
  spender: Bytes! # address who has been granted an allowance
  allowances: [LPAllowance!]! # list of LP allowances
}

  # # # # # # # # # # #
  # ERC20 Pool Events #
  # # # # # # # # # # #

type AddCollateral @entity(immutable: true) {
  id: Bytes!
  pool: Pool!            # Pool to which collateral was added
  bucket: Bucket!        # Bucket to which collateral was added
  actor: Bytes!          # address
  index: Int!            # uint256
  amount: BigDecimal!    # uint256
  lpAwarded: BigDecimal! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type AddQuoteToken @entity(immutable: true) {
  id: Bytes!
  pool: Pool!            # Pool to which quote was added
  bucket: Bucket!        # Bucket to which quote was added
  lender: Bytes!         # address
  index: Int!            # uint256
  amount: BigDecimal!    # uint256
  lpAwarded: BigDecimal! # uint256
  lup: BigDecimal!       # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

# emitted when auction has been removed from the liquidation queue
type AuctionSettle @entity(immutable: true) {
  id: Bytes!
  pool: Pool!             # Pool whose debt was settled
  loan: Loan!             # Loan which was settled
  borrower: Bytes!        # address
  collateral: BigDecimal! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type BondWithdrawn @entity(immutable: true) {
  id: Bytes!
  kicker: Bytes!      # address
  reciever: Bytes!    # address
  amount: BigDecimal! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type BucketBankruptcy @entity(immutable: true) {
  id: Bytes!
  bucket: Bucket!          # Bucket which was bankrupted
  index: Int!              # uint256
  pool: Pool!              # Pool whose bucket was bankrupted
  lpForfeited: BigDecimal! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type BucketTake @entity(immutable: true) {
  id: Bytes!
  borrower: Bytes!          # address
  taker: Bytes!             # address of the taker
  liquidationAuction: LiquidationAuction! # liquidation auction in which the take is occuring
  loan: Loan!               # loan which was taken
  pool: Pool!               # pool in which the take is occuring
  index: Int!               # uint256
  auctionPrice: BigDecimal! # price of auction when taken
  amount: BigDecimal!       # uint256
  collateral: BigDecimal!   # uint256
  bondChange: BigDecimal!   # uint256
  isReward: Boolean!        # bool
  lpAwarded: BucketTakeLPAwarded!
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type BucketTakeLPAwarded @entity(immutable: true) {
  id: Bytes!
  taker: Bytes!                # address
  pool: Pool!                  # Pool in which the take occurred
  kicker: Bytes!               # address
  lpAwardedTaker: BigDecimal!  # uint256
  lpAwardedKicker: BigDecimal! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type DrawDebt @entity(immutable: true) {
  id: Bytes!
  pool: Pool!                    # Pool debt was drawn from
  borrower: Bytes!               # address
  amountBorrowed: BigDecimal!    # uint256
  collateralPledged: BigDecimal! # uint256
  lup: BigDecimal!               # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type Flashloan @entity(immutable: true) {
  id: Bytes!
  pool: Pool! 
  borrower: Bytes!    # address
  amount: BigDecimal! # uint256
}

type Kick @entity {
  id: Bytes!
  kicker: Bytes!             # address of the kicker
  pool: Pool!                # Pool in which a kick occurred
  loan: Loan!                # Loan which was kicked
  locked: BigDecimal!        # amount of quote from the bond locked in the kick (updated on take)  TODO: rename bondLocked
  claimable: BigDecimal!     # amount of quote from the bond claimable by the kicker (updated on settle)  TODO: rename bondClaimable?
  liquidationAuction: LiquidationAuction! # Liquidation auction which was initiated
  borrower: Bytes!           # address of the borrower being liquidated
  debt: BigDecimal!          # amount of debt to be covered
  collateral: BigDecimal!    # amount of collateral available to liquidate
  bond: BigDecimal!          # liquidation bond paid by kicker
  startingPrice: BigDecimal! # initial price of auction
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type LoanStamped @entity(immutable: true) {
  id: Bytes!
  pool: Pool!
  borrower: Bytes! # address
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type MoveQuoteToken @entity(immutable: true) {
  id: Bytes!
  pool: Pool!                 # Pool in which quote tokens were moved
  lender: Bytes!              # address
  from: Bucket!               # bucket quote token was moved from
  to: Bucket!                 # bucket quote token was moved to
  amount: BigDecimal!         # uint256
  lpRedeemedFrom: BigDecimal! # uint256
  lpAwardedTo: BigDecimal!    # uint256
  lup: BigDecimal!            # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type RemoveCollateral @entity(immutable: true) {
  id: Bytes!
  pool: Pool!             # Pool where collateral was removed
  bucket: Bucket!         # Bucket where collateral was removed
  claimer: Bytes!         # address
  index: Int!             # uint256
  amount: BigDecimal!     # uint256
  lpRedeemed: BigDecimal! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type RemoveQuoteToken @entity(immutable: true) {
  id: Bytes!
  pool: Pool!             # Pool where deposit was removed
  bucket: Bucket!         # Bucket where deposit was removed
  lender: Bytes!          # address
  index: Int!             # uint256
  amount: BigDecimal!     # uint256
  lpRedeemed: BigDecimal! # uint256
  lup: BigDecimal!        # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type RepayDebt @entity(immutable: true) {
  id: Bytes!
  pool: Pool!                   # Pool debt was repaid to
  borrower: Bytes!              # address
  quoteRepaid: BigDecimal!      # uint256
  collateralPulled: BigDecimal! # uint256
  lup: BigDecimal!              # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

# starts a claimable reserve auction
type ReserveAuctionKick @entity(immutable: true) {
  id: Bytes!                      # transaction.hash + transaction.from
  kicker: Bytes                   # address of the taker, null if emitted as start of event
  reserveAuction: ReserveAuction! # reserve auction in which the take is occuring
  pool: Pool!                     # pool in which the auction was kicked
  claimableReserves: BigDecimal!  # uint256 initial amount of claimable reserves in the auction
  startingPrice: BigDecimal!      # uint256 initial auction price
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

# indicates AJNA was burned in a claimable reserve auction
type ReserveAuctionTake @entity(immutable: true) {
  id: Bytes!                         # transaction.hash + transaction.from
  taker: Bytes                       # address of the taker, null if emitted as start of event
  reserveAuction: ReserveAuction!    # reserve auction in which the take is occuring
  pool: Pool!                        # pool in which the take is occuring
  claimableReservesRemaining: BigDecimal! # uint256 remaining amount of claimable reserves in the auction
  auctionPrice: BigDecimal!          # uint256 cost of purchasing one quote token, denominated in AJNA
  quotePurchased: BigDecimal!        # amount of quote token purchased by taker in this take
  ajnaBurned: BigDecimal!            # amount of AJNA burned by taker in this take
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

# indicates rate was reset on an underutilized pool with high interest rate
type ResetInterestRate @entity(immutable: true) {
  id: Bytes!
  pool: Pool!                # Pool whose interest rate was reset
  oldBorrowRate: BigDecimal! # uint256
  newBorrowRate: BigDecimal! # uint256
  oldLendRate: BigDecimal!   # uint256
  newLendRate: BigDecimal!   # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

# emitted for each settle TX; one to many required before auction is settled
type Settle @entity(immutable: true) {
  id: Bytes!
  pool: Pool!              # Pool whose debt was settled
  liquidationAuction: LiquidationAuction! # Liquidation auction which was settled
  loan: Loan!              # Loan which was settled
  borrower: Bytes!         # address
  settledDebt: BigDecimal! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type Take @entity(immutable: true) {
  id: Bytes!
  taker: Bytes!             # address of the taker
  pool: Pool!               # Pool in which the take occurred
  borrower: Bytes!          # address of the borrower being liquidated
  liquidationAuction: LiquidationAuction! # Liquidation auction which was taken
  loan: Loan!               # Loan which was taken
  auctionPrice: BigDecimal! # price of auction when taken
  amount: BigDecimal!       # uint256
  collateral: BigDecimal!   # uint256
  bondChange: BigDecimal!   # uint256
  isReward: Boolean!        # bool
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type TransferLP @entity(immutable: true) {
  id: Bytes!
  owner: Bytes!    # address
  newOwner: Bytes! # address
  indexes: [Int!]! # uint256[]
  lp: BigDecimal!  # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type UpdateInterestRate @entity(immutable: true) {
  id: Bytes!
  pool: Pool!                 # Pool whose interest rate was updated
  # interest rates    
  oldBorrowRate: BigDecimal!  # uint256
  newBorrowRate: BigDecimal!  # uint256
  oldLendRate: BigDecimal!    # uint256
  newLendRate: BigDecimal!    # uint256
  # fees
  borrowFeeRate: BigDecimal!  # uint256
  depositFeeRate: BigDecimal! # uint256
  # event
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}
type Approval @entity(immutable: true) {
  id: Bytes!
  owner: Bytes! # address
  approved: Bytes! # address
  tokenId: BigInt! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type ApprovalForAll @entity(immutable: true) {
  id: Bytes!
  owner: Bytes! # address
  operator: Bytes! # address
  approved: Boolean! # bool
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type MoveLiquidity @entity(immutable: true) {
  id: Bytes!
  lender: Bytes!   # address
  tokenId: BigInt! # uint256
  pool: Pool!
  fromIndex: Int!  # uint256
  toIndex: Int!    # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

# PositionManager ERC-721 transfer event
type Transfer @entity(immutable: true) {
  id: Bytes!
  token: Token!    # token which was transferred
  pool: Pool!
  from: Bytes!     # address
  to: Bytes!       # address
  tokenId: BigInt! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type PoolCreated @entity(immutable: true) {
  id: Bytes!
  pool: Pool!           # pool which was created
  poolType: String!     # ERC20 or ERC721
  factory: PoolFactory! # address of factory contract used to create pool
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

  # # # # # # # # # #  #
  # ERC721 POOL EVENTS #
  # # # # # # # # # #  #

type AddCollateralNFT @entity(immutable: true) {
  id: Bytes!
  pool: Pool!            # Pool to which collateral was added
  bucket: Bucket!        # Bucket to which collateral was added
  actor: Bytes!          # address
  index: BigInt!         # bucket index to which collateral was added
  tokenIds: [BigInt!]!   # uint256[] list of tokenIds added as collateral
  lpAwarded: BigDecimal! # lp awarded for adding collateral
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type AuctionNFTSettle @entity(immutable: true) {
  id: Bytes!
  pool: Pool!             # Pool whose debt was settled
  loan: Loan!             # Loan which was settled
  borrower: Bytes!        # address
  collateral: BigDecimal! # uint256
  lp: BigDecimal!         # uint256
  index: Int!             # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type DrawDebtNFT @entity(immutable: true) {
  id: Bytes!
  pool: Pool!                 # Pool from which quote was withdrawn
  borrower: Bytes! # address
  amountBorrowed: BigDecimal! # uint256
  tokenIdsPledged: [BigInt!]! # uint256[]
  lup: BigDecimal! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type MergeOrRemoveCollateralNFT @entity(immutable: true) {
  id: Bytes!
  pool: Pool!            # Pool in which NFT collateral was merged or removed
  actor: Bytes! # address
  collateralMerged: BigDecimal! # uint256
  toIndexLps: BigDecimal! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

  # # # # # # # # # # # # # # #
  # POSITION MANAGER ENTITIES #
  # # # # # # # # # # # # # # #

type Position @entity {
  id: Bytes!                # byte encoded tokenId
  tokenId: BigInt           # tokenId
  indexes: [PositionLend!]! # list of PositionLends which constitute a position
  owner: Bytes!             # address of the position owner
  pool: Pool!               # pool that the position is associated with
  token: Token!             # pointer to LPToken entity
  tokenURI: String!         # tokenURI of the positionNFT
}

# created to handle the seperate lpb positions for each bucket index
type PositionLend @entity {
  id: Bytes! # $positionId + '|' + $bucketIndex
  bucket: Bucket! # pointer to associated Bucket entity
  bucketIndex: Int! # index of the bucket with lpb
  depositTime: BigInt! # time at which the position was deposited
  lpb: BigDecimal! # amount of LPB position has in the bucket
  lpbValueInQuote: BigDecimal! # quote equivalent value of LPB in the bucket
  tokenId: BigInt! # tokenId of the position
}

  # # # # # # # # # # # # # #
  # POSITION MANAGER EVENTS #
  # # # # # # # # # # # # # #

type Burn @entity(immutable: true) {
  id: Bytes!
  lender: Bytes! # address
  tokenId: BigInt! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type MemorializePosition @entity(immutable: true) {
  id: Bytes!
  pool: Pool!
  lender: Bytes!   # address
  tokenId: BigInt! # uint256
  indexes: [Int!]! # uint256[]
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type Mint @entity(immutable: true) {
  id: Bytes!
  lender: Bytes! # address
  pool: Pool!
  tokenId: BigInt! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type RedeemPosition @entity(immutable: true) {
  id: Bytes!
  pool: Pool!
  lender: Bytes!   # address
  tokenId: BigInt! # uint256
  indexes: [Int!]! # uint256[]
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

  # # # # # # # # # # # #
  # GRANT FUND ENTITIES #
  # # # # # # # # # # # #

type GrantFund @entity {
  id: Bytes! # address of the grant fund
  treasury: BigDecimal! # Total ajna tokens in the grant fund treasure
  distributionPeriods: [DistributionPeriod!]! # List of distribution periods
  totalDelegationRewardsClaimed: BigDecimal! # Total delegation rewards claimed across all distribution periods
}

type DistributionPeriod @entity {
  id: Bytes! # distribution period id converted to Bytes from uint
  distributionId: BigInt! # identifies the distribution period
  startBlock: BigInt! # block number the distribution period starts
  endBlock: BigInt! # block number the distribution period ends
  topSlate: FundedSlate # The current top FundedSlate
  slatesSubmitted: [FundedSlate!]! # FundedSlate[] slates submitted in the distribution period
  fundsAvailable: BigDecimal! # Total ajna tokens available for distribution in the distribution period
  delegationRewardsClaimed: BigDecimal! # Total delegation rewards claimed in the distribution period
  fundingVotePowerUsed: BigDecimal! # Total funding vote power used
  screeningVotesCast: BigDecimal! # number of screening votes cast
  votes: [DistributionPeriodVote!]! # Voter info for the distribution period
  proposals: [Proposal!]! # List of proposals submitted in the distribution period
  totalTokensDistributed: BigDecimal! # Total ajna tokens distributed to executed proposals in a distribution period
}

type Proposal @entity {
  id: Bytes! # proposal id converted to Bytes from uint
  proposalId: BigInt! # proposal id stored in original uint format
  description: String! # proposal description hashed as part of proposalId
  distribution: DistributionPeriod # distributionPeriod in which the proposal was submitted if Standard, null otherwise
  executed: Boolean! # bool
  screeningVotesReceived: BigDecimal! # uint256
  fundingVotesReceived: BigDecimal! # uint256
  fundingVotesNegative: BigDecimal! # uint256
  fundingVotesPositive: BigDecimal! # uint256
  totalTokensRequested: BigDecimal! # uint256
  params: [ProposalParams!]! # ProposalParams
}

type ProposalParams @entity {
  id: Bytes! # $proposalId + '|' + $paramIndex
  target: Bytes! # address
  value: BigInt! # uint256
  calldata: Bytes! # bytes
  recipient: Bytes! # address
  tokensRequested: BigDecimal! # uint256
}

type DistributionPeriodVote @entity {
  id: Bytes! # $accountId + '|'' + $distributionId
  voter: Account! # the account of the voter whose vote state in this distribution is being tracked
  distribution: DistributionPeriod! # the distribution period associated with this entity
  initialFundingStageVotingPowerRecordedPostVote: BigDecimal! # Voters initial funding stage voting power. Only recorded if the voter cast a screeningVote in this distribution period.
  remainingFundingStageVotingPowerRecordedPostVote: BigDecimal! # Voters remaining funding stage voting power.
  initialScreeningStageVotingPowerRecordedPostVote: BigDecimal! # Voters initial screening stage voting power. Only recorded if the voter cast a screeningVote in this distribution period.
  remainingScreeningStageVotingPowerRecordedPostVote: BigDecimal! # Voters remaining screening stage voting power.
  screeningVotes: [ScreeningVote!]! # ScreeningVote[] Array of ScreeningVotes cast.
  fundingVotes: [FundingVote!]! # FundingVote[] Array of FundingVotes cast.
}

# 1-1 with Proposal. Multiple screeningVotes on the same proposal write to a single entity
type ScreeningVote @entity {
  id: Bytes! # $proposalId + 'screening' + $account.id + $distributionId
  distribution: DistributionPeriod! # distribution period the vote was cast in
  voter: Account! # actor who cast votes
  proposal: Proposal! # proposal being voted on
  totalVotesCast: BigDecimal! # total screening votes cast by a single voter on a proposal
  votesCast: [VoteCast!]! # array of voteCast entities created for each screeningVote on this proposal
}

# 1-1 with Proposal. Multiple fundingVotes on the same proposal write to a single entity
type FundingVote @entity {
  id: Bytes! # $proposalId + 'funding' + $account.id + $distributionId
  distribution: DistributionPeriod! # distribution period the vote was cast in
  voter: Account! # actor who cast votes
  proposal: Proposal! # proposal being voted on
  totalVotesCast: BigDecimal! # uint256 total unsquared votes cast on the proposal
  votingPowerUsed: BigDecimal! # uint256 # cost of the incremental funding vote to the voter's voting power
  votesCast: [VoteCast!]! # array of voteCast entities created for each fundingVote on this proposal
}

type FundedSlate @entity {
  id: Bytes! # bytes32 hash of slate proposalIds
  distribution: DistributionPeriod! # distribution period the vote was cast in
  proposals: [Proposal!]! # uint256[] list of proposalIds
  totalTokensRequested: BigDecimal! # total number of tokens requested by all proposals in the slate
  totalFundingVotesReceived: BigDecimal! # net funding votes received by all proposals in the slate
  updateBlock: BigInt! # block number the slate was updated
}

  # # # # # # # # # # #
  # GRANT FUND EVENTS #
  # # # # # # # # # # #


type DelegateRewardClaimed @entity(immutable: true) {
  id: Bytes!
  delegateeAddress_: Bytes! # address
  distribution: DistributionPeriod! # distribution period the rewards were claimed in
  rewardClaimed_: BigInt! # uint256  TODO: remove trailing underscore
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type FundTreasury @entity(immutable: true) {
  id: Bytes!
  amount: BigInt! # uint256
  treasuryBalance: BigDecimal! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type FundedSlateUpdated @entity(immutable: true) {
  id: Bytes!
  distributionId_: BigInt! # uint256
  fundedSlateHash_: Bytes! # bytes32
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type ProposalCreated @entity(immutable: true) {
  id: Bytes!
  proposal: Proposal!
  proposer: Bytes! # address
  targets: [Bytes!]! # address[]
  values: [BigDecimal!]! # uint256[]
  signatures: [String!]! # string[]
  calldatas: [Bytes!]! # bytes[]
  startBlock: BigInt! # uint256
  endBlock: BigInt! # uint256
  description: String! # string
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type ProposalExecuted @entity(immutable: true) {
  id: Bytes!
  proposalId: BigInt! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type DistributionPeriodStarted @entity(immutable: true) {
  id: Bytes!
  distribution: DistributionPeriod! # The newly started distribution period
  startBlock: BigInt! # uint256
  endBlock: BigInt! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type VoteCast @entity(immutable: true) {
  id: Bytes!
  voter: Bytes! # address # TODO: should be Account
  proposalId: BigInt! # uint256
  support: Int! # uint8
  weight: BigDecimal! # uint256
  reason: String! # string
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

  # # # # # # # # # # #
  # AJNA TOKEN EVENTS #
  # # # # # # # # # # #

type DelegateChanged @entity(immutable: true) {
  id: Bytes!
  delegator: Bytes! # address
  fromDelegate: Bytes! # address
  toDelegate: Bytes! # address
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type DelegateVotesChanged @entity(immutable: true) {
  id: Bytes!
  delegate: Bytes! # address
  previousBalance: BigDecimal! # uint256
  newBalance: BigDecimal! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}


  # # # # # # # # # # # #
  # BURN WRAPPER EVENTS #
  # # # # # # # # # # # #

type BurnWrap @entity(immutable: true) {
  id: Bytes!
  wrapper: Bytes!     # address
  account: Account    # null if does not already exist
  amount: BigDecimal! # uint256
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}
