> ## 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 Addresses

> TxLINE Solana program addresses and public validation accounts

## Mainnet Addresses

| Type           | Address                                        |
| -------------- | ---------------------------------------------- |
| Program ID     | `9ExbZjAapQww1vfcisDmrngPinHTEfpjYRWMunJgcKaA` |
| TxL Token Mint | `Zhw9TVKp68a1QrftncMSd6ELXKDtpVMNuMGr1jNwdeL`  |
| API Endpoint   | `https://txline.txodds.com/api/`               |

## Devnet Addresses

| Type           | Address                                        |
| -------------- | ---------------------------------------------- |
| Program ID     | `6pW64gN1s2uqjHkn1unFeEjAwJkPGHoppGvS715wyP2J` |
| TxL Token Mint | `4Zao8ocPhmMgq7PdsYWyxvqySMGx7xb9cMftPMkEokRG` |
| API Endpoint   | `https://txline-dev.txodds.com/api/`           |

<Warning>
  Use all values from one network only. A devnet subscribe transaction from `6pW64gN1s2uqjHkn1unFeEjAwJkPGHoppGvS715wyP2J` must be activated with `https://txline-dev.txodds.com`, and a mainnet subscribe transaction from `9ExbZjAapQww1vfcisDmrngPinHTEfpjYRWMunJgcKaA` must be activated with `https://txline.txodds.com`.
</Warning>

## Network Consistency Checklist

| Network | Solana RPC                            | Program ID                                     | TxL Mint                                       | Guest JWT URL                                    | Activation URL                                     |
| ------- | ------------------------------------- | ---------------------------------------------- | ---------------------------------------------- | ------------------------------------------------ | -------------------------------------------------- |
| Mainnet | `https://api.mainnet-beta.solana.com` | `9ExbZjAapQww1vfcisDmrngPinHTEfpjYRWMunJgcKaA` | `Zhw9TVKp68a1QrftncMSd6ELXKDtpVMNuMGr1jNwdeL`  | `https://txline.txodds.com/auth/guest/start`     | `https://txline.txodds.com/api/token/activate`     |
| Devnet  | `https://api.devnet.solana.com`       | `6pW64gN1s2uqjHkn1unFeEjAwJkPGHoppGvS715wyP2J` | `4Zao8ocPhmMgq7PdsYWyxvqySMGx7xb9cMftPMkEokRG` | `https://txline-dev.txodds.com/auth/guest/start` | `https://txline-dev.txodds.com/api/token/activate` |

The transaction signature, guest JWT, activation endpoint, and program ID must all come from the same row. If any one value comes from a different row, activation can fail even when the on-chain transaction itself confirmed.

## API Hosts

| Network | Guest Auth                                       | API Base                             |
| ------- | ------------------------------------------------ | ------------------------------------ |
| Mainnet | `https://txline.txodds.com/auth/guest/start`     | `https://txline.txodds.com/api/`     |
| Devnet  | `https://txline-dev.txodds.com/auth/guest/start` | `https://txline-dev.txodds.com/api/` |

Use the host root for `/auth/guest/start`, then use the matching `/api/token/activate` endpoint after the on-chain `subscribe` transaction confirms.

## Program References

| Network | Reference                                                      |
| ------- | -------------------------------------------------------------- |
| Mainnet | [Program Reference (Mainnet)](/documentation/programs/mainnet) |
| Devnet  | [Program Reference (Devnet)](/documentation/programs/devnet)   |

For runnable code, use the examples that match your network and keep the program ID, generated types, API host, and proof data aligned.

## Activation Message

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 matching network as `Authorization: Bearer <jwt>`.

## Public Validation Accounts

| Account                  | Seed(s)                                                            | Purpose                                                 |
| ------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------- |
| Daily scores roots       | `daily_scores_roots`, `epochDay` as u16 little-endian              | On-chain root account used for score proof validation   |
| Daily batch roots        | `daily_batch_roots`, `epochDay` as u16 little-endian               | On-chain root account used for odds proof validation    |
| Ten daily fixtures roots | `ten_daily_fixtures_roots`, aligned epoch day as u16 little-endian | On-chain root account used for 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");

// For devnet, replace programId with:
// 6pW64gN1s2uqjHkn1unFeEjAwJkPGHoppGvS715wyP2J

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];
}
```
