Skip to main content

tengu_api/
consts.rs

1//! PDA seeds and constants.
2
3use solana_program::pubkey::Pubkey;
4use solana_program::pubkey;
5
6pub const ADMIN_ADDRESS: Pubkey = pubkey!("DEvGq2WVuA3qkSCtwwuMYThY4onkJunEHSAxU5cieph8");
7/// Authority for buyback (swap treasury SOL → DOJO, burn). Same as admin.
8pub const BUYBACK_AUTHORITY: Pubkey = ADMIN_ADDRESS;
9pub const FEE_COLLECTOR: Pubkey = pubkey!("FEEjHM2DoFu6UifSBmrxTQ6X2KkWQ1dbPXASCtdLUdnx");
10/// SOL payment split: fee collector gets this share (basis points). 1000 = 10%.
11pub const SOL_SPLIT_FEE_BPS: u64 = 1000;
12/// SOL payment split: staking pool gets this share (basis points). 3000 = 30%.
13pub const SOL_SPLIT_STAKING_BPS: u64 = 3000;
14/// SOL payment split: treasury (buybacks) gets this share (basis points). 6000 = 60%.
15pub const SOL_SPLIT_TREASURY_BPS: u64 = 6000;
16
17pub const TASK_VERIFIER: Pubkey = pubkey!("tASK7746ambmkkTvqtyCehd3F56X4VJpr9GCPh4bUmu");
18/// $DOJO SPL token mint. Matches ui constants.ts DOJO_MINT.
19pub const DOJO_MINT: Pubkey = pubkey!("shaRdWvYzRQecQUxxzytUUGexXJsjr3cMq1VRkBiCZF");
20/// Wrapped SOL mint. Used for treasury wSOL ATA in buyback.
21pub const WSOL_MINT: Pubkey = pubkey!("So11111111111111111111111111111111111111112");
22/// Jupiter swap program for buyback (SOL → DOJO).
23pub const SWAP_PROGRAM: Pubkey = pubkey!("JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4");
24
25/// Dojos Genesis Token (DGT) group mint. Soulbound mints have TokenGroupMember.group == this.
26pub const DGT_GROUP: Pubkey = pubkey!("DGT1rCDvLYEmasQJ2M9naJ2iakFrsS4Vn4XvmNWJREje");
27
28/// Seeker Genesis Token (SGT) group from Solana Mobile. Used to detect Seeker users. Matches ui SGT_GROUP.
29pub const SGT_GROUP: Pubkey = pubkey!("GT22s89nU4iWFkNXj1Bw6uYhJJWDRPpShHt4Bk8f99Te");
30
31pub const CONFIG: &[u8] = b"config";
32pub const GAME: &[u8] = b"game";
33pub const DOJO: &[u8] = b"dojo";
34pub const SHOGUN: &[u8] = b"shogun";
35pub const BARRACKS: &[u8] = b"barracks";
36pub const BATTLE: &[u8] = b"battle";
37pub const FORGE: &[u8] = b"forge";
38pub const TASKS: &[u8] = b"tasks";
39pub const TREASURY: &[u8] = b"treasury";
40pub const REFERRAL: &[u8] = b"referral";
41pub const PRESTIGE: &[u8] = b"prestige";
42/// Seeker: one account per SGT mint that has claimed the Seeker task (anti-Sybil).
43pub const SEEKER: &[u8] = b"seeker";
44pub const STAKE: &[u8] = b"stake";
45/// Prestige levels for fodder (1–6). Index = collection_index * PRESTIGE_LEVELS + (prestige - 1).
46pub const PRESTIGE_LEVELS: usize = 6;
47
48pub const ED25519_SIGNATURE_OFFSETS_START: usize = 2;
49pub const ED25519_SIGNATURE_OFFSETS_SIZE: usize = 14;
50pub const ED25519_DATA_START: usize = ED25519_SIGNATURE_OFFSETS_START + ED25519_SIGNATURE_OFFSETS_SIZE;
51pub const ED25519_PUBKEY_SIZE: usize = 32;
52pub const ED25519_SIGNATURE_SIZE: usize = 64;
53
54/// Solana: ~0.4s per slot. Ore/chakra/cooldowns use Solana slots.
55pub const SECONDS_PER_SLOT: f64 = 0.4;
56/// Slots in 24h (86400 / 0.4 ≈ 216000).
57pub const ONE_DAY_SLOTS: u64 = 216_000;
58/// Fren Pet S2P: linear refund of staked DOJO over this many days ([docs](https://docs.frenpet.xyz/stake)).
59pub const STAKE_VESTING_DAYS: u64 = 30;
60/// Slot length of the S2P vesting window (`STAKE_VESTING_DAYS` × [`ONE_DAY_SLOTS`]).
61pub const STAKE_VESTING_SLOTS: u64 = STAKE_VESTING_DAYS * ONE_DAY_SLOTS;
62/// Default halving period when `set_genesis_slot` passes 0 for halving (28 × [`ONE_DAY_SLOTS`]).
63pub const DEFAULT_HALVING_PERIOD_SLOTS: u64 = 28 * ONE_DAY_SLOTS;
64pub const CHAKRA_MAX: u64 = ONE_DAY_SLOTS;
65/// Chakra granted per dine tier: 24h, 48h, 72h.
66pub const CHAKRA_24H: u64 = ONE_DAY_SLOTS;
67pub const CHAKRA_48H: u64 = 2 * ONE_DAY_SLOTS;
68pub const CHAKRA_72H: u64 = 3 * ONE_DAY_SLOTS;
69/// Ore = (spirit_power * slots_elapsed) / ORE_DIVISOR. 200 = 0.5x vs Ninja (Solana 2x faster).
70pub const ORE_DIVISOR: u64 = 200;
71/// Pool-split: raw $DOJO emission per slot (6 decimals). Hyper Ninja: 1000/block × 8640 blocks/day = 8.64M/day; Solana 216k slots/day → 40/slot.
72pub const EMISSION_RAW_PER_SLOT_BASE: u64 = 40_000_000;
73pub const DOJO_DECIMALS: u8 = 6;
74/// One $DOJO token, denominated in raw units (6 decimals).
75pub const ONE_DOJO: u64 = 10u64.pow(DOJO_DECIMALS as u32);
76
77pub const SLOTS_PER_LEVEL: u64 = 3;
78pub const MAX_BARRACKS_SLOTS: usize = 12;
79/// Max total fodder (sum of fodder_counts) before recruit. Must reforge to free space.
80pub const MAX_FODDER_TOTAL: u64 = 200;
81
82pub const STARTER_TICKET_PRICE: u64 = 1_000_000_000;
83pub const RECRUIT_SOL_PRICE: u64 = 100_000_000;
84
85/// Base cost (first dine for this shogun). 150/300/450 shards.
86pub const DINE_COST_24H: u64 = 150_000_000;
87pub const DINE_COST_48H: u64 = 300_000_000;
88pub const DINE_COST_72H: u64 = 450_000_000;
89
90/// Escalated cost (second+ dine for this shogun). 195/390/585 shards.
91pub const DINE_COST_24H_ESCALATED: u64 = 195_000_000;
92pub const DINE_COST_48H_ESCALATED: u64 = 390_000_000;
93pub const DINE_COST_72H_ESCALATED: u64 = 585_000_000;
94
95pub const BARRACKS_COST_1_2_SHARDS: u64 = 50_000_000;
96pub const BARRACKS_COST_1_2_SOL: u64 = 10_000_000;
97pub const BARRACKS_COST_2_3_SHARDS: u64 = 300_000_000;
98pub const BARRACKS_COST_2_3_SOL: u64 = 100_000_000;
99pub const BARRACKS_COST_3_4: u64 = 8_000_000_000;
100
101/// 1→2: 0.1 SOL.
102pub const FORGE_COST_1_2: u64 = 100_000_000;
103/// 2→3: 1 SOL.
104pub const FORGE_COST_2_3: u64 = 1_000_000_000;
105/// 3→4: 2 SOL.
106pub const FORGE_COST_3_4: u64 = 2_000_000_000;
107/// 4→5: 5 SOL.
108pub const FORGE_COST_4_5: u64 = 5_000_000_000;
109/// 5→6: 12 SOL.
110pub const FORGE_COST_5_6: u64 = 12_000_000_000;
111/// 6→7: 21 SOL (max level).
112pub const FORGE_COST_6_7: u64 = 21_000_000_000;
113
114/// 1→2: no cooldown (unused; we use _2_3 for level 2).
115pub const FORGE_COOLDOWN_1_2: u64 = 0;
116/// 2→3: no cooldown after 1→2; 30 min after 2→3 (level 3 uses _3_4).
117pub const FORGE_COOLDOWN_2_3: u64 = 0;
118/// 3→4: 30 min in slots (1800s / 0.4 = 4500). Cooldown after 2→3.
119pub const FORGE_COOLDOWN_3_4: u64 = 4_500;
120/// 4→5: 90 min in slots (5400s / 0.4 = 13500). Cooldown after 3→4.
121pub const FORGE_COOLDOWN_4_5: u64 = 13_500;
122/// 5→6: 180 min in slots (10800s / 0.4 = 27000). Cooldown after 4→5.
123pub const FORGE_COOLDOWN_5_6: u64 = 27_000;
124/// 6→7: 300 min in slots (18000s / 0.4 = 45000). Cooldown after 5→6 (max level).
125pub const FORGE_COOLDOWN_6_7: u64 = 45_000;
126
127/// Same as ONE_DOJO. Speed-up forge: cost per minute = remaining minutes (Ninja decay).
128pub const SHARDS_RAW_PER_UNIT: u64 = ONE_DOJO;
129
130// Leveling: cost = 200 + 800*(level-1). Capped at 100.
131pub const LEVEL_UP_COST_BASE: u64 = 200_000_000;   // 200 shards raw
132pub const LEVEL_UP_COST_INCREMENT: u64 = 800_000_000; // 800 shards raw per level
133pub const MAX_SHOGUN_LEVEL: u64 = 100;
134
135pub const SP_N: u64 = 10;   // 1x
136pub const SP_R: u64 = 20;   // 2x
137pub const SP_SR: u64 = 80;  // 8x
138pub const SP_SSR: u64 = 200; // 20x
139pub const SP_UR: u64 = 600; // 60x
140
141pub const DROP_N: u64 = 541;
142pub const DROP_R: u64 = 324;
143pub const DROP_SR: u64 = 108;
144pub const DROP_SSR: u64 = 22;
145pub const DROP_UR: u64 = 5;
146
147pub const RECRUITMENT_TICKET_REWARD_1: u64 = 1;
148pub const RECRUITMENT_TICKET_REWARD_2: u64 = 2;
149pub const RECRUITMENT_TICKET_REWARD_3: u64 = 3;
150pub const RECRUITMENT_TICKET_REWARD_4: u64 = 4;
151pub const RECRUITMENT_TICKET_REWARD_5: u64 = 5;
152pub const RECRUITMENT_TICKET_REWARD_6: u64 = 6;
153pub const RECRUITMENT_TICKET_REWARD_7: u64 = 7;
154pub const RECRUITMENT_TICKET_REWARD_8: u64 = 8;
155pub const RECRUITMENT_TICKET_REWARD_9: u64 = 9;
156pub const RECRUITMENT_TICKET_REWARD_10: u64 = 10;
157pub const RECRUITMENT_TICKET_REWARD_11: u64 = 11;
158pub const RECRUITMENT_TICKET_REWARD_12: u64 = 12;
159pub const RECRUITMENT_TICKET_REWARD_13: u64 = 13;
160pub const RECRUITMENT_TICKET_REWARD_15: u64 = 15;
161
162pub const ELEMENT_RARITY_REWARD_N: u64 = 1;
163pub const ELEMENT_RARITY_REWARD_R: u64 = 1;
164pub const ELEMENT_RARITY_REWARD_SR: u64 = 2;
165pub const ELEMENT_RARITY_REWARD_SSR: u64 = 5;
166pub const ELEMENT_RARITY_REWARD_UR: u64 = 20;
167
168pub const DAILY_TASK_START: u64 = 17;
169
170pub const CLAIM_TASK_PREFIX: &[u8] = b"dojos:claim_task:";
171pub const ELEMENT_RARITY_SET_SIZE: usize = 3;
172
173// Task ID layout:
174// 0–7: On-chain tasks (recruit, dine, forge Lv.2)
175// 8: Collection rewards (3 ninjas same element+rarity; 25 combos)
176// 9–16: Off-chain tasks (signature required)
177// 17–24: Daily resettable tasks (signature, bits reset daily)
178// 33–35: Forge Lv.3, Lv.4, Lv.5
179pub const TASK_FORGE_3: u64 = 33;
180pub const TASK_FORGE_4: u64 = 34;
181pub const TASK_FORGE_5: u64 = 35;
182pub const FORGE_3_REWARD: u64 = 2;
183pub const FORGE_4_REWARD: u64 = 5;
184pub const FORGE_5_REWARD: u64 = 10;
185pub const FORGE_6_REWARD: u64 = 15;
186pub const FORGE_7_REWARD: u64 = 20;
187
188pub const MAX_SUPPLY: u64 = ONE_DOJO * 1_000_000_000;
189
190// PvP battles (Fren Pet–aligned timings; [`SECONDS_PER_SLOT`] ≈ 0.4 → slots = seconds × 10 / 4)
191/// Min slots between initiating battles (30 minutes).
192pub const BATTLE_COOLDOWN_SLOTS: u64 = (30 * 60 * 10) / 4;
193/// Target cannot be attacked if targeted by a duel within this window (1 hour).
194pub const BATTLE_TARGET_IMMUNITY_SLOTS: u64 = (60 * 60 * 10) / 4;
195/// Max PvP duels initiated per dojo per 24h rolling window.
196pub const BATTLE_MAX_DUELS_PER_24H: u64 = 32;
197/// Point transfer cap per battle (0.5% = 50 bps).
198pub const BATTLE_TRANSFER_BPS: u64 = 50;
199/// Fren “hibernated target”: caps on **defender** BP use 1% (100 bps) when defender’s champion has **0 chakra** (must dine to stay “fed”).
200pub const BATTLE_TRANSFER_DEFENDER_DEPLETED_BPS: u64 = 100;
201/// Attacker BP below this uses Fren “My pet has less than 10k points” (not full odds).
202pub const BATTLE_POINTS_LOW_THRESHOLD: u64 = 10_000;
203/// Fren Pet: default cached AP/DP on new [`crate::state::Battle`] accounts.
204pub const BATTLE_DEFAULT_AP: u64 = 10;
205pub const BATTLE_DEFAULT_DP: u64 = 10;
206/// Starting PvP battle score (matches [`BATTLE_POINTS_LOW_THRESHOLD`]).
207pub const BATTLE_DEFAULT_BATTLE_POINTS: u64 = BATTLE_POINTS_LOW_THRESHOLD;
208/// Champion barracks slot unset sentinel (`u64::MAX`).
209pub const BATTLE_CHAMPION_SLOT_UNSET: u64 = u64::MAX;
210/// Fren: max points attacker can win when attacker BP is below [`BATTLE_POINTS_LOW_THRESHOLD`] (also capped by 0.5% of defender’s BP).
211pub const BATTLE_LOW_WIN_CAP: u64 = 100;
212/// Min slots between champion changes (12 hours).
213pub const CHAMPION_CHANGE_COOLDOWN_SLOTS: u64 = (12 * 60 * 60 * 10) / 4;
214/// After initiating a battle, champion cannot change until this elapses (same as battle cooldown).
215pub const CHAMPION_LOCK_AFTER_BATTLE_SLOTS: u64 = BATTLE_COOLDOWN_SLOTS;
216
217/// Stake → XP: `(balance_raw * delta_slots) / XP_STAKE_DIVISOR`. ~1000 XP per 1 DOJO·day.
218pub const XP_STAKE_DIVISOR: u128 = 216_000_000_000;
219
220/// Bps of **battle points won** (`points_moved`) granted as reward XP (same `dojo.xp` as stake → `claim_xp_rewards`).
221/// Fren-style: reward weight scales with transfer size, not a flat win. `10_000` = 1:1; `1000` ≈ old flat 50 when ~500 BP moves.
222pub const XP_BATTLE_BP_TO_REWARD_BPS: u64 = 1000;
223/// Per shogun recruited (tickets or SOL path); total = count × this.
224pub const XP_RECRUIT_PER_PULL: u64 = 25;
225/// One-time per successful forge level upgrade.
226pub const XP_FORGE_UPGRADE: u64 = 40;
227/// One-time per successful barracks level upgrade (shards or SOL path).
228pub const XP_BARRACKS_UPGRADE: u64 = 40;
229/// First successful dine per barracks slot index (lifetime bitmask on `Barracks`).
230pub const XP_DINE_FIRST_PER_SLOT: u64 = 20;
231
232// Scene collection
233pub const SCENES: &[u8] = b"scenes";
234pub const SCENE_DEFAULT_ID: u64 = 0;
235pub const SCENE_SECTIONS_PER_SCENE: usize = 12;
236pub const SCENE_COUNT_MAX: usize = 9;
237pub const SCENE_COUNT: u64 = 8;
238/// Scenes in roll pool (1–5). Excludes scene 0 (Green Mountain) and buyable scenes 6–8.
239pub const SCENE_ROLL_COUNT: u64 = 5;
240pub const SCENE_ROLL_SHARD_COUNT: u64 = 10;
241/// Scenes 6–8 can be bought with Amethyst (unlock entire scene).
242pub const SCENE_BUY_START: u64 = 6;
243
244// Scene bonuses for claim_shards (ore = (spirit_power * chakra) / divisor; bonuses apply after sum).
245/// Scene 0 (Green Mountain): no bonus.
246/// Scenes 1, 6, 7, 8: flat +50_000 Spirit Power.
247pub const SCENE_BONUS_FLAT_50K: u64 = 50_000;
248/// Scene 2: flat +100_000 Spirit Power.
249pub const SCENE_BONUS_FLAT_100K: u64 = 100_000;
250/// Scene 3: +2% multiplier (basis points).
251pub const SCENE_BONUS_PCT_2: u64 = 200;
252/// Scene 4: +3% multiplier (basis points).
253pub const SCENE_BONUS_PCT_3: u64 = 300;
254/// Scene 5: +5% multiplier (basis points).
255pub const SCENE_BONUS_PCT_5: u64 = 500;