> ## Documentation Index
> Fetch the complete documentation index at: https://txline-docs.txodds.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Program Reference (Mainnet)

> Public mainnet integration values for TxLINE programs

## Overview

Use this page for the public mainnet values needed by TxLINE integrations. Keep the Solana RPC, program ID, TxL mint, guest JWT host, activation endpoint, and API host on the same network.

<Warning>
  Do not activate a mainnet transaction on the devnet API host. A mainnet subscription transaction must be activated with `https://txline.txodds.com`.
</Warning>

## Mainnet Values

| Type           | Value                                          |
| -------------- | ---------------------------------------------- |
| Solana RPC     | `https://api.mainnet-beta.solana.com`          |
| Program ID     | `9ExbZjAapQww1vfcisDmrngPinHTEfpjYRWMunJgcKaA` |
| TxL Token Mint | `Zhw9TVKp68a1QrftncMSd6ELXKDtpVMNuMGr1jNwdeL`  |
| Guest Auth     | `https://txline.txodds.com/auth/guest/start`   |
| Activation     | `https://txline.txodds.com/api/token/activate` |
| API Base       | `https://txline.txodds.com/api/`               |

## Activation

After `subscribe(serviceLevelId, durationWeeks)` confirms, activate the API token by signing this exact message with the same wallet that submitted the transaction:

```text theme={null}
${txSig}:${selectedLeagues.join(",")}:${jwt}
```

For the standard free bundle, `selectedLeagues = []`, so the message is:

```text theme={null}
${txSig}::${jwt}
```

Send the detached wallet signature as base64 in `walletSignature`, and send the guest JWT from the mainnet host as `Authorization: Bearer <jwt>`.

## Validation Accounts

| Account                  | Seed(s)                                                            | Used for                                                       |
| ------------------------ | ------------------------------------------------------------------ | -------------------------------------------------------------- |
| Daily scores roots       | `daily_scores_roots`, `epochDay` as u16 little-endian              | Score proof validation with `validateStat` or `validateStatV2` |
| Daily batch roots        | `daily_batch_roots`, `epochDay` as u16 little-endian               | Odds proof validation                                          |
| Ten daily fixtures roots | `ten_daily_fixtures_roots`, aligned epoch day as u16 little-endian | Fixture proof validation                                       |

<Warning>
  Derive the epoch day from the exact timestamp in the proof response, never from `Date.now()`. For scores, use `validation.summary.updateStats.minTimestamp`; for fixtures, use `validation.snapshot.Ts`; for odds, use `validation.odds.Ts`. Recompute it for every proof.
</Warning>

```typescript theme={null}
import { PublicKey } from "@solana/web3.js";
import { BN } from "@coral-xyz/anchor";

const programId = new PublicKey("9ExbZjAapQww1vfcisDmrngPinHTEfpjYRWMunJgcKaA");

function epochDayFromProofTimestamp(proofTimestampMs: number): number {
  if (!Number.isSafeInteger(proofTimestampMs) || proofTimestampMs < 0) {
    throw new Error("Expected a non-negative proof timestamp in milliseconds");
  }

  const epochDay = Math.floor(proofTimestampMs / 86400000);
  if (epochDay > 0xffff) {
    throw new Error("Proof timestamp is outside the u16 epoch-day range");
  }
  return epochDay;
}

function deriveDailyValidationPda(
  seed: "daily_scores_roots" | "daily_batch_roots",
  proofTimestampMs: number
): PublicKey {
  const epochDay = epochDayFromProofTimestamp(proofTimestampMs);
  return PublicKey.findProgramAddressSync(
    [Buffer.from(seed), new BN(epochDay).toArrayLike(Buffer, "le", 2)],
    programId
  )[0];
}

function deriveTenDailyFixturesPda(fixtureProofTimestampMs: number): PublicKey {
  const epochDay = epochDayFromProofTimestamp(fixtureProofTimestampMs);
  const alignedEpochDay = Math.floor(epochDay / 10) * 10;
  return PublicKey.findProgramAddressSync(
    [
      Buffer.from("ten_daily_fixtures_roots"),
      new BN(alignedEpochDay).toArrayLike(Buffer, "le", 2),
    ],
    programId
  )[0];
}
```

## Score Validation

The public score validation endpoint supports both validation shapes:

| API request                                                      | On-chain method  | Use case                                      |
| ---------------------------------------------------------------- | ---------------- | --------------------------------------------- |
| `/scores/stat-validation?fixtureId=...&seq=...&statKey=...`      | `validateStat`   | Single-stat or legacy two-stat validation     |
| `/scores/stat-validation?fixtureId=...&seq=...&statKeys=1,2,...` | `validateStatV2` | Multi-stat validation with indexed strategies |

Use a real `seq` value from an observed score record. For V2 validation, keep the requested `statKeys` order stable because strategy indexes refer to those same positions.

## Related Guides

* [Quickstart](/documentation/quickstart)
* [World Cup Free Tier](/documentation/worldcup)
* [On-Chain Validation](/documentation/examples/onchain-validation)
* [Streaming Data](/documentation/examples/streaming-data)
* [Troubleshooting](/documentation/examples/troubleshooting)
