/** * This code was AUTOGENERATED using the Codama library. * Please DO NOT EDIT THIS FILE, instead use visitors * to add features, then rerun Codama to update it. * * @see https://github.com/codama-idl/codama */ import { assertAccountExists, assertAccountsExist, combineCodec, decodeAccount, fetchEncodedAccount, fetchEncodedAccounts, fixDecoderSize, fixEncoderSize, getAddressDecoder, getAddressEncoder, getArrayDecoder, getArrayEncoder, getBytesDecoder, getBytesEncoder, getI64Decoder, getI64Encoder, getStructDecoder, getStructEncoder, getU16Decoder, getU16Encoder, getU32Decoder, getU32Encoder, getU8Decoder, getU8Encoder, transformEncoder, type Account, type Address, type Codec, type Decoder, type EncodedAccount, type Encoder, type FetchAccountConfig, type FetchAccountsConfig, type MaybeAccount, type MaybeEncodedAccount, type ReadonlyUint8Array, } from '@solana/kit'; import { getFactionDecoder, getFactionEncoder, type Faction, type FactionArgs, } from '@staratlas/dev-profile-faction'; import { FactionAccountSeeds, findFactionAccountPda } from '../pdas'; import { getFactionStatusDecoder, getFactionStatusEncoder, getMinorFactionIdDecoder, getMinorFactionIdEncoder, getRegionIdDecoder, getRegionIdEncoder, type FactionStatus, type FactionStatusArgs, type MinorFactionId, type MinorFactionIdArgs, type RegionId, type RegionIdArgs, } from '../types'; export const FACTION_ACCOUNT_DISCRIMINATOR = new Uint8Array([ 94, 145, 95, 33, 171, 111, 184, 7, ]); export function getFactionAccountDiscriminatorBytes() { return fixEncoderSize(getBytesEncoder(), 8).encode( FACTION_ACCOUNT_DISCRIMINATOR, ); } /** * The per-faction record in the dynamic registry (decision D1/D8). Sized, packed, 209 bytes. * * Modeled on `ProfileFactionAccount` (a sized * `ProgramAccount` embedding the [`Faction`] enum) + the [`EncounterPool`](crate::state::EncounterPool) * header (`(game, …, minor_faction)` scoping). Growth is by carving from `_reserved` (version-gated), * never by appending. */ export type FactionAccount = { discriminator: ReadonlyUint8Array; /** Layout/schema version (migration lever). */ version: number; /** PDA bump. */ bump: number; /** Game scoping key. */ gameId: Address; /** The dynamic faction id (reuses the `MinorFactionId` space; `0` = null, `1/2/3` = majors). */ factionId: MinorFactionId; /** Legacy alignment bridge: `Unaligned` for minors; `MUD/ONI/Ustur` for the 3 majors. */ alignment: Faction; /** Capability bitset ([`FactionCapabilityFlags`]). */ capabilityFlags: number; /** Lifecycle status. */ status: FactionStatus; /** Cached bump of the `FactionAuthority` PDA (the program-derived signer used in P2/P5). */ authorityBump: number; /** Optional guild controller (P0: always `NONE`; the validated assignment lands in P1). */ controller: Address; /** Max simultaneous Allied edges (diplomacy cap, enforced in P3). Default 3. */ maxAllies: number; /** Advisory count of this faction's treasuries (P2). */ treasuryCount: number; /** Homeland region for safe-zones / spawn origin (`0` = none). */ homeRegion: RegionId; /** Content-addressed off-chain lore reference (SHA-256 of the canonical content file). */ nameHash: Array; /** Off-chain manifest hash (cosmetics, blueprint catalog, dialogue). */ contentUriHash: Array; /** Creation timestamp (unix seconds). */ createdAt: bigint; /** * The faction's NPC fleet OPERATOR profile (the un-rentable `SagePlayerProfile` whose key flies this * faction's NPC fleets). `NONE` until an admin binds it via `SetFactionOperator`; `MintNpcFleet` requires * the minting operator to equal this exactly. (0-valued `NONE` = no operator = no NPC fleets.) */ operatorProfile: Address; /** * Unix ts of this faction's most recent dynamic starbase capture — the per-faction anti-blitz cursor * (`attack_starbase` STEP H refuses a new capture until `this + faction_capture_cooldown_secs`). */ lastCaptureAt: bigint; /** * Live (concurrent) count of this faction's NPC fleets: bumped at `MintNpcFleet`, and decremented on every * fleet-teardown path (disband / forced-disband / admin-remove / destroyed-cleanup) when the caller * supplies the fleet's FLEET-kind `FactionOwnership` sidecar + this account. ⚠ BEST-EFFORT: the * PERMISSIONLESS destroyed-cleanup path may omit those optionals, leaving the slot occupied — so under * adversarial cleanup the cap degrades toward a lifetime mint cap (never WORSE than that). A fully * non-gameable concurrent cap would need an on-`Fleet` NPC marker (the `Fleet` account has no reserve for * one without a breaking layout change — deferred). */ npcFleetCount: number; /** * Hard cap on this faction's concurrent NPC fleets — the PRIMARY anti-flood brake (independent of ATLAS * cost). Enforced at `MintNpcFleet` against the live `npc_fleet_count`. */ maxNpcFleets: number; /** Additive growth space (carve from the front, version-gated; never append). */ reserved: Array; }; export type FactionAccountArgs = { /** Layout/schema version (migration lever). */ version: number; /** PDA bump. */ bump: number; /** Game scoping key. */ gameId: Address; /** The dynamic faction id (reuses the `MinorFactionId` space; `0` = null, `1/2/3` = majors). */ factionId: MinorFactionIdArgs; /** Legacy alignment bridge: `Unaligned` for minors; `MUD/ONI/Ustur` for the 3 majors. */ alignment: FactionArgs; /** Capability bitset ([`FactionCapabilityFlags`]). */ capabilityFlags: number; /** Lifecycle status. */ status: FactionStatusArgs; /** Cached bump of the `FactionAuthority` PDA (the program-derived signer used in P2/P5). */ authorityBump: number; /** Optional guild controller (P0: always `NONE`; the validated assignment lands in P1). */ controller: Address; /** Max simultaneous Allied edges (diplomacy cap, enforced in P3). Default 3. */ maxAllies: number; /** Advisory count of this faction's treasuries (P2). */ treasuryCount: number; /** Homeland region for safe-zones / spawn origin (`0` = none). */ homeRegion: RegionIdArgs; /** Content-addressed off-chain lore reference (SHA-256 of the canonical content file). */ nameHash: Array; /** Off-chain manifest hash (cosmetics, blueprint catalog, dialogue). */ contentUriHash: Array; /** Creation timestamp (unix seconds). */ createdAt: number | bigint; /** * The faction's NPC fleet OPERATOR profile (the un-rentable `SagePlayerProfile` whose key flies this * faction's NPC fleets). `NONE` until an admin binds it via `SetFactionOperator`; `MintNpcFleet` requires * the minting operator to equal this exactly. (0-valued `NONE` = no operator = no NPC fleets.) */ operatorProfile: Address; /** * Unix ts of this faction's most recent dynamic starbase capture — the per-faction anti-blitz cursor * (`attack_starbase` STEP H refuses a new capture until `this + faction_capture_cooldown_secs`). */ lastCaptureAt: number | bigint; /** * Live (concurrent) count of this faction's NPC fleets: bumped at `MintNpcFleet`, and decremented on every * fleet-teardown path (disband / forced-disband / admin-remove / destroyed-cleanup) when the caller * supplies the fleet's FLEET-kind `FactionOwnership` sidecar + this account. ⚠ BEST-EFFORT: the * PERMISSIONLESS destroyed-cleanup path may omit those optionals, leaving the slot occupied — so under * adversarial cleanup the cap degrades toward a lifetime mint cap (never WORSE than that). A fully * non-gameable concurrent cap would need an on-`Fleet` NPC marker (the `Fleet` account has no reserve for * one without a breaking layout change — deferred). */ npcFleetCount: number; /** * Hard cap on this faction's concurrent NPC fleets — the PRIMARY anti-flood brake (independent of ATLAS * cost). Enforced at `MintNpcFleet` against the live `npc_fleet_count`. */ maxNpcFleets: number; /** Additive growth space (carve from the front, version-gated; never append). */ reserved: Array; }; /** Gets the encoder for {@link FactionAccountArgs} account data. */ export function getFactionAccountEncoder(): Encoder { return transformEncoder( getStructEncoder([ ['discriminator', fixEncoderSize(getBytesEncoder(), 8)], ['version', getU8Encoder()], ['bump', getU8Encoder()], ['gameId', getAddressEncoder()], ['factionId', getMinorFactionIdEncoder()], ['alignment', getFactionEncoder()], ['capabilityFlags', getU32Encoder()], ['status', getFactionStatusEncoder()], ['authorityBump', getU8Encoder()], ['controller', getAddressEncoder()], ['maxAllies', getU8Encoder()], ['treasuryCount', getU8Encoder()], ['homeRegion', getRegionIdEncoder()], ['nameHash', getArrayEncoder(getU8Encoder(), { size: 32 })], ['contentUriHash', getArrayEncoder(getU8Encoder(), { size: 32 })], ['createdAt', getI64Encoder()], ['operatorProfile', getAddressEncoder()], ['lastCaptureAt', getI64Encoder()], ['npcFleetCount', getU16Encoder()], ['maxNpcFleets', getU16Encoder()], ['reserved', getArrayEncoder(getU8Encoder(), { size: 14 })], ]), (value) => ({ ...value, discriminator: FACTION_ACCOUNT_DISCRIMINATOR }), ); } /** Gets the decoder for {@link FactionAccount} account data. */ export function getFactionAccountDecoder(): Decoder { return getStructDecoder([ ['discriminator', fixDecoderSize(getBytesDecoder(), 8)], ['version', getU8Decoder()], ['bump', getU8Decoder()], ['gameId', getAddressDecoder()], ['factionId', getMinorFactionIdDecoder()], ['alignment', getFactionDecoder()], ['capabilityFlags', getU32Decoder()], ['status', getFactionStatusDecoder()], ['authorityBump', getU8Decoder()], ['controller', getAddressDecoder()], ['maxAllies', getU8Decoder()], ['treasuryCount', getU8Decoder()], ['homeRegion', getRegionIdDecoder()], ['nameHash', getArrayDecoder(getU8Decoder(), { size: 32 })], ['contentUriHash', getArrayDecoder(getU8Decoder(), { size: 32 })], ['createdAt', getI64Decoder()], ['operatorProfile', getAddressDecoder()], ['lastCaptureAt', getI64Decoder()], ['npcFleetCount', getU16Decoder()], ['maxNpcFleets', getU16Decoder()], ['reserved', getArrayDecoder(getU8Decoder(), { size: 14 })], ]); } /** Gets the codec for {@link FactionAccount} account data. */ export function getFactionAccountCodec(): Codec< FactionAccountArgs, FactionAccount > { return combineCodec(getFactionAccountEncoder(), getFactionAccountDecoder()); } export function decodeFactionAccount( encodedAccount: EncodedAccount, ): Account; export function decodeFactionAccount( encodedAccount: MaybeEncodedAccount, ): MaybeAccount; export function decodeFactionAccount( encodedAccount: EncodedAccount | MaybeEncodedAccount, ): Account | MaybeAccount { return decodeAccount( encodedAccount as MaybeEncodedAccount, getFactionAccountDecoder(), ); } export async function fetchFactionAccount( rpc: Parameters[0], address: Address, config?: FetchAccountConfig, ): Promise> { const maybeAccount = await fetchMaybeFactionAccount(rpc, address, config); assertAccountExists(maybeAccount); return maybeAccount; } export async function fetchMaybeFactionAccount< TAddress extends string = string, >( rpc: Parameters[0], address: Address, config?: FetchAccountConfig, ): Promise> { const maybeAccount = await fetchEncodedAccount(rpc, address, config); return decodeFactionAccount(maybeAccount); } export async function fetchAllFactionAccount( rpc: Parameters[0], addresses: Array
, config?: FetchAccountsConfig, ): Promise[]> { const maybeAccounts = await fetchAllMaybeFactionAccount( rpc, addresses, config, ); assertAccountsExist(maybeAccounts); return maybeAccounts; } export async function fetchAllMaybeFactionAccount( rpc: Parameters[0], addresses: Array
, config?: FetchAccountsConfig, ): Promise[]> { const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config); return maybeAccounts.map((maybeAccount) => decodeFactionAccount(maybeAccount), ); } export async function fetchFactionAccountFromSeeds( rpc: Parameters[0], seeds: FactionAccountSeeds, config: FetchAccountConfig & { programAddress?: Address } = {}, ): Promise> { const maybeAccount = await fetchMaybeFactionAccountFromSeeds( rpc, seeds, config, ); assertAccountExists(maybeAccount); return maybeAccount; } export async function fetchMaybeFactionAccountFromSeeds( rpc: Parameters[0], seeds: FactionAccountSeeds, config: FetchAccountConfig & { programAddress?: Address } = {}, ): Promise> { const { programAddress, ...fetchConfig } = config; const [address] = await findFactionAccountPda(seeds, { programAddress }); return await fetchMaybeFactionAccount(rpc, address, fetchConfig); }