Skip to content

Instantly share code, notes, and snippets.

@eshaben
Last active April 26, 2024 20:56
Show Gist options
  • Save eshaben/6ea8906c8758eff1d371e4b5ef1accd5 to your computer and use it in GitHub Desktop.
Save eshaben/6ea8906c8758eff1d371e4b5ef1accd5 to your computer and use it in GitHub Desktop.

Documentation for the Airlyft Campaign Indexer

The generic indexer provides address and transaction information across all participating appchains.

The endpoint for the generic indexer is: https://tanssi-campaign.squids.live/airlyft/graphql

TOC:

Schema

The Chain entity provides statistics for each chain.

type Chain @entity {
  id: ID! # The chain ID. This is the parachain ID, not the EVM chain ID
  transactions: [Transaction!]! @derivedFrom(field: "chain") # List of transactions on this chain
  totalTransactions: BigInt! # The total number of transactions on this chain
  totalContractCalls: BigInt! # The total number of contract calls on this chain
  totalContractsCreated: BigInt! # The total number of contracts created on this chain
  totalGasUsed: BigInt! # The total gas used by this chain
  uniqueAddressesCount: BigInt! # The total number of unique addresses on this chain
  addresses: [Address]! @derivedFrom(field: "chain") # List of addresses on this chain
}

The Address entity provides statistics for each address. There can be multiple Address records in this table if an address has interacted with multiple chains. You can use either id or chain to determine which chain a specific record belongs to.

type Address @entity {
  id: ID! # The chain ID + the address
  address: String! @index # The address
  chain: Chain! # The chain the address exists on
  isContract: Boolean! # Whether the address is a contract address or an EOA
  transactionsSent: [Transaction]! @derivedFrom(field: "sender") # List of transactions sent
  transactionsReceived: [Transaction]! @derivedFrom(field: "receiver") # List of transactions received
  totalTransactions: BigInt! # The total number of transactions sent by this address on this chain
  totalContractCalls: BigInt! # The total number of contract calls for this address on this chain
  totalContractsCreated: BigInt! # The total number of contracts created for this address on this chain
  totalGasUsed: BigInt! # The total gas used for this address on this chain
}

The Transaction entity provides data for EVM and Substrate transactions.

type Transaction @entity {
  id: ID! # The chain ID + the call ID
  chain: Chain! # The chain the transaction was executed on
  blockNo: Int! # The transaction's block number 
  timestamp: String! # The transaction's timestamp
  isEvm: Boolean! # Whether it is an EVM or Substrate transaction
  hash: String! # The Substrate extrinsic or EVM transaction hash
  sender: Address! # Transaction sender
  receiver: Address # Transaction receiver
  gasUsed: BigInt! # Gas consumed. For EVM transactions only
  type: TransactionType # The type of EVM transaction. For EVM transactions only
}

The type property only exists on EVM transactions and will be one of the following:

enum TransactionType {
  BALANCE_TRANSFER
  CONTRACT_CALL
  CONTRACT_CREATION
}

Recommendations

As seen in the above schema, the Address entity provides the address in two ways: through Address.id and Address.address. When querying data for an address on a specific chain, it's best to access Address.id, instead of using the Chain table. For example, the following queries both retrieves an addresses sent transactions on a specific chain:

❌ Don't do this:

query MyQuery {
  transactions(where: {sender: {address_eq: "0xf3de80eb24b43d916b1cdfd29e2691a685d87270"}, AND: {chain: {id_eq: "2800"}}}) {
    hash
  }
}

✅ Do this:

query MyQuery {
  transactions(where: {sender: {id_eq: "2800-0xf3de80eb24b43d916b1cdfd29e2691a685d87270"}}) {
    hash
  }
}

Examples

Get Addresses for a Specific Chain

To get all addresses for a specific chain, you can use the following query:

query AddressesPerChain {
  chains(where: {id_eq: "INSERT_CHAIN_ID"}) {   # Pass in the chain ID (the parachain ID, not the EVM chain ID)
    id                                          # Will return the ID of the chain
    addresses {                                 # An array of address objects
      address                                   # The address
    }
  }
}
Example response
{
  "data": {
    "chains": [
      {
        "id": "2787",
        "addresses": [
          {
            "address": "0x7fd4b72d3bf681c2e80d6076d7997b21def45130"
          },
          {
            "address": "0x4e9a2eee2caf9096161f9a5c3f0b0de8f648aa11"
          },
          {
            "address": "0x4be7e9924bff2fcbb8a3a00e178f304468734465"
          },
          {
            "address": "0x33038f6ca67977c0b02340ac9ef249cb8187a688"
          }
        ]
      }
    ]
  }
}

Get Activity for a Specific Address on a Single Chain

To get address information for a specific chain, you can use the following query:

query AddressSpecificChain {
  addresses(where: {id_eq: "INSERT_CHAIN_ID-INSERT_ADDRESS"}) {
    totalContractCalls
    totalContractsCreated
    totalTransactions
    totalGasUsed
  }
}
Example response
{
  "data": {
    "addresses": [
      {
        "totalContractCalls": "0",
        "totalContractsCreated": "0",
        "totalTransactions": "0",
        "totalGasUsed": "0"
      }
    ]
  }
}

Get Activity for a Specific Address on Multiple Chains

⚠️ The following query is not recommended if you need to get activity data for a large number of addresses. See the Get Activity for a Set of Addresses Across All Chains section.

To get a break down of address activity across all chains, you can use the following query. It will return an address object for each chain the address has interacted with, providing a breakdown of activity on each chain. If you're trying to get the totals for each, you must combine all the entries to get the totals or you can use the query in the Get Activity for a Set of Addresses Across All Chains section.

query AddressAllChains {
  addresses(where: {address_eq: "INSERT_ADDRESS"}) {
    id
    totalContractCalls
    totalContractsCreated
    totalTransactions
    totalGasUsed
  }
}
Example response
{
  "data": {
    "addresses": [
      {
        "id": "2787-0x33038f6ca67977c0b02340ac9ef249cb8187a688",
        "totalContractCalls": "2",
        "totalContractsCreated": "0",
        "totalTransactions": "4",
        "totalGasUsed": "0"
      },
      {
        "id": "2700-0x33038f6ca67977c0b02340ac9ef249cb8187a688",
        "totalContractCalls": "0",
        "totalContractsCreated": "0",
        "totalTransactions": "10",
        "totalGasUsed": "0"
      }
    ]
  }
}

Get Total Activity for a Set of Addresses Across All Chains

The following query returns the total numbers across all chains for the provided addresses. It orders the returned data by the total number of transactions (from highest to lowest).

To get address information for a large number of addresses across all chains, you can use the following query. Please note that the maximum number of addresses that should be passed to this query is 4000. If you have more than 4000 addresses, you'll need to split them up into chunks before passing them to the query.

query AddressStats {
  # Addresses should be in `address` format, not `chain-address` format
  userStats(addresses: ["INSERT_ADDRESS", "INSERT_ADDRESS", ...]) {
    address
    interactedAppchains
    totalContractCalls
    totalGasConsumed
    totalTransactions
  }
}
Example response
{
  "data": {
    "userStats": [
      {
        "address": "0x4e9a2eee2caf9096161f9a5c3f0b0de8f648aa11",
        "interactedAppchains": [
          "2787"
        ],
        "totalContractCalls": "0",
        "totalGasConsumed": "2974430",
        "totalTransactions": "2"
      },
      {
        "address": "0x7fd4b72d3bf681c2e80d6076d7997b21def45130",
        "interactedAppchains": [
          "2787"
        ],
        "totalContractCalls": "0",
        "totalGasConsumed": "21000",
        "totalTransactions": "1"
      }
    ]
  }
}

Get Transactions for a Specific Address

To get the transactions for a specific address, you can use the following query:

query AddressTransactions {
  addresses(where: {id_eq: "INSERT_CHAIN_ID-INSERT_ADDRESS"}) {
    totalTransactions
    transactionsSent {
      hash
    }
    transactionsReceived {
      hash
    }
  }
}

⚠️ Please remember that the total number of transactions only includes sent transactions. So while you can query the sent and received transactions, the totalTransactions only includes sent transactions.

Example response
{
  "data": {
    "addresses": [
      {
        "id": "2787-0x7fd4b72d3bf681c2e80d6076d7997b21def45130",
        "totalTransactions": "1",
        "transactionsSent": [
          {
            "hash": "0x3963dcaf24abd3b4b0cd53be7f1c4611b5670985c111d3cfb1a3768e67ad3c05"
          }
        ],
        "transactionsReceived": []
      }
    ]
  }
}

Get an Addresses Interactions with a Specific Contract

To get an addresses interactions with a specific contract, you can use the following query:

query MyQuery {
  transactions(where: {receiver: {id_eq: "INSERT_CHAIN_ID-INSERT_CONTRACT_ADDRESS"}, AND: {sender: {id_eq: "INSERT_CHAIN_ID-INSERT_ADDRESS"}}}) {
    hash
  }
}
Example response
{
  "data": {
    "transactions": [
      {
        "hash": "0x82986906eb1f60a99dc8a315a4a7caede3e8ca168d27fb9d8188c7004aea974b"
      },
      {
        "hash": "0x975425ec1129d82b928cd78a894dc679c63aff69f55a63093707a1f853863a40"
      }
    ]
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment