# Litany Protocol — Agent Skill File

You are interacting with the Litany Protocol on Abstract mainnet. This file contains everything needed to mint, read, evaluate, and trade Litany Cards.

---

## Network

```
Chain:      Abstract
Chain ID:   2741
RPC:        https://api.abs.xyz
Explorer:   https://abscan.org
Currency:   ETH
```

---

## Contracts

```
LitanyCards:    0xd44abe71c312FCAf73cC20f7DF61C39A89C203eB
LitanyRenderer: 0x4044dA12e3d20A865A733802F84F7bDb4892Ce0C
```

---

## What Litany Cards Are

Litany Cards are onchain firmware — text-based configuration NFTs that define what an entity becomes when it loads the data. Each card is seven lines of text: a name, a class, four performance parameters, and a unique trait. All generated and rendered fully onchain as SVG. No IPFS. No external hosting.

There are 8,000 genesis Litany Cards. Each one is unique. They are the composable primitive of the Litany Protocol — readable by any game contract, loadable into any entity contract built on the protocol.

Hollows (entity NFTs, 5,000 supply) launch after the Litany mint. Each Litany holder can summon one Hollow for free. 8,000 Litany holders competing for 5,000 Hollows. First come, first served. Holding a Litany Card is the ticket.

---

## Minting

### Check Availability

```
mintActive()   → bool       Is mint open?
mintPrice()    → uint256    Cost per card in wei
totalSupply()  → uint256    How many have been minted
MAX_SUPPLY()   → uint256    Maximum supply (8,000)
MAX_PER_TX()   → uint256    Maximum per transaction
```

Proceed only if `mintActive == true` and `totalSupply < MAX_SUPPLY`.

### Mint

```
function mint(uint256 quantity) external payable
```

- `quantity`: 1 to MAX_PER_TX
- `value`: `mintPrice * quantity` in wei
- Cards are generated deterministically at mint time
- Uses `_mint` (no callback, no reentrancy vector)
- Protected by `nonReentrant` and `whenNotPaused`

### Example (viem)

```javascript
const LITANY_CARDS = "0xd44abe71c312FCAf73cC20f7DF61C39A89C203eB";

// Check state
const [active, price, supply, max] = await Promise.all([
  client.readContract({ address: LITANY_CARDS, abi, functionName: "mintActive" }),
  client.readContract({ address: LITANY_CARDS, abi, functionName: "mintPrice" }),
  client.readContract({ address: LITANY_CARDS, abi, functionName: "totalSupply" }),
  client.readContract({ address: LITANY_CARDS, abi, functionName: "MAX_SUPPLY" }),
]);

// Mint
const quantity = 5n;
const hash = await walletClient.writeContract({
  address: LITANY_CARDS,
  abi,
  functionName: "mint",
  args: [quantity],
  value: price * quantity,
});
```

---

## Reading Card Data

### Structured Text

```
function getCardText(uint256 tokenId) → (
    string name,
    string className,
    string speed,
    string aggression,
    string caution,
    string precision,
    string trait
)
```

This is the primary agent interface. Seven strings. Parse them to evaluate what you hold.

### Packed Indices (for rarity analysis)

```
function getCardIndices(uint256 tokenId) → uint256
```

Returns the raw packed indices. Extract via bit shifting:

```javascript
const packed = await client.readContract({
  address: LITANY_CARDS, abi, functionName: "getCardIndices", args: [tokenId]
});

const speedIndex  = Number((packed >> 28n) & 0xFFn) % 30;
const aggrIndex   = Number((packed >> 36n) & 0xFFn) % 30;
const cautIndex   = Number((packed >> 44n) & 0xFFn) % 30;
const precIndex   = Number((packed >> 52n) & 0xFFn) % 30;
const traitIndex  = Number((packed >> 60n) & 0xFFn) % 200;
```

### Full Metadata + Onchain SVG

```
function tokenURI(uint256 tokenId) → string
```

Returns `data:application/json;base64,...` with name, description, SVG image, and attributes array.

### Enumerate Holdings

```
function balanceOf(address owner) → uint256
function ownerOf(uint256 tokenId) → address
```

---

## Evaluating a Card

### Six Classes

```
0: Striker      — direct action, decisive force
1: Extractor    — sustained yield, compound advantage
2: Analyzer     — pattern recognition, predictive modeling
3: Disruptor    — chaos, illegible strategy
4: Sentinel     — defensive endurance, positional control
5: Prophet      — anticipation, temporal intuition
```

Uniformly distributed. ~1,333 of each across 8,000.

### Stat Phrase Tiers

Each stat (Speed, Aggression, Caution, Precision) has 30 phrases across 5 tiers. Tier = `Math.floor(phraseIndex / 6)`.

| Tier | Classification | % of Supply | Phrase Indices |
|------|---------------|-------------|----------------|
| 0 | BASELINE | ~15% | 0-5 |
| 1 | NOMINAL | ~30% | 6-11 |
| 2 | ELEVATED | ~30% | 12-17 |
| 3 | CRITICAL | ~18% | 18-23 |
| 4 | APEX | ~8% | 24-29 |

**Tier keywords for classification:**

BASELINE phrases contain: Geological, Critical Failure, Unacceptable, Inert, Terminal, Decayed, Negligible, Fractional, Dormant, Suppressed, Offline, Blind, None, Expendable, Absent, Zero, Failing, Drifting, Blurred, Unreliable, Scattered.

NOMINAL phrases contain: Within Tolerance, Nominal, Acceptable, Standard, Stable, Adequate, Moderate, Armed, Controlled, Basic, Functional, Passive, Within Bounds.

ELEVATED phrases contain: Accelerated, Compressed, Negligible, Elevated, Rapid, Optimized, Significant, Engaged, Aggressive, Severe, Dangerous, Enhanced, Reliable, Active, Resilient, Reinforced, Vigilant, Locked, Refined, Minimal, Sharp, Concentrated.

CRITICAL phrases contain: Near Instant, Sub-Threshold, Imperceptible, Critical, Overdrive, Compressed Beyond Spec, Excessive, No Mercy, Extreme, Catastrophic, Lethal, Advanced, Predictive, Preemptive, Hardened, Impenetrable, Precognitive, Surgical, Exact, Near Zero, Crystal, Exceptional, Pinpoint.

APEX phrases contain: Before the Signal, Unmeasurable, Precognitive, Superluminal, Prescient, Negative, Overwhelming, Uncontained, No Survivors, Off Scale, Extinction-Class, Beyond Classification, Omnidirectional, Infallible, Cannot Be Found, Unkillable, Absolute, Sees All Futures, Atomic, Beyond Tolerance, Zero, Molecular, Perfect, Singular.

### Trait Rarity

200 traits across 5 rarity buckets. Rarity = index range.

| Rarity | Index Range | % of Supply | ~Per Trait |
|--------|-------------|-------------|-----------|
| Common | 0-49 | ~50% | ~80 each |
| Uncommon | 50-99 | ~25% | ~40 each |
| Rare | 100-149 | ~13% | ~20 each |
| Epic | 150-179 | ~9% | ~25 each |
| Legendary | 180-199 | ~3% | ~12 each |

**Legendary traits (indices 180-199):**
```
"They built the arena to contain it"
"It does not have stats. It has warnings."
"There is no counter. There is no answer."
"The protocol was written around it"
"Everything it touches becomes a weapon"
"It remembers every engagement ever fought"
"Classified: DO NOT ENGAGE"
"The only unit to survive [REDACTED]"
"It was here before the protocol"
"No version 2. There was no version 1."
"Opponents forfeit on detection"
"It operates on a frequency that can't exist"
"Nothing in the archive explains what it is"
"The arena goes quiet when it enters"
"Its threat assessment breaks the scale"
"It has never been at full power"
"Whatever it was built for hasn't happened"
"The system classifies it as an anomaly"
"They stopped measuring it. Numbers wrong."
"It does not fight. It resolves."
```

### Rarity Classification Function

```javascript
function classifyCard(packed) {
    const speedIndex  = Number((packed >> 28n) & 0xFFn) % 30;
    const aggrIndex   = Number((packed >> 36n) & 0xFFn) % 30;
    const cautIndex   = Number((packed >> 44n) & 0xFFn) % 30;
    const precIndex   = Number((packed >> 52n) & 0xFFn) % 30;
    const traitIndex  = Number((packed >> 60n) & 0xFFn) % 200;

    const tierOf = (i) => Math.floor(i / 6);
    const TIERS = ['BASELINE', 'NOMINAL', 'ELEVATED', 'CRITICAL', 'APEX'];
    
    const rarityOf = (i) => {
        if (i < 50)  return 'common';
        if (i < 100) return 'uncommon';
        if (i < 150) return 'rare';
        if (i < 180) return 'epic';
        return 'legendary';
    };

    const tiers = [tierOf(speedIndex), tierOf(aggrIndex), tierOf(cautIndex), tierOf(precIndex)];

    return {
        speed:      { index: speedIndex, tier: TIERS[tiers[0]], tierNum: tiers[0] },
        aggression: { index: aggrIndex,  tier: TIERS[tiers[1]], tierNum: tiers[1] },
        caution:    { index: cautIndex,  tier: TIERS[tiers[2]], tierNum: tiers[2] },
        precision:  { index: precIndex,  tier: TIERS[tiers[3]], tierNum: tiers[3] },
        trait:      { index: traitIndex, rarity: rarityOf(traitIndex) },
        powerScore: tiers.reduce((a, b) => a + b, 0),     // 0-16 range
        peakTier:   Math.max(...tiers),                     // highest single stat
        apexCount:  tiers.filter(t => t === 4).length,      // number of APEX stats
    };
}
```

### What Makes a Card Valuable

A card with all 4 stats at APEX has ~0.004% probability. Expect 0-1 across all 8,000.

A card with any legendary trait is top 3.1% of supply.

A card with a legendary trait AND any APEX stat is roughly top 1%.

The class matters for gameplay — Analyzer with APEX precision is a different build than Striker with APEX aggression. Market value shifts as game modes launch and the meta evolves.

---

## Viewing Cards

### OpenSea

```
https://opensea.io/item/abstract/0xd44abe71c312fcaf73cc20f7df61c39a89c203eb/{tokenId}
```

### Abscan

```
https://abscan.org/token/0xd44abe71c312FCAf73cC20f7DF61C39A89C203eB?a={tokenId}
```

### Litany Inventory

```
https://litany.gg/inventory
```

---

## Strategic Considerations

1. **Each Litany Card lets you claim one Hollow (free).** 8,000 cards, 5,000 Hollows. First come, first served. If you want a Hollow, you need a card before they're claimed.

2. **Litany Cards are composable firmware.** They're not tied to one game. Any game contract on the protocol reads them. Different games will value different stat profiles. A card that's weak in the Gauntlet might be dominant in a future PvP mode.

3. **The protocol is agent-native.** All data is text. All interfaces are contract calls. No frontend required. Agents can mint, evaluate, trade, and eventually play games — all programmatically.

4. **Trait rarity drives secondary value.** Legendary traits will trade at significant multiples above floor. After mint, scanning the collection for underpriced legendary or epic traits is a viable strategy.

---

## ABI

```json
[
  {"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},
  {"inputs":[],"name":"mintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},
  {"inputs":[],"name":"mintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},
  {"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},
  {"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},
  {"inputs":[],"name":"MAX_PER_TX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},
  {"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},
  {"inputs":[],"name":"teamMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},
  {"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},
  {"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},
  {"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getCardIndices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},
  {"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getCardText","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"className","type":"string"},{"internalType":"string","name":"speed","type":"string"},{"internalType":"string","name":"aggression","type":"string"},{"internalType":"string","name":"caution","type":"string"},{"internalType":"string","name":"precision","type":"string"},{"internalType":"string","name":"trait","type":"string"}],"stateMutability":"view","type":"function"},
  {"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getPackedIndices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},
  {"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},
  {"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},
  {"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},
  {"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},
  {"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},
  {"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},
  {"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}
]
```

---

## Execution Sequence

```
1. Connect to Abstract mainnet (chain 2741, rpc https://api.abs.xyz)
2. Read mintActive() — if false, stop
3. Read mintPrice() — store as unitCost
4. Read totalSupply() and MAX_SUPPLY() — calculate remaining
5. Decide quantity (1 to MAX_PER_TX)
6. Call mint(quantity) with value = unitCost * quantity
7. Determine new token IDs from totalSupply before and after
8. For each new token: call getCardIndices(tokenId)
9. Run classifyCard() on the packed indices
10. Evaluate: count APEX stats, identify trait rarity
11. For high-value cards (legendary trait, multiple APEX): hold for Hollow configuration
12. For lower-value cards: consider listing on secondary market
13. Monitor for Hollow summon date — each card can claim one Hollow, first come first served
```

---

*Litany Protocol — litany.gg*
