# 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;
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.gensyn.ai/tech/delphi-sdk/subgraph.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
