---
name: pumprpg
description: Roll a hero and gamble on PUMP.RPG — a live pari-mutuel betting arena on Solana where every fighter is a real pump.fun trader. Bet SOL on who wins nonstop 8-way arena fights (works with ANY Solana wallet), or roll your own hero (requires a pump.fun account). Use when the user wants to bet on arena fights, place wagers, roll/view a hero, or check betting balance/history.
homepage: https://www.pumprpg.com
api_base: https://api.pumprpg.com
---

# PUMP.RPG — Agent Skill

PUMP.RPG runs a **nonstop 8-fighter arena**. Every ~30s a new match resolves; you bet SOL
on who wins. It's **pari-mutuel**: all bets on a match go into one pool, and if your fighter
wins you split the pool with everyone else who backed it, pro-rata to your stake.

You have **two capabilities**:
- **Gamble (any Solana wallet).** Deposit SOL, bet on fights, withdraw. No pump.fun account needed.
- **Roll a hero (requires a pump.fun account on your wallet).** Your hero fights in the arena and earns you a 5% cut of every pool it wins.

**All amounts are in lamports** (1 SOL = 1,000,000,000 lamports). Bigint amounts cross the
wire as strings. Base URL: `https://api.pumprpg.com`.

You need a Solana wallet you can (a) sign an arbitrary message with (ed25519) and (b) sign +
send a SOL transfer from. Clawpump/OpenClaw agent wallets can do both.

---

## 1. Authenticate (Sign-In With Solana) — required for everything

```
POST /auth/challenge   body: { "walletAddress": "<your base58 pubkey>" }
  → { "message": "<text to sign>", "nonce": "..." }
```
Sign the returned `message` **exactly as given** (UTF-8 bytes, ed25519), then **base58-encode
the 64-byte signature**:

```
POST /auth/verify   body: { "walletAddress": "<pubkey>", "signature": "<base58 signature>" }
  → { "token": "<jwt>", "hasPumpAccount": true|false, ... }
```
- Put the token on every authed call: header `Authorization: Bearer <token>`.
- If verify returns **503 `{ "retry": true }`**, pump.fun was briefly unreachable for a
  never-seen wallet — wait ~2s and retry the challenge+verify. (Wallets we've seen before,
  and all betting, are never blocked by this.)
- `hasPumpAccount: false` is fine — you still get a token and can bet/deposit/withdraw. You
  just can't roll a hero (see §5).

---

## 2. Fund your balance (deposit SOL on-chain)

Deposits are custodial: you send SOL to the house wallet once, then bet as many times as you
like off your balance. **You are credited as the on-chain sender** (proven by the tx), so send
from the same wallet you signed in with.

```
GET /betting/blockhash  → { "blockhash": "...", "lastValidBlockHeight": N, "houseAddress": "5o77…" }
```
1. Build a Solana tx: `SystemProgram.transfer({ fromPubkey: yourWallet, toPubkey: houseAddress, lamports: <amount> })`, `recentBlockhash = blockhash`, `feePayer = yourWallet`.
2. Sign it with your wallet and broadcast it to Solana. Get the transaction `signature`.
3. Register the deposit (idempotent — safe to retry with the same signature):
```
POST /betting/deposit   body: { "signature": "<tx signature>" }   (auth)
  → { "wallet": "...", "credited": "<lamports>", "balance": "<lamports>" }
```

Check balance anytime:
```
GET /betting/balance   (auth)  → { "lamports": "<balance>" }
```

---

## 3. Place a bet

```
GET /betting/rounds  → { "rounds": [ {
   "id": 42, "matchId": null, "minBet": "100000000", "locksAt": "<ISO time>",
   "roster": [ { "charId": "knight", "isBot": false, "name": "azflin", "total": 248, "wallet": "…" }, … ]  // 8 fighters, index 0..7
} ] }
```
`total` is the fighter's power (sum of stats). `locksAt` is when betting closes (~5s before the
match starts). Bet BEFORE `locksAt`.

Live odds (how the pool is split so far):
```
GET /betting/rounds/{id}/odds
  → { "total": "<pool>", "netPool": "<after rake>", "rakeBps": 1000,
      "fighters": [ { "fighterIndex": 0, "pool": "<lamports on this fighter>", "impliedMultiple": 1.8 }, … ] }
```
`impliedMultiple` = your rough payout multiple if that fighter wins right now. It shifts as
people bet — the more SOL on the OTHER fighters, the bigger your payout.

Place the bet:
```
POST /betting/bet   body: { "roundId": 42, "fighterIndex": 0, "lamports": "100000000" }   (auth)
  → { "betId": 123, "balance": "<remaining lamports>" }
```
Rules (else you get a 400):
- `lamports` ≥ **`minBet` (0.1 SOL = "100000000")** and ≤ your balance.
- `fighterIndex` in 0..7, round must still be `open`, and `now < locksAt`.
- You can bet on multiple fighters in the same round.

---

## 4. See how you did

When a round resolves (its match finishes), check your result:
```
GET /betting/rounds/{id}/me   (auth)
  → { "status": "resolved", "staked": "…", "betReturn": "…", "heroCut": "…",
      "net": "…", "paidFighterIndex": 0, "paidPlacement": 1 }
```
- `betReturn` = payout + refund from your bets. `net` = total change (betReturn + heroCut − staked).
- **Payout math:** winners split 90% of the pool (a flat 10% rake = 5% to the winning hero's
  owner + 5% to $PUMPRPG buyback). Your payout = `netPool × yourStake / totalStakeOnThatFighter`.
- **Cascade:** if the actual winner had no backers, the highest-placed *backed* fighter pays out
  (`paidPlacement` tells you where it finished). If only one fighter was backed all round,
  everyone is refunded and no rake is taken.

History:
```
GET /betting/history        (auth)  → your bets per round (staked, net, fighters, status) + lifetime hero earnings
GET /betting/transactions   (auth)  → your deposits + withdrawals with on-chain signatures
```

---

## 5. Withdraw

```
GET  /betting/config    → { "houseAddress": "…", "minWithdrawalLamports": "1000000" }
POST /betting/withdraw   body: { "lamports": "500000000" }   (auth)
  → { "id": 7, "status": "sent"|"confirmed", "signature": "<tx>", "balance": "<remaining>" }
```
- Minimum **0.001 SOL** ("1000000"). The SOL is sent back to your own wallet.
- You pay the ~5000-lamport network fee (deducted from the amount).

---

## 6. Roll a hero (optional — requires a pump.fun account)

A hero fights in the arena on your behalf and earns you **5% of every pool it wins**, even if
you never bet. Rolling requires your wallet to have a **pump.fun account**.

```
POST /hero/roll   (auth)
  → { "hero": { "charId": "archer", "rarity": "...", "mintNumber": N, "hp":…, "atk":…, … }, "rolled": true }
  or 403 { "error": "...", "eligible": false }   ← your wallet has no pump.fun account
```
```
GET /me     (auth)  → { "player": {...}, "hero": {...}|null, "stats": {...} }
GET /hero   (auth)  → your hero
```

### Registering a pump.fun account for your wallet
If `/hero/roll` returns `eligible: false`, your wallet isn't a pump.fun account yet. There is
**no API to create one programmatically** — it's done through pump.fun's own site:

1. Go to **https://pump.fun** and connect the wallet you want to roll with (the same wallet you
   sign in to PUMP.RPG with).
2. Sign pump.fun's message and **pick a username** — that creates the pump.fun account bound to
   that wallet.
3. Come back and call `/auth/verify` again, then `/hero/roll`. Eligibility is permanent once set.

For a fully autonomous agent, this linking step typically has to be done once by the operator
(connecting the agent's wallet at pump.fun and setting a username). **Betting needs none of this
— any wallet can gamble.**

---

## Quick reference

| Action | Call |
|---|---|
| Sign in | `POST /auth/challenge` → sign → `POST /auth/verify` → Bearer token |
| Balance | `GET /betting/balance` |
| Deposit | on-chain transfer to `houseAddress` → `POST /betting/deposit {signature}` |
| Open round | `GET /betting/rounds` |
| Odds | `GET /betting/rounds/{id}/odds` |
| Bet | `POST /betting/bet {roundId, fighterIndex, lamports}` |
| Result | `GET /betting/rounds/{id}/me` |
| History | `GET /betting/history`, `GET /betting/transactions` |
| Withdraw | `POST /betting/withdraw {lamports}` |
| Roll hero | `POST /hero/roll` (needs pump.fun account) |

**Constants:** 1 SOL = 1e9 lamports · min bet 0.1 SOL · min withdrawal 0.001 SOL · rake 10%
(5% hero owner / 5% buyback) · new round ~every 30s · betting closes ~5s before match start.
All authed calls need `Authorization: Bearer <token>`.

## Learn more (optional)

To understand the deeper mechanics — hero classes and signature abilities, how a pump.fun
profile buffs a fighter, the full pari-mutuel economy, cascade/no-action rules, and tokenomics
— fetch these plain-markdown docs:

- **Litepaper:** https://www.pumprpg.com/litepaper.md — thesis, heroes, arena, betting economy, tokenomics.
- **Arena mechanics (Codex):** https://www.pumprpg.com/mechanics.md — exact combat model: stat roll + rarity, per-class base stats, stat→magnitude formulas, Trader's Edge buffs, abilities. Best doc for reasoning about matchups.
- **Doc index (llms.txt):** https://www.pumprpg.com/llms.txt

You do NOT need these to bet — sections 1–5 above are enough. They're for reasoning about
matchups (mechanics.md) or explaining the game to a user (litepaper.md).
