@wuwei-labs/srsly
Version:
TypeScript SDK for SRSLY
153 lines • 6.78 kB
JavaScript
/**
* 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