Indexer

Envio HyperIndex events, attribution, trigger state and registry history.

Monad testnet; not audited. Query the selected deployment's GraphQL endpoint with any GraphQL client. The production runbook records its configuration. Production uses project bondrail-next, release branch envio-next, and https://indexer.dev.hyperindex.xyz/1ac5720/v1/graphql. Keep that release branch as-is when updating app deployment names. Indexer history is a read model; reconcile important results with the chain.

BondrailAccount.Settled attributes account-mediated x402 payments; Revenue records the split and avoids counting that settlement again as Native revenue. Collected records Native volume. Token AuthorizationUsed / Transfer evidence can attribute direct-to-token x402 receipts. Payment identities deduplicate settlement and token evidence. Other inflows are unclassified. Native payer attribution uses account events, including calls through another contract; it is not limited to the transaction's top-level recipient.

Bond.triggered follows BondrailBond.TriggerChanged, including recovery; timeline events record Triggered and TriggerRecovered. The on-chain trigger sums all booked account revenue, including self-payments, independently of attributed revenue. BondRecorded and Attested track registry-scoped membership and assessment history when the registry is configured. Evaluate expiry and current signer through attestedProfile; stored event history does not establish current validity or completeness.

Funding-link detection is one hop for the indexed asset. “Attributed” means a proven payer without a detected related-party link under that policy, not an independent customer or delivered service. Coverage, late indexing and omissions matter; see credit profiles.

indexer/schema.graphql
# Bondrail on-chain history, indexed by Envio HyperIndex.
# Event rows use chain:block:tx:logIndex; x402 payments use chain:asset:payer:nonce to correlate logs.

# One business's BondrailAccount: its revenue address and payment entrypoint from day one.
type Issuer {
  id: ID! # account address
  chainId: Int!
  issuer: String! @index
  asset: String! # the token the account earns, raises and repays in
  tier: Int # 0 Native, 1 Watched; Native once a project is bound, otherwise known at the first bond
  project: String @index # Native project bound to the account
  projectApproved: Boolean # reviewer-approved as Native (individually, or via its template)
  template: String @index # creation-code hash of the reviewed template it was deployed from
  activeBond: String
  grossRevenue: BigInt!
  volume: BigInt! # collected gross payments (in and out) plus account settlements
  toInvestors: BigInt!
  toIssuer: BigInt!
  payments: Int!
  createdAt: BigInt!
  firstRevenueAt: BigInt
}

# An issuer's treasury wallet -> its account.
type Treasury {
  id: ID! # issuer wallet address
  accounts: [String!]! # every account this wallet issued (one issuer can run several)
}

# One per (issuer account, wallet) pair once that issuer's treasury has sent the wallet the asset. A wallet
# funded by several issuers has several links; each FundingEdge is one underlying transfer.
type FundingLink {
  id: ID! # `${account}-${wallet}`
  account: String! @index
  wallet: String! @index
  amount: BigInt!
}

type Bond {
  id: ID! # bond address
  chainId: Int!
  account: String! @index
  issuer: String!
  adapter: Int!
  policyHash: String!
  phase: Int! # 0 Funding, 1 Active, 2 Closing, 3 Closed, 4 Cancelled
  raised: BigInt!
  released: BigInt!
  undrawn: BigInt!
  principalRecovery: BigInt!
  revenueCollected: BigInt!
  stakeRecovery: BigInt!
  pool: BigInt!
  redeemed: BigInt!
  totalSupply: BigInt!
  effectiveCap: BigInt!
  defaulted: Boolean!
  triggered: Boolean!
  createdAt: BigInt!
}

type Holder {
  id: ID! # bond-holder
  bond: String! @index
  holder: String! @index
  balance: BigInt!
}

# A USDC transfer into an account (the raw receipt behind an x402 payment or an unclassified inflow).
type Receipt {
  id: ID!
  chainId: Int!
  account: String! @index
  sender: String!
  amount: BigInt!
  block: BigInt!
  blockHash: String!
  txHash: String! @index
  logIndex: Int!
  timestamp: BigInt!
}

# A revenue payment attributed to a payer, exactly once per payment:
#   native    account Revenue event from collect(): the payer is proven by the pull
#   x402      EIP-3009 settlement into an account (AuthorizationUsed in the same tx): the payer signed it
#   transfer  any other USDC transfer into an account: unclassified, never verified revenue
type Payment {
  id: ID!
  chainId: Int!
  account: String! @index
  receiptId: String!
  payer: String! @index
  amount: BigInt!
  timestamp: BigInt! @index
  source: String! # native | transfer | x402
  synthetic: Boolean!
  related: Boolean!
  evidenceComplete: Boolean!
  reasons: [String!]!
  txHash: String!
}

# USDC sent from an issuer's treasury (issuer or payout wallet) to another wallet.
type FundingEdge {
  id: ID!
  chainId: Int!
  issuerAccount: String! @index
  sender: String!
  recipient: String! @index
  amount: BigInt!
  timestamp: BigInt!
  txHash: String!
}

# How one booked payment was divided (account Revenue event).
type Split {
  id: ID!
  account: String! @index
  bond: String!
  payer: String!
  collected: Boolean!
  gross: BigInt!
  toBond: BigInt!
  toIssuer: BigInt!
  timestamp: BigInt!
  txHash: String!
}

# Every bond lifecycle event, for timelines (Deposited, Activated, RevenueReceived, Redeemed, ...).
type ChainEvent {
  id: ID!
  chainId: Int!
  address: String! @index
  kind: String!
  account: String!
  amount: BigInt!
  block: BigInt!
  blockHash: String!
  txHash: String!
  timestamp: BigInt!
}

type CovenantCheck {
  id: ID!
  chainId: Int!
  bond: String! @index
  result: Int! # 0 Unknown, 1 Compliant, 2 Violation
  epoch: BigInt!
  observedAt: BigInt!
  evidenceHash: String!
  txHash: String!
  timestamp: BigInt!
}

type DailyRevenue {
  id: ID! # account-day
  account: String! @index
  day: Int!
  gross: BigInt!
  verified: BigInt! # attributed: a proven payer with no detected link to the issuer
  x402: BigInt! # attributed x402 settlements (the revenue-drop check compares days)
  payments: Int!
}

# Per (account, payer) totals, so pages never need the full payment history.
type PayerTotal {
  id: ID! # `${account}-${payer}`
  account: String! @index
  payer: String!
  amount: BigInt!
  payments: Int!
  related: Boolean! # any payment from this payer was linked to the issuer
  reasons: [String!]!
  source: String! # the first payment's source
}

# EIP-3009 emits AuthorizationUsed immediately before Transfer. Consumed by that Transfer.
type Authorization {
  id: ID! # chain:asset:tx:authorizer
  nonce: String!
}

# Settled precedes its Revenue event, even inside a batched transaction. Consumed by Revenue.
type AccountSettlement {
  id: ID! # chain:tx:account
  payer: String!
  amount: BigInt!
}

# Registry-scoped membership: never infer that this set contains every factory bond.
type CreditBond {
  id: ID! # chain:registry:bond
  chainId: Int!
  registry: String! @index
  account: String! @index
  bond: String!
  timestamp: BigInt!
  txHash: String!
}

# Immutable accepted attestations. Expiry/validity is evaluated by consumers at read time.
type CreditAttestation {
  id: ID! # chain:registry:account:nonce
  chainId: Int!
  registry: String! @index
  account: String! @index
  signer: String!
  periodStart: BigInt!
  periodEnd: BigInt!
  attributedRevenue: BigInt!
  excludedRevenue: BigInt!
  distinctPayers: BigInt!
  topPayerShareBps: Int!
  creditLine: BigInt!
  evidenceHash: String!
  issuedAt: BigInt!
  expiresAt: BigInt!
  nonce: BigInt!
  timestamp: BigInt!
  txHash: String!
}

type LatestCreditAttestation {
  id: ID! # chain:registry:account
  registry: String! @index
  account: String! @index
  attestation: CreditAttestation!
}

# Event-derived registry, mandate and running totals. Unknown legacy metadata stays null until registration.
type Vault {
  id: ID!
  chainId: Int! @index
  registry: String! @index
  asset: String @index
  curator: String
  owner: String
  name: String
  symbol: String
  strategy: String
  metadataHash: String
  pendingCurator: String
  curatorChangeAfter: BigInt
  createdAt: BigInt!
  totalSupply: BigInt!
  deposited: BigInt!
  withdrawn: BigInt!
  depositedShares: BigInt!
  withdrawnShares: BigInt!
  allocated: BigInt!
  collected: BigInt!
  raiseWithdrawn: BigInt!
  income: BigInt!
  lockedIncome: BigInt! # last checkpoint, NOT currently unvested income
  holdings: [String!]! # curator-tracked bonds, not unsolicited claim transfers
  realizedPrice: BigInt # raw assets * 1e18 / raw shares, rounded down
  realizedPriceKind: String # Deposit | Withdraw
  realizedPriceTimestamp: BigInt
}

type VaultActivity {
  id: ID!
  chainId: Int!
  vault: String! @index
  kind: String!
  actor: String!
  receiver: String!
  bond: String!
  assets: BigInt!
  shares: BigInt!
  timestamp: BigInt!
  block: BigInt!
  txHash: String!
  realizedPrice: BigInt # Deposit/Withdraw only; raw assets * 1e18 / raw shares
  lockedIncome: BigInt # IncomeCheckpointed only
}

# Mint/burn/transfer accounting; remaining deposit cost follows transferred shares pro rata.
type VaultPosition {
  id: ID!
  vault: String! @index
  holder: String! @index
  shares: BigInt!
  costBasis: BigInt!
  deposited: BigInt!
  withdrawn: BigInt!
}

# Tracked allocation cost, cleared on full raise withdrawal or collection.
# Claims are allocated Funding claims (1:1 assets), not unsolicited token receipts.
type VaultHolding {
  id: ID! # vault-bond
  vault: String! @index
  bond: String! @index
  claims: BigInt!
  costBasis: BigInt!
  allocated: BigInt!
  collected: BigInt!
  raiseWithdrawn: BigInt!
  active: Boolean!
}

# UTC-day event sums with closing event-derived supply and last checkpoint's locked income.
# Price is the LAST Deposit/Withdraw ratio THAT DAY; null without either, never carried forward.
# Quiet days have no rows. These values are not NAV, idle cash or live entry/exit quotes.
type VaultDailySnapshot {
  id: ID!
  vault: String! @index
  day: Int! @index
  timestamp: BigInt!
  block: BigInt!
  eventCount: Int!
  deposited: BigInt!
  withdrawn: BigInt!
  depositedShares: BigInt!
  withdrawnShares: BigInt!
  allocated: BigInt!
  collected: BigInt!
  raiseWithdrawn: BigInt!
  income: BigInt!
  lockedIncome: BigInt!
  totalSupply: BigInt!
  realizedPrice: BigInt
  realizedPriceKind: String
  realizedPriceTimestamp: BigInt
}