📈Subgraph Queries

Complete guide to querying DreamLend protocol data using The Graph subgraph. Access real-time and historical data for loans, users, and protocol statistics.

🌐 Subgraph Endpoint

GraphQL Endpoint: https://api.subgraph.somnia.network/api/public/d5671b32-2846-489e-a577-e7d9702dd17b/subgraphs/dreamlend-graph/v0.0.3/

Playground: Open GraphQL Playground

📊 Entity Schema

Loan Entity

type Loan @entity {
  id: ID!
  lender: Bytes!
  borrower: Bytes
  tokenAddress: Bytes!
  amount: BigInt!
  interestRate: BigInt!
  duration: BigInt!
  collateralAddress: Bytes!
  collateralAmount: BigInt!
  minCollateralRatioBPS: BigInt!
  liquidationThresholdBPS: BigInt!
  maxPriceStaleness: BigInt!
  status: LoanStatus!
  startTime: BigInt
  repaidAmount: BigInt!
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

User Entity

type User @entity {
  id: ID!
  address: Bytes!
  totalLoansCreated: BigInt!
  totalLoansBorrowed: BigInt!
  totalAmountLent: BigInt!
  totalAmountBorrowed: BigInt!
  totalInterestEarned: BigInt!
  totalInterestPaid: BigInt!
  activeLoansAsLender: [Loan!]! @derivedFrom(field: "lender")
  activeLoansAsBorrower: [Loan!]! @derivedFrom(field: "borrower")
}

ProtocolStats Entity

type ProtocolStats @entity {
  id: ID!
  totalLoansCreated: BigInt!
  totalActiveLoans: BigInt!
  totalLoanVolume: BigInt!
  totalLoanVolumeUSD: BigDecimal!
  totalInterestEarned: BigInt!
  totalCollateralLocked: BigInt!
  totalLiquidations: BigInt!
  totalUsers: BigInt!
}

🔍 Common Queries

Get All Active Loans

query GetActiveLoans {
  loans(
    where: { status: Active }
    orderBy: blockTimestamp
    orderDirection: desc
    first: 100
  ) {
    id
    lender
    borrower
    tokenAddress
    amount
    interestRate
    duration
    collateralAddress
    collateralAmount
    startTime
    blockTimestamp
  }
}

Get Pending Loan Offers

query GetPendingOffers {
  loans(
    where: { status: Pending }
    orderBy: blockTimestamp
    orderDirection: desc
    first: 50
  ) {
    id
    lender
    tokenAddress
    amount
    interestRate
    duration
    collateralAddress
    collateralAmount
    minCollateralRatioBPS
    liquidationThresholdBPS
    blockTimestamp
  }
}

Get User's Loans

query GetUserLoans($userAddress: Bytes!) {
  # Loans where user is lender
  lenderLoans: loans(
    where: { lender: $userAddress }
    orderBy: blockTimestamp
    orderDirection: desc
  ) {
    id
    borrower
    tokenAddress
    amount
    interestRate
    duration
    status
    startTime
    repaidAmount
    blockTimestamp
  }

  # Loans where user is borrower
  borrowerLoans: loans(
    where: { borrower: $userAddress }
    orderBy: blockTimestamp
    orderDirection: desc
  ) {
    id
    lender
    tokenAddress
    amount
    interestRate
    duration
    collateralAddress
    collateralAmount
    status
    startTime
    repaidAmount
    blockTimestamp
  }
}

Get Loan Details

query GetLoanDetails($loanId: ID!) {
  loan(id: $loanId) {
    id
    lender
    borrower
    tokenAddress
    amount
    interestRate
    duration
    collateralAddress
    collateralAmount
    minCollateralRatioBPS
    liquidationThresholdBPS
    maxPriceStaleness
    status
    startTime
    repaidAmount
    blockNumber
    blockTimestamp
    transactionHash
  }
}

Get Protocol Statistics

query GetProtocolStats {
  protocolStats(id: "global") {
    totalLoansCreated
    totalActiveLoans
    totalLoanVolume
    totalLoanVolumeUSD
    totalInterestEarned
    totalCollateralLocked
    totalLiquidations
    totalUsers
  }
}

Get User Statistics

query GetUserStats($userAddress: ID!) {
  user(id: $userAddress) {
    address
    totalLoansCreated
    totalLoansBorrowed
    totalAmountLent
    totalAmountBorrowed
    totalInterestEarned
    totalInterestPaid
    activeLoansAsLender {
      id
      amount
      status
    }
    activeLoansAsBorrower {
      id
      amount
      status
    }
  }
}

Get Loans by Token

query GetLoansByToken($tokenAddress: Bytes!) {
  loans(
    where: { tokenAddress: $tokenAddress }
    orderBy: blockTimestamp
    orderDirection: desc
    first: 100
  ) {
    id
    lender
    borrower
    amount
    interestRate
    duration
    status
    blockTimestamp
  }
}

Get Recent Liquidations

query GetRecentLiquidations {
  loans(
    where: { status: Defaulted }
    orderBy: blockTimestamp
    orderDirection: desc
    first: 50
  ) {
    id
    lender
    borrower
    tokenAddress
    amount
    collateralAddress
    collateralAmount
    blockTimestamp
  }
}

Get Loans with Filters

query GetFilteredLoans(
  $minAmount: BigInt!
  $maxInterestRate: BigInt!
  $tokenAddress: Bytes!
) {
  loans(
    where: {
      status: Pending
      amount_gte: $minAmount
      interestRate_lte: $maxInterestRate
      tokenAddress: $tokenAddress
    }
    orderBy: interestRate
    orderDirection: asc
    first: 20
  ) {
    id
    lender
    amount
    interestRate
    duration
    collateralAddress
    collateralAmount
    blockTimestamp
  }
}

📊 Advanced Queries

Get Loan History with Events

query GetLoanHistory($loanId: ID!) {
  loan(id: $loanId) {
    id
    lender
    borrower
    status
    # Add related events when available
    loanOfferCreatedEvents: loanOfferCreatedEvents(where: { loanId: $loanId }) {
      blockTimestamp
      transactionHash
    }
    loanOfferAcceptedEvents: loanOfferAcceptedEvents(
      where: { loanId: $loanId }
    ) {
      borrower
      blockTimestamp
      transactionHash
    }
  }
}

Get Top Lenders

query GetTopLenders {
  users(
    orderBy: totalAmountLent
    orderDirection: desc
    first: 10
    where: { totalLoansCreated_gt: 0 }
  ) {
    address
    totalLoansCreated
    totalAmountLent
    totalInterestEarned
  }
}

Get Market Overview

query GetMarketOverview {
  # Get protocol stats
  protocolStats(id: "global") {
    totalLoansCreated
    totalActiveLoans
    totalLoanVolumeUSD
  }

  # Get recent loans
  recentLoans: loans(orderBy: blockTimestamp, orderDirection: desc, first: 10) {
    id
    tokenAddress
    amount
    interestRate
    status
    blockTimestamp
  }

  # Get active offers
  activeOffers: loans(
    where: { status: Pending }
    orderBy: interestRate
    orderDirection: asc
    first: 10
  ) {
    id
    tokenAddress
    amount
    interestRate
    duration
  }
}

🛠️ JavaScript Integration

Using Apollo Client

import { ApolloClient, InMemoryCache, gql } from "@apollo/client";

const client = new ApolloClient({
  uri: "https://api.subgraph.somnia.network/api/public/d5671b32-2846-489e-a577-e7d9702dd17b/subgraphs/dreamlend-graph/v0.0.3/",
  cache: new InMemoryCache(),
});

const GET_ACTIVE_LOANS = gql`
  query GetActiveLoans {
    loans(where: { status: Active }, first: 100) {
      id
      lender
      borrower
      amount
      interestRate
      tokenAddress
    }
  }
`;

const { data, loading, error } = await client.query({
  query: GET_ACTIVE_LOANS,
});

Using Fetch API

const query = `
  query GetUserLoans($userAddress: String!) {
    loans(where: { lender: $userAddress }) {
      id
      amount
      interestRate
      status
    }
  }
`;

const response = await fetch(
  "https://api.subgraph.somnia.network/api/public/d5671b32-2846-489e-a577-e7d9702dd17b/subgraphs/dreamlend-graph/v0.0.3/",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query,
      variables: { userAddress: "0x..." },
    }),
  }
);

const { data } = await response.json();

React Hook Example

import { useQuery } from "@apollo/client";

function useUserLoans(userAddress) {
  const { data, loading, error } = useQuery(GET_USER_LOANS, {
    variables: { userAddress },
    pollInterval: 30000, // Poll every 30 seconds
  });

  return {
    lenderLoans: data?.lenderLoans || [],
    borrowerLoans: data?.borrowerLoans || [],
    loading,
    error,
  };
}

📋 Query Parameters

Filtering

  • where: Filter entities by field values

  • where_not: Exclude entities matching criteria

  • where_gt/gte/lt/lte: Numeric comparisons

  • where_in/not_in: Array membership

Sorting

  • orderBy: Field to sort by

  • orderDirection: asc or desc

Pagination

  • first: Number of entities to return (max 1000)

  • skip: Number of entities to skip

  • last: Get last N entities

Example with All Parameters

query GetFilteredLoans {
  loans(
    where: {
      status_in: [Pending, Active]
      amount_gte: "1000000000"
      interestRate_lte: "2000"
    }
    orderBy: blockTimestamp
    orderDirection: desc
    first: 50
    skip: 0
  ) {
    id
    amount
    interestRate
    status
  }
}

🔄 Real-time Updates

Subscriptions (if supported)

subscription OnNewLoans {
  loans(orderBy: blockTimestamp, orderDirection: desc, first: 1) {
    id
    lender
    amount
    interestRate
    blockTimestamp
  }
}

Polling Strategy

// Poll for updates every 30 seconds
const { data } = useQuery(GET_ACTIVE_LOANS, {
  pollInterval: 30000,
  fetchPolicy: "cache-and-network",
});

🎯 Best Practices

Performance Optimization

  1. Limit Results: Always use first parameter

  2. Specific Fields: Only query fields you need

  3. Proper Indexing: Use indexed fields for filtering

  4. Batch Queries: Combine related queries

Error Handling

const { data, loading, error } = useQuery(QUERY, {
  errorPolicy: "all", // Return partial data on error
  onError: (error) => {
    console.error("Subgraph query error:", error);
  },
});

Caching Strategy

const client = new ApolloClient({
  cache: new InMemoryCache({
    typePolicies: {
      Loan: {
        fields: {
          // Cache loans by ID for 5 minutes
          loans: {
            merge: false,
          },
        },
      },
    },
  }),
});

For more examples and integration patterns, see our Developer Integration Guide.

Last updated