UNPKG

@wuwei-labs/srsly

Version:
153 lines 6.78 kB
/** * PDA derivation functions for SAGE and Profile Faction programs * @module pda/sage */ import { address, getProgramDerivedAddress, getAddressEncoder } from '@solana/kit'; import { getAddresses } from '../utils/config'; import { getSignerAddress } from '../utils/signer'; import { PROFILE_FACTION_SEED, SAGE_PLAYER_PROFILE_SEED, STARBASE_SEED, STARBASE_PLAYER_SEED, getFactionCoordinates, getFactionName, } from './constants'; /** * Address encoder for PDA seeds */ const addressEncoder = getAddressEncoder(); /** * Text encoder for string seeds */ const textEncoder = new TextEncoder(); /** * Derive the profile faction PDA from a profile address * @param profile - The player profile public key * @param programAddress - Optional Profile Faction program address (defaults to network-specific address) * @returns The derived profile faction PDA */ export async function deriveProfileFaction(profile, programAddress) { const profileAddress = getSignerAddress(profile); const program = programAddress ? getSignerAddress(programAddress) : address(getAddresses().profileFaction); // Encode seeds to bytes const profileFactionSeedBytes = textEncoder.encode(PROFILE_FACTION_SEED); const profileBytes = addressEncoder.encode(profileAddress); const [pda] = await getProgramDerivedAddress({ programAddress: program, seeds: [profileFactionSeedBytes, profileBytes], }); return pda; } /** * Derive the SAGE player profile PDA * @param profile - The player profile public key * @param gameId - The game ID public key * @param programAddress - Optional SAGE program address (defaults to network-specific address) * @returns The derived SAGE player profile PDA */ export async function deriveSagePlayerProfile(profile, gameId, programAddress) { const profileAddress = getSignerAddress(profile); const gameIdAddress = getSignerAddress(gameId); const program = programAddress ? getSignerAddress(programAddress) : address(getAddresses().sage); // Encode seeds to bytes const sagePlayerProfileSeedBytes = textEncoder.encode(SAGE_PLAYER_PROFILE_SEED); const profileBytes = addressEncoder.encode(profileAddress); const gameIdBytes = addressEncoder.encode(gameIdAddress); const [pda] = await getProgramDerivedAddress({ programAddress: program, seeds: [sagePlayerProfileSeedBytes, profileBytes, gameIdBytes], }); return pda; } /** * Derive the starbase PDA from faction and game ID * @param faction - Faction name ('mud', 'oni', 'ustur') or faction ID (1, 2, 3) * @param gameId - The game ID public key * @param programAddress - Optional SAGE program address (defaults to network-specific address) * @returns The derived starbase PDA */ export async function deriveStarbase(faction, gameId, programAddress) { const factionName = typeof faction === 'number' ? getFactionName(faction) : faction; const coords = getFactionCoordinates(factionName); const gameIdAddress = getSignerAddress(gameId); const program = programAddress ? getSignerAddress(programAddress) : address(getAddresses().sage); // Encode string and address seeds to bytes const starbaseSeedBytes = textEncoder.encode(STARBASE_SEED); const gameIdBytes = addressEncoder.encode(gameIdAddress); // Convert coordinates to little-endian bytes const xBuffer = new ArrayBuffer(8); const xView = new DataView(xBuffer); xView.setBigInt64(0, BigInt(coords.x), true); // true = little endian const yBuffer = new ArrayBuffer(8); const yView = new DataView(yBuffer); yView.setBigInt64(0, BigInt(coords.y), true); // true = little endian const [pda] = await getProgramDerivedAddress({ programAddress: program, seeds: [starbaseSeedBytes, gameIdBytes, new Uint8Array(xBuffer), new Uint8Array(yBuffer)], }); return pda; } /** * Derive the starbase player PDA * @param sagePlayerProfile - The SAGE player profile public key * @param starbase - The starbase public key * @param starbaseSeqId - Optional starbase sequence ID (defaults to 0) * @param programAddress - Optional SAGE program address (defaults to network-specific address) * @returns The derived starbase player PDA */ export async function deriveStarbasePlayer(sagePlayerProfile, starbase, starbaseSeqId = 0, programAddress) { const profileAddress = getSignerAddress(sagePlayerProfile); const starbaseAddress = getSignerAddress(starbase); const program = programAddress ? getSignerAddress(programAddress) : address(getAddresses().sage); // Encode string and address seeds to bytes const starbasePlayerSeedBytes = textEncoder.encode(STARBASE_PLAYER_SEED); const profileBytes = addressEncoder.encode(profileAddress); const starbaseBytes = addressEncoder.encode(starbaseAddress); // Convert sequence ID to little-endian u16 bytes const seqBuffer = new ArrayBuffer(2); const seqView = new DataView(seqBuffer); seqView.setUint16(0, starbaseSeqId, true); // true = little endian const [pda] = await getProgramDerivedAddress({ programAddress: program, seeds: [starbasePlayerSeedBytes, profileBytes, starbaseBytes, new Uint8Array(seqBuffer)], }); return pda; } /** * Derive all SAGE game accounts at once (convenience function) * * This is a helper that derives all three SAGE-related accounts needed for most operations: * - Profile faction (from Profile Faction program) * - SAGE player profile (from SAGE program) * - Starbase (from SAGE program using faction coordinates) * - Starbase player (from SAGE program) * * @param profile - The player profile public key * @param faction - Faction name ('mud', 'oni', 'ustur') or faction ID (1, 2, 3) * @param gameId - The game ID public key * @param starbaseSeqId - Optional starbase sequence ID (defaults to 0) * @returns Object containing all derived SAGE accounts * * @example * ```typescript * const accounts = await deriveGameAccounts( * playerProfile, * 'mud', * gameId * ); * // Returns: { profileFaction, sagePlayerProfile, starbase, starbasePlayer } * ``` */ export async function deriveGameAccounts(profile, faction, gameId, starbaseSeqId = 0) { // Derive all accounts const [profileFaction, sagePlayerProfile, starbase] = await Promise.all([ deriveProfileFaction(profile), deriveSagePlayerProfile(profile, gameId), deriveStarbase(faction, gameId), ]); // Derive starbase player (depends on sagePlayerProfile and starbase) const starbasePlayer = await deriveStarbasePlayer(sagePlayerProfile, starbase, starbaseSeqId); return { profileFaction, sagePlayerProfile, starbase, starbasePlayer, }; } //# sourceMappingURL=sage.js.map