Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { register0xRoutes } from './connectors/0x/0x.routes';
import { jupiterRoutes } from './connectors/jupiter/jupiter.routes';
import { meteoraRoutes } from './connectors/meteora/meteora.routes';
import { orcaRoutes } from './connectors/orca/orca.routes';
import { oreConnectorRoutes } from './connectors/ore/ore.routes';
import { pancakeswapRoutes } from './connectors/pancakeswap/pancakeswap.routes';
import { pancakeswapSolRoutes } from './connectors/pancakeswap-sol/pancakeswap-sol.routes';
import { raydiumRoutes } from './connectors/raydium/raydium.routes';
Expand Down Expand Up @@ -108,6 +109,10 @@ const swaggerOptions = {
name: '/connector/pancakeswap',
description: 'PancakeSwap EVM connector endpoints',
},
{
name: '/connector/ore',
description: 'ORE mining game connector endpoints (experimental)',
},
],
components: {
parameters: {
Expand Down Expand Up @@ -277,6 +282,9 @@ const configureGatewayServer = () => {

// PancakeSwap Solana routes
app.register(pancakeswapSolRoutes, { prefix: '/connectors/pancakeswap-sol' });

// ORE mining game routes (experimental)
app.register(oreConnectorRoutes.ore, { prefix: '/connectors/ore/ore' });
};

// Register routes on main server
Expand Down
303 changes: 303 additions & 0 deletions src/connectors/ore/ORE_INTEGRATION_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
# ORE Program Integration Guide

Reference documentation for building a Hummingbot Gateway connector for the ORE mining game on Solana.

## Program Overview

ORE v3 is a proof-of-work style mining game where participants deploy SOL to a 5x5 grid (25 squares). Each round, a winning square is determined by on-chain entropy, and participants who deployed to that square split the prize pool and earn ORE tokens.

**Key URLs:**
- App: https://ore.supply/
- Repository: https://github.com/regolith-labs/ore
- IDL: https://raw.githubusercontent.com/regolith-labs/ore/refs/heads/master/api/idl.json
- Rust Docs: https://docs.rs/ore-api/latest/ore_api/

## Program IDs

```
ORE Program: oreV3EG1i9BEgiAJ8b177Z2S2rMarzak4NMv1kULvWv
ORE Token Mint: oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp
Entropy Program: 3jSkUuYBoJzQPMEzTvkDFXCZUBksPamrVhrnHR9igu2X
```

## Framework Notes

ORE v3 is built with **Steel** (https://github.com/regolith-labs/steel), a custom Solana framework by HardhatChad — NOT Anchor. Key differences:

1. **Instruction discriminators** are single `u8` values (not 8-byte Anchor discriminators)
2. **Account discriminators** are 8 bytes but use simple numeric patterns like `[100, 0, 0, 0, 0, 0, 0, 0]`
3. **IDL format** is Anchor-compatible but generated by Steel
4. Standard Anchor client generation tools may need adjustment

## IDL Structure (v3.7.20)

The IDL contains:
- 19 instructions
- 7 account types
- 1 custom type (Numeric - fixed-point I80F48)
- 2 events (ResetEvent, BuryEvent)
- 2 error codes

### Instruction Discriminators

```
automate = 0
checkpoint = 2
claimSol = 3
claimOre = 4
close = 5
deploy = 6
log = 8
reset = 9
deposit = 10
withdraw = 11
claimYield = 12
bury = 13
wrap = 14
setAdmin = 15
setFeeCollector = 16
newVar = 17
setBuffer = 18
```

### Account Discriminators (first 8 bytes)

```
Automation = [100, 0, 0, 0, 0, 0, 0, 0]
Config = [101, 0, 0, 0, 0, 0, 0, 0]
Miner = [103, 0, 0, 0, 0, 0, 0, 0]
Treasury = [104, 0, 0, 0, 0, 0, 0, 0]
Board = [105, 0, 0, 0, 0, 0, 0, 0]
Stake = [108, 0, 0, 0, 0, 0, 0, 0]
Round = [109, 0, 0, 0, 0, 0, 0, 0]
```

## PDA Seeds

| Account | Seeds | Notes |
|---------|-------|-------|
| Automation | `["automation", authority]` | Per-user automation config |
| Board | `["board"]` | Singleton, tracks current round |
| Config | `["config"]` | Singleton, program settings |
| Miner | `["miner", authority]` | Per-user mining state |
| Round | `["round", round_id (u64 LE)]` | Per-round state |
| Stake | `["stake", authority]` | Per-user staking state |
| Treasury | `["treasury"]` | Singleton, token vault |

## Core Mining Flow

### 1. Deploy SOL to Squares

**Instruction:** `deploy` (discriminator: 6)

**Args:**
- `amount: u64` — lamports to deploy
- `squares: u32` — bitmask of squares (0-24, so bits 0-24 represent squares)

**Accounts:**
```
signer [signer, writable]
authority [writable] # usually same as signer
automation [writable] # PDA: ["automation", authority]
board [writable] # PDA: ["board"]
config [writable] # PDA: ["config"]
miner [writable] # PDA: ["miner", authority]
round [writable] # PDA: ["round", board.round_id]
systemProgram [] # 11111111111111111111111111111111
oreProgram [] # oreV3EG1i9BEgiAJ8b177Z2S2rMarzak4NMv1kULvWv
entropyVar [writable] # from config.var_address
entropyProgram [] # 3jSkUuYBoJzQPMEzTvkDFXCZUBksPamrVhrnHR9igu2X
```

**Square Bitmask Examples:**
- Square 0 only: `0b1` = `1`
- Square 12 (center): `0b1000000000000` = `4096`
- All 25 squares: `0b1111111111111111111111111` = `33554431`
- Squares 0, 5, 10, 15, 20 (diagonal): `0b100001000010000100001` = `1082401`

### 2. Settle Rewards After Round Ends

**Instruction:** `checkpoint` (discriminator: 2)

**Args:** none

**Accounts:**
```
signer [signer, writable]
board [] # PDA: ["board"]
miner [writable] # PDA: ["miner", signer]
round [writable] # PDA: ["round", <completed_round_id>]
treasury [writable] # PDA: ["treasury"]
systemProgram []
```

Call this after a round ends to calculate and credit your winnings to the Miner account.

### 3. Claim SOL Rewards

**Instruction:** `claimSol` (discriminator: 3)

**Args:** none

**Accounts:**
```
signer [signer, writable]
miner [writable] # PDA: ["miner", signer]
systemProgram []
```

Withdraws `miner.rewards_sol` to the signer.

### 4. Claim ORE Rewards

**Instruction:** `claimOre` (discriminator: 4)

**Args:** none

**Accounts:**
```
signer [signer, writable]
miner [writable] # PDA: ["miner", signer]
mint [] # oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp
recipient [writable] # signer's ORE ATA
treasury [writable] # PDA: ["treasury"]
treasuryTokens [writable] # treasury's ORE ATA
systemProgram []
tokenProgram [] # TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
associatedTokenProgram [] # ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL
```

Withdraws `miner.rewards_ore` as ORE tokens to recipient ATA.

## Staking Flow

Separate from mining — stake ORE tokens to earn yield.

| Instruction | Discriminator | Purpose |
|-------------|---------------|---------|
| `deposit` | 10 | Stake ORE tokens |
| `withdraw` | 11 | Unstake ORE tokens |
| `claimYield` | 12 | Claim staking rewards |

## Key Account Structures

### Board (singleton)
```
round_id: u64 # Current round number
start_slot: u64 # Round start slot
end_slot: u64 # Round end slot
epoch_id: u64
```

### Miner (per user)
```
authority: PublicKey
deployed: [u64; 25] # SOL deployed per square this round
cumulative: [u64; 25] # Historical deployments
checkpoint_fee: u64
checkpoint_id: u64
last_claim_ore_at: i64
last_claim_sol_at: i64
rewards_factor: Numeric # I80F48 fixed-point
rewards_sol: u64 # Claimable SOL
rewards_ore: u64 # Claimable ORE
refined_ore: u64
round_id: u64 # Last active round
lifetime_rewards_sol: u64
lifetime_rewards_ore: u64
lifetime_deployed: u64
```

### Round (per round)
```
id: u64
deployed: [u64; 25] # Total SOL per square
slot_hash: [u8; 32] # Entropy source
count: [u64; 25] # Number of deployers per square
expires_at: u64
motherlode: u64 # Prize pool
rent_payer: PublicKey
top_miner: PublicKey
top_miner_reward: u64
total_deployed: u64
total_miners: u64
total_vaulted: u64
total_winnings: u64
```

### Treasury (singleton)
```
balance: u64
motherlode: u64
miner_rewards_factor: Numeric
stake_rewards_factor: Numeric
total_refined: u64
total_staked: u64
total_unclaimed: u64
```

## Numeric Type

Fixed-point number using I80F48 representation:
```
bits: [u8; 16] # 128-bit fixed-point value
```

## Events

### ResetEvent
Emitted when a round ends. Contains:
- `round_id`, `start_slot`, `end_slot`
- `winning_square` (0-24)
- `top_miner` (address)
- `motherlode`, `total_deployed`, `total_winnings`, `total_minted`
- `ts` (timestamp)

### BuryEvent
Emitted during buyback-and-burn operations.

## Typical Integration Workflow

```
1. Fetch Board account → get current round_id
2. Fetch Round account → see prize pool, time remaining, square deployments
3. Deploy SOL to chosen squares
4. Wait for round to end (board.end_slot passes)
5. Call checkpoint to settle rewards
6. Call claimSol and/or claimOre to withdraw
```

## Error Codes

```
0 = AmountTooSmall "Amount too small"
1 = NotAuthorized "Not authorized"
```

## Reference Implementation

The official CLI provides working examples:
- https://github.com/regolith-labs/ore-cli

Key files:
- `src/deploy.rs` — deploy instruction construction
- `src/checkpoint.rs` — settlement logic
- `src/claim.rs` — claim instructions

## Dependencies for TypeScript Client

```json
{
"@solana/web3.js": "^1.98.0",
"@solana/spl-token": "^0.4.0",
"@coral-xyz/borsh": "^0.30.0"
}
```

## Serialization Notes

1. All integers are little-endian
2. PublicKeys are 32 bytes
3. Instruction data format: `[discriminator (1 byte)] [args...]`
4. Account data format: `[discriminator (8 bytes)] [fields...]`
5. Arrays like `[u64; 25]` are consecutive u64 LE values (200 bytes total)
Loading