/** * 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, 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 { EncounterPoolSeeds, findEncounterPoolPda } from '../pdas'; import { getMinorFactionIdDecoder, getMinorFactionIdEncoder, getPoolOfferEntryDecoder, getPoolOfferEntryEncoder, getRegionIdDecoder, getRegionIdEncoder, getScanPatternStatusDecoder, getScanPatternStatusEncoder, type MinorFactionId, type MinorFactionIdArgs, type PoolOfferEntry, type PoolOfferEntryArgs, type RegionId, type RegionIdArgs, type ScanPatternStatus, type ScanPatternStatusArgs, } from '../types'; export const ENCOUNTER_POOL_DISCRIMINATOR = new Uint8Array([ 33, 94, 192, 97, 239, 142, 243, 113, ]); export function getEncounterPoolDiscriminatorBytes() { return fixEncoderSize(getBytesEncoder(), 8).encode( ENCOUNTER_POOL_DISCRIMINATOR, ); } /** * The dev-registered ENVELOPE for one `(region, minor_faction)` encounter pool. * * Long-lived; created/edited only by `MANAGE_NPC_ENCOUNTERS`-gated admin instructions and read-only * at encounter time. Modeled on [`ScanPattern`](crate::state::ScanPattern): a sized header + an * `#[unsized_start]` `List` tail (additive growth lives in the tail). */ export type EncounterPool = { discriminator: ReadonlyUint8Array; /** Layout version (mirrors `ScanPattern.version`). */ version: number; /** PDA bump. */ bump: number; /** Game scoping key. */ gameId: Address; /** The zone this pool belongs to. */ regionId: RegionId; /** The minor-faction NPC this pool represents (off-chain lore name mapped by `MinorFactionId`). */ minorFaction: MinorFactionId; /** Reuses the `Draft`/`Active` gate idiom; only `Active` pools can spawn an encounter. */ status: ScanPatternStatus; /** * Ultra-rare candidacy chance, as `trigger_weight / trigger_total` (kept well under ~1%). * Same fixed-point domain as the scan roll (`U16F16`). */ triggerWeight: number; triggerTotal: number; /** Market lifetime once revealed, in seconds (decision #4 = 300). Applied as `now + ttl` at reveal. */ marketTtlSecs: number; /** ATLAS-burn sink on the faucet leg, in basis points. `0` = off (default until econ enables). */ atlasBurnBps: number; /** * `0` = the faucet leg (NPC buys from the player) is disabled ⇒ the market is **sell-only**. * Default off until econ enables it per pool (decision 1-c). */ faucetEnabled: number; /** `0` = no catalog rotation; non-zero = rotate the available offers each `rotation_period_secs`. */ rotationEnabled: number; /** Rotation epoch length in seconds (anti-staleness); ignored when `rotation_enabled == 0`. */ rotationPeriodSecs: number; /** The allowed item set (buy + sell offers, side per entry). A revealed market is a weighted subset. */ offers: Array; }; export type EncounterPoolArgs = { /** Layout version (mirrors `ScanPattern.version`). */ version: number; /** PDA bump. */ bump: number; /** Game scoping key. */ gameId: Address; /** The zone this pool belongs to. */ regionId: RegionIdArgs; /** The minor-faction NPC this pool represents (off-chain lore name mapped by `MinorFactionId`). */ minorFaction: MinorFactionIdArgs; /** Reuses the `Draft`/`Active` gate idiom; only `Active` pools can spawn an encounter. */ status: ScanPatternStatusArgs; /** * Ultra-rare candidacy chance, as `trigger_weight / trigger_total` (kept well under ~1%). * Same fixed-point domain as the scan roll (`U16F16`). */ triggerWeight: number; triggerTotal: number; /** Market lifetime once revealed, in seconds (decision #4 = 300). Applied as `now + ttl` at reveal. */ marketTtlSecs: number; /** ATLAS-burn sink on the faucet leg, in basis points. `0` = off (default until econ enables). */ atlasBurnBps: number; /** * `0` = the faucet leg (NPC buys from the player) is disabled ⇒ the market is **sell-only**. * Default off until econ enables it per pool (decision 1-c). */ faucetEnabled: number; /** `0` = no catalog rotation; non-zero = rotate the available offers each `rotation_period_secs`. */ rotationEnabled: number; /** Rotation epoch length in seconds (anti-staleness); ignored when `rotation_enabled == 0`. */ rotationPeriodSecs: number; /** The allowed item set (buy + sell offers, side per entry). A revealed market is a weighted subset. */ offers: Array; }; /** Gets the encoder for {@link EncounterPoolArgs} account data. */ export function getEncounterPoolEncoder(): Encoder { return transformEncoder( getStructEncoder([ ['discriminator', fixEncoderSize(getBytesEncoder(), 8)], ['version', getU8Encoder()], ['bump', getU8Encoder()], ['gameId', getAddressEncoder()], ['regionId', getRegionIdEncoder()], ['minorFaction', getMinorFactionIdEncoder()], ['status', getScanPatternStatusEncoder()], ['triggerWeight', getU32Encoder()], ['triggerTotal', getU32Encoder()], ['marketTtlSecs', getU32Encoder()], ['atlasBurnBps', getU16Encoder()], ['faucetEnabled', getU8Encoder()], ['rotationEnabled', getU8Encoder()], ['rotationPeriodSecs', getU32Encoder()], ['offers', getArrayEncoder(getPoolOfferEntryEncoder())], ]), (value) => ({ ...value, discriminator: ENCOUNTER_POOL_DISCRIMINATOR }), ); } /** Gets the decoder for {@link EncounterPool} account data. */ export function getEncounterPoolDecoder(): Decoder { return getStructDecoder([ ['discriminator', fixDecoderSize(getBytesDecoder(), 8)], ['version', getU8Decoder()], ['bump', getU8Decoder()], ['gameId', getAddressDecoder()], ['regionId', getRegionIdDecoder()], ['minorFaction', getMinorFactionIdDecoder()], ['status', getScanPatternStatusDecoder()], ['triggerWeight', getU32Decoder()], ['triggerTotal', getU32Decoder()], ['marketTtlSecs', getU32Decoder()], ['atlasBurnBps', getU16Decoder()], ['faucetEnabled', getU8Decoder()], ['rotationEnabled', getU8Decoder()], ['rotationPeriodSecs', getU32Decoder()], ['offers', getArrayDecoder(getPoolOfferEntryDecoder())], ]); } /** Gets the codec for {@link EncounterPool} account data. */ export function getEncounterPoolCodec(): Codec< EncounterPoolArgs, EncounterPool > { return combineCodec(getEncounterPoolEncoder(), getEncounterPoolDecoder()); } export function decodeEncounterPool( encodedAccount: EncodedAccount, ): Account; export function decodeEncounterPool( encodedAccount: MaybeEncodedAccount, ): MaybeAccount; export function decodeEncounterPool( encodedAccount: EncodedAccount | MaybeEncodedAccount, ): Account | MaybeAccount { return decodeAccount( encodedAccount as MaybeEncodedAccount, getEncounterPoolDecoder(), ); } export async function fetchEncounterPool( rpc: Parameters[0], address: Address, config?: FetchAccountConfig, ): Promise> { const maybeAccount = await fetchMaybeEncounterPool(rpc, address, config); assertAccountExists(maybeAccount); return maybeAccount; } export async function fetchMaybeEncounterPool( rpc: Parameters[0], address: Address, config?: FetchAccountConfig, ): Promise> { const maybeAccount = await fetchEncodedAccount(rpc, address, config); return decodeEncounterPool(maybeAccount); } export async function fetchAllEncounterPool( rpc: Parameters[0], addresses: Array
, config?: FetchAccountsConfig, ): Promise[]> { const maybeAccounts = await fetchAllMaybeEncounterPool( rpc, addresses, config, ); assertAccountsExist(maybeAccounts); return maybeAccounts; } export async function fetchAllMaybeEncounterPool( rpc: Parameters[0], addresses: Array
, config?: FetchAccountsConfig, ): Promise[]> { const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config); return maybeAccounts.map((maybeAccount) => decodeEncounterPool(maybeAccount)); } export async function fetchEncounterPoolFromSeeds( rpc: Parameters[0], seeds: EncounterPoolSeeds, config: FetchAccountConfig & { programAddress?: Address } = {}, ): Promise> { const maybeAccount = await fetchMaybeEncounterPoolFromSeeds( rpc, seeds, config, ); assertAccountExists(maybeAccount); return maybeAccount; } export async function fetchMaybeEncounterPoolFromSeeds( rpc: Parameters[0], seeds: EncounterPoolSeeds, config: FetchAccountConfig & { programAddress?: Address } = {}, ): Promise> { const { programAddress, ...fetchConfig } = config; const [address] = await findEncounterPoolPda(seeds, { programAddress }); return await fetchMaybeEncounterPool(rpc, address, fetchConfig); }