> For the complete documentation index, see [llms.txt](https://docs.gensyn.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.gensyn.ai/tech/delphi-sdk/subgraph.md).

# Subgraph

## Overview

The Delphi SDK includes a `SubgraphClient` that queries on-chain event data indexed by a [Goldsky subgraph.](https://docs.goldsky.com/subgraphs/introduction)

This gives read-only access to historical *buys, sells, redemptions, liquidations,* and *winner submissions* without needing an archive node or parsing raw logs.

{% hint style="info" %}
For more information on using Goldsky to build on Gensyn, [click here.](https://docs.gensyn.network/builders/goldsky)
{% endhint %}

### Accessing the Subgraph Client

`getSubgraph()` returns a `SubgraphClient` instance configured with the correct Goldsky endpoint for the active network.

```typescript
import { DelphiClient } from "@gensyn-ai/gensyn-delphi-sdk";

const client = new DelphiClient();
const subgraph = client.getSubgraph();
```

#### URL Resolution Order

1. `config.subgraphUrl` (constructor option on `DelphiClient`)
2. `DELPHI_SUBGRAPH_URL` environment variable
3. Network default (*Testnet* or *Mainnet*)

| Network   | Default endpoint                                                                                         |
| --------- | -------------------------------------------------------------------------------------------------------- |
| T*estnet* | `https://api.goldsky.com/api/public/project_cmgzfvv29eu3601tm97hzgzg5/subgraphs/test-graph/1.0.0/gn`     |
| M*ainnet* | `https://api.goldsky.com/api/public/project_cmgzfvv29eu3601tm97hzgzg5/subgraphs/delphi-mainnet/1.0.0/gn` |

### SubgraphClient API

#### query(query, variables?)

You can execute any arbitrary GraphQL query against the subgraph. Returns the `data` field from the response or throws on errors.

```typescript
query<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<T>
```

#### getMarketTrades(marketProxy, params?)

Returns all buy and sell events for a given market proxy address, sorted most-recent-first.

```typescript
getMarketTrades(
  marketProxy: string,
  params?: { first?: number; skip?: number }
): Promise<{ buys: SubgraphBuy[]; sells: SubgraphSell[] }>
```

Defaults: `first = 100`, `skip = 0`.

#### getMeta()

Returns the current indexed block, deployment hash, and whether the subgraph has indexing errors. Useful for checking data freshness.

```typescript
getMeta(): Promise<SubgraphMeta>
```

### Types

#### SubgraphBuy

```typescript
interface SubgraphBuy {
  id: string;
  block_number: string;
  timestamp_: string;          // Unix seconds as string
  transactionHash_: string;
  contractId_: string;
  marketProxy: string | null;
  buyer: string | null;
  outcomeIdx: string | null;
  tokensIn: string | null;     // USDC spent (6-decimal bigint as string)
  sharesOut: string | null;    // Shares received (18-decimal bigint as string)
}
```

#### SubgraphSell

```typescript
interface SubgraphSell {
  id: string;
  block_number: string;
  timestamp_: string;
  transactionHash_: string;
  contractId_: string;
  marketProxy: string | null;
  seller: string | null;
  outcomeIdx: string | null;
  sharesIn: string | null;     // Shares sold (18-decimal bigint as string)
  tokensOut: string | null;    // USDC received (6-decimal bigint as string)
}
```

#### SubgraphMeta

```typescript
interface SubgraphMeta {
  block: {
    number: number;
    timestamp: number | null;
    hash: string | null;
  };
  deployment: string;
  hasIndexingErrors: boolean;
}
```

### GraphQL Schema Entities

The subgraph indexes *six* on-chain event types.&#x20;

Each entity is available as both a singular query (by `id`) and a plural collection query with filtering, ordering, and pagination.

| Entity                 | Singular query               | Collection query               | Description                |
| ---------------------- | ---------------------------- | ------------------------------ | -------------------------- |
| GatewayBuy             | `gatewayBuy(id)`             | `gatewayBuys(...)`             | Share purchase events      |
| GatewaySell            | `gatewaySell(id)`            | `gatewaySells(...)`            | Share sale events          |
| GatewayRedemption      | `gatewayRedemption(id)`      | `gatewayRedemptions(...)`      | Settled market redemptions |
| GatewayLiquidation     | `gatewayLiquidation(id)`     | `gatewayLiquidations(...)`     | Position liquidations      |
| GatewayWinnerSubmitted | `gatewayWinnerSubmitted(id)` | `gatewayWinnerSubmitteds(...)` | Winner declaration events  |
| Initialized            | `initialized(id)`            | `initializeds(...)`            |                            |

### Entity Fields&#x20;

#### Common Fields (All Entities)

| Field              | Type      | Description               |
| ------------------ | --------- | ------------------------- |
| `id`               | `ID!`     | Unique event identifier   |
| `block_number`     | `BigInt!` | Block number of the event |
| `timestamp_`       | `BigInt!` | Unix timestamp (seconds)  |
| `transactionHash_` | `String!` | Transaction hash          |
| `contractId_`      | `String!` | Gateway contract address  |

#### Additional Fields (Specific Entities)

* **GatewayBuy** additional fields: `marketProxy`, `buyer`, `outcomeIdx`, `tokensIn` (USDC, 6-dec), `sharesOut` (shares, 18-dec)
* **GatewaySell** additional fields: `marketProxy`, `seller`, `outcomeIdx`, `sharesIn` (shares, 18-dec), `tokensOut` (USDC, 6-dec)
* **GatewayRedemption** additional fields: `marketProxy`, `redeemer`, `sharesIn` (18-dec), `tokensOut` (USDC, 6-dec)
* **GatewayLiquidation** additional fields: `marketProxy`, `liquidator`, `outcomeIndices`, `sharesIn`, `totalTokensOut` (USDC, 6-dec)
* **GatewayWinnerSubmitted** additional fields: `marketProxy`, `winningOutcomeIdx`

#### Collection Query Parameters

All plural queries accept these:

| Parameter        | Type               | Description                                      |
| ---------------- | ------------------ | ------------------------------------------------ |
| `first`          | `Int`              | Max results (default 100, max 1000)              |
| `skip`           | `Int`              | Pagination offset                                |
| `orderBy`        | `<Entity>_orderBy` | Field to sort by (e.g. `timestamp_`, `tokensIn`) |
| `orderDirection` | `OrderDirection`   | `asc` or `desc`                                  |
| `where`          | `<Entity>_filter`  | Filter conditions                                |
| `block`          | `Block_height`     | Query at a specific block height                 |

#### Filtering (*where* clause)

| Suffix    | Operator         | Example                           |
| --------- | ---------------- | --------------------------------- |
| (none)    | equals           | `{ marketProxy: "0x..." }`        |
| `_not`    | not equals       | `{ buyer_not: "0x..." }`          |
| `_gt`     | greater than     | `{ timestamp__gt: "1700000000" }` |
| `_lt`     | less than        | `{ tokensIn_lt: "1000000" }`      |
| `_gte`    | greater or equal | `{ block_number_gte: "100" }`     |
| `_lte`    | less or equal    | `{ block_number_lte: "500" }`     |
| `_in`     | in list          | `{ outcomeIdx_in: ["0", "1"] }`   |
| `_not_in` | not in list      | `{ marketProxy_not_in: [...] }`   |

{% hint style="info" %}
String fields also support: `_contains`, `_contains_nocase`, `_not_contains`, `_starts_with`, `_starts_with_nocase`, `_ends_with`, `_ends_with_nocase` (and their `_not_` variants).
{% endhint %}

### Usage Examples

Here are some common subgraph query examples.&#x20;

#### 1. Listing recent trades for a given market

```typescript
const subgraph = client.getSubgraph();
const { buys, sells } = await subgraph.getMarketTrades("0x1234...abcd", { first: 20 });

for (const buy of buys) {
  const cost = Number(BigInt(buy.tokensIn ?? "0")) / 1e6;
  const shares = Number(BigInt(buy.sharesOut ?? "0")) / 1e18;
  const time = new Date(Number(buy.timestamp_) * 1000).toLocaleString();
  console.log(`BUY  ${time} | ${buy.buyer} | outcome ${buy.outcomeIdx} | ${cost.toFixed(4)} USDC → ${shares.toFixed(4)} shares`);
}
```

#### 2. Querying global recent buys

```typescript
const data = await subgraph.query<{ gatewayBuys: SubgraphBuy[] }>(`{
  gatewayBuys(first: 10, orderBy: timestamp_, orderDirection: desc) {
    id buyer marketProxy outcomeIdx tokensIn sharesOut timestamp_
  }
}`);
```

#### 3. Filtering buys by wallet address

```typescript
const data = await subgraph.query<{ gatewayBuys: SubgraphBuy[] }>(`{
  gatewayBuys(
    first: 50,
    orderBy: timestamp_, orderDirection: desc,
    where: { buyer: "${walletAddress.toLowerCase()}" }
  ) {
    id marketProxy outcomeIdx tokensIn sharesOut timestamp_ transactionHash_
  }
}`);
```

#### 4. Filtering buys by time range

```typescript
const oneDayAgo = Math.floor(Date.now() / 1000) - 86400;
const data = await subgraph.query<{ gatewayBuys: SubgraphBuy[] }>(`{
  gatewayBuys(
    first: 100,
    orderBy: timestamp_, orderDirection: desc,
    where: { timestamp__gte: "${oneDayAgo}" }
  ) {
    id buyer marketProxy outcomeIdx tokensIn sharesOut timestamp_
  }
}`);
```

#### 5. Querying redemptions for a given market

```typescript
const data = await subgraph.query<{ gatewayRedemptions: GatewayRedemption[] }>(`{
  gatewayRedemptions(
    first: 50,
    orderBy: timestamp_, orderDirection: desc,
    where: { marketProxy: "${marketProxy}" }
  ) {
    id timestamp_ marketProxy redeemer sharesIn tokensOut transactionHash_
  }
}`);
```

#### 6. Querying winner submissions

```typescript
const data = await subgraph.query<{ gatewayWinnerSubmitteds: GatewayWinnerSubmitted[] }>(`{
  gatewayWinnerSubmitteds(
    first: 10,
    orderBy: timestamp_, orderDirection: desc,
    where: { marketProxy: "${marketProxy}" }
  ) {
    id timestamp_ marketProxy winningOutcomeIdx transactionHash_
  }
}`);
```

#### 7. Checking subgraph indexing status

```typescript
const meta = await subgraph.getMeta();
console.log(`Indexed up to block ${meta.block.number}`);
console.log(`Has errors: ${meta.hasIndexingErrors}`);
```

#### 8. Pagination

```typescript
let skip = 0;
const pageSize = 100;
const allBuys: SubgraphBuy[] = [];

while (true) {
  const { buys } = await subgraph.getMarketTrades(marketProxy, { first: pageSize, skip });
  allBuys.push(...buys);
  if (buys.length < pageSize) break;
  skip += pageSize;
}
```

#### 9. Parsing subgraph values

```typescript
// Timestamps → Date
const date = new Date(Number(event.timestamp_) * 1000);

// USDC amounts (6 decimals)
const usdc = Number(BigInt(event.tokensIn ?? "0")) / 1e6;

// Share amounts (18 decimals)
const shares = Number(BigInt(event.sharesOut ?? "0")) / 1e18;

// Outcome index
const outcomeIdx = Number(event.outcomeIdx ?? "0");

// Effective price per share (from a buy event)
const pricePerShare = usdc / shares;
```
