/** * 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 { combineCodec, fixDecoderSize, fixEncoderSize, getAddressEncoder, getBytesDecoder, getBytesEncoder, getProgramDerivedAddress, getStructDecoder, getStructEncoder, getU16Decoder, getU16Encoder, SOLANA_ERROR__PROGRAM_CLIENTS__INSUFFICIENT_ACCOUNT_METAS, SolanaError, transformEncoder, type AccountMeta, type AccountSignerMeta, type Address, type FixedSizeCodec, type FixedSizeDecoder, type FixedSizeEncoder, type Instruction, type InstructionWithAccounts, type InstructionWithData, type ReadonlyAccount, type ReadonlySignerAccount, type ReadonlyUint8Array, type TransactionSigner, type WritableAccount, type WritableSignerAccount, } from '@solana/kit'; import { getAccountMetaFactory, getAddressFromResolvedInstructionAccount, type ResolvedInstructionAccount, } from '@solana/program-client-core'; import { SAGE_PROGRAM_ADDRESS } from '../programs'; import { getFleetStanceDecoder, getFleetStanceEncoder, type FleetStance, type FleetStanceArgs, } from '../types'; export const ATTACK_FLEET_DISCRIMINATOR = new Uint8Array([ 89, 173, 5, 123, 109, 13, 236, 217, ]); export function getAttackFleetDiscriminatorBytes() { return fixEncoderSize(getBytesEncoder(), 8).encode( ATTACK_FLEET_DISCRIMINATOR, ); } export type AttackFleetInstruction< TProgram extends string = typeof SAGE_PROGRAM_ADDRESS, TAccountProfileValidationSigner extends string | AccountMeta = string, TAccountProfileValidationProfile extends string | AccountMeta = string, TAccountProfileValidationCertificate extends string | AccountMeta = string, TAccountProfileValidationProgram extends string | AccountMeta = 'C4PRoFNroxxzdgeCoM31LJjYRg7kT6ymogSTAT99iD1u', TAccountCharacter extends string | AccountMeta = string, TAccountFleet extends string | AccountMeta = string, TAccountDefendingFleet extends string | AccountMeta = string, TAccountDefenderCharacter extends string | AccountMeta = string, TAccountLoot extends string | AccountMeta = string, TAccountRegionTracker extends string | AccountMeta = string, TAccountGame extends string | AccountMeta = string, TAccountInstructionsSysvar extends string | AccountMeta = 'Sysvar1nstructions1111111111111111111111111', TAccountRecentSlothashes extends string | AccountMeta = string, TAccountSystemProgram extends string | AccountMeta = '11111111111111111111111111111111', TAccountAsteroid extends string | AccountMeta = string, TAccountFactionRelationTracker extends string | AccountMeta = string, TAccountCrewBinding extends string | AccountMeta = string, TAccountAttackerFleetOwnership extends string | AccountMeta = string, TAccountDefenderFleetOwnership extends string | AccountMeta = string, TAccountAttackerFactionAccount extends string | AccountMeta = string, TAccountAttackerRewardsRegistry extends string | AccountMeta = string, TAccountAttackerRewardsConfig extends string | AccountMeta = string, TAccountAttackerRewardsEpoch extends string | AccountMeta = string, TAccountAttackerRewardsContribution extends string | AccountMeta = string, TAccountDefenderRewardsRegistry extends string | AccountMeta = string, TAccountDefenderRewardsConfig extends string | AccountMeta = string, TAccountDefenderRewardsEpoch extends string | AccountMeta = string, TAccountDefenderRewardsContribution extends string | AccountMeta = string, TAccountAttackerXpBudget extends string | AccountMeta = string, TAccountDefenderXpBudget extends string | AccountMeta = string, TAccountXpBudgetConfig extends string | AccountMeta = string, TRemainingAccounts extends readonly AccountMeta[] = [], > = Instruction & InstructionWithData & InstructionWithAccounts< [ TAccountProfileValidationSigner extends string ? ReadonlySignerAccount & AccountSignerMeta : TAccountProfileValidationSigner, TAccountProfileValidationProfile extends string ? WritableAccount : TAccountProfileValidationProfile, TAccountProfileValidationCertificate extends string ? ReadonlyAccount : TAccountProfileValidationCertificate, TAccountProfileValidationProgram extends string ? ReadonlyAccount : TAccountProfileValidationProgram, TAccountCharacter extends string ? WritableAccount : TAccountCharacter, TAccountFleet extends string ? WritableAccount : TAccountFleet, TAccountDefendingFleet extends string ? WritableAccount : TAccountDefendingFleet, TAccountDefenderCharacter extends string ? WritableAccount : TAccountDefenderCharacter, TAccountLoot extends string ? WritableSignerAccount & AccountSignerMeta : TAccountLoot, TAccountRegionTracker extends string ? ReadonlyAccount : TAccountRegionTracker, TAccountGame extends string ? ReadonlyAccount : TAccountGame, TAccountInstructionsSysvar extends string ? ReadonlyAccount : TAccountInstructionsSysvar, TAccountRecentSlothashes extends string ? ReadonlyAccount : TAccountRecentSlothashes, TAccountSystemProgram extends string ? ReadonlyAccount : TAccountSystemProgram, TAccountAsteroid extends string ? WritableAccount : TAccountAsteroid, TAccountFactionRelationTracker extends string ? ReadonlyAccount : TAccountFactionRelationTracker, TAccountCrewBinding extends string ? WritableAccount : TAccountCrewBinding, TAccountAttackerFleetOwnership extends string ? ReadonlyAccount : TAccountAttackerFleetOwnership, TAccountDefenderFleetOwnership extends string ? ReadonlyAccount : TAccountDefenderFleetOwnership, TAccountAttackerFactionAccount extends string ? ReadonlyAccount : TAccountAttackerFactionAccount, TAccountAttackerRewardsRegistry extends string ? ReadonlyAccount : TAccountAttackerRewardsRegistry, TAccountAttackerRewardsConfig extends string ? ReadonlyAccount : TAccountAttackerRewardsConfig, TAccountAttackerRewardsEpoch extends string ? WritableAccount : TAccountAttackerRewardsEpoch, TAccountAttackerRewardsContribution extends string ? WritableAccount : TAccountAttackerRewardsContribution, TAccountDefenderRewardsRegistry extends string ? ReadonlyAccount : TAccountDefenderRewardsRegistry, TAccountDefenderRewardsConfig extends string ? ReadonlyAccount : TAccountDefenderRewardsConfig, TAccountDefenderRewardsEpoch extends string ? WritableAccount : TAccountDefenderRewardsEpoch, TAccountDefenderRewardsContribution extends string ? WritableAccount : TAccountDefenderRewardsContribution, TAccountAttackerXpBudget extends string ? WritableAccount : TAccountAttackerXpBudget, TAccountDefenderXpBudget extends string ? WritableAccount : TAccountDefenderXpBudget, TAccountXpBudgetConfig extends string ? ReadonlyAccount : TAccountXpBudgetConfig, ...TRemainingAccounts, ] >; export type AttackFleetInstructionData = { discriminator: ReadonlyUint8Array; /** The index of the key in the player profile */ keyIndex: number; /** * The attacking stance * TODO: actually use this */ stance: FleetStance; }; export type AttackFleetInstructionDataArgs = { /** The index of the key in the player profile */ keyIndex: number; /** * The attacking stance * TODO: actually use this */ stance: FleetStanceArgs; }; export function getAttackFleetInstructionDataEncoder(): FixedSizeEncoder { return transformEncoder( getStructEncoder([ ['discriminator', fixEncoderSize(getBytesEncoder(), 8)], ['keyIndex', getU16Encoder()], ['stance', getFleetStanceEncoder()], ]), (value) => ({ ...value, discriminator: ATTACK_FLEET_DISCRIMINATOR }), ); } export function getAttackFleetInstructionDataDecoder(): FixedSizeDecoder { return getStructDecoder([ ['discriminator', fixDecoderSize(getBytesDecoder(), 8)], ['keyIndex', getU16Decoder()], ['stance', getFleetStanceDecoder()], ]); } export function getAttackFleetInstructionDataCodec(): FixedSizeCodec< AttackFleetInstructionDataArgs, AttackFleetInstructionData > { return combineCodec( getAttackFleetInstructionDataEncoder(), getAttackFleetInstructionDataDecoder(), ); } export type AttackFleetAsyncInput< TAccountProfileValidationSigner extends string = string, TAccountProfileValidationProfile extends string = string, TAccountProfileValidationCertificate extends string = string, TAccountProfileValidationProgram extends string = string, TAccountCharacter extends string = string, TAccountFleet extends string = string, TAccountDefendingFleet extends string = string, TAccountDefenderCharacter extends string = string, TAccountLoot extends string = string, TAccountRegionTracker extends string = string, TAccountGame extends string = string, TAccountInstructionsSysvar extends string = string, TAccountRecentSlothashes extends string = string, TAccountSystemProgram extends string = string, TAccountAsteroid extends string = string, TAccountFactionRelationTracker extends string = string, TAccountCrewBinding extends string = string, TAccountAttackerFleetOwnership extends string = string, TAccountDefenderFleetOwnership extends string = string, TAccountAttackerFactionAccount extends string = string, TAccountAttackerRewardsRegistry extends string = string, TAccountAttackerRewardsConfig extends string = string, TAccountAttackerRewardsEpoch extends string = string, TAccountAttackerRewardsContribution extends string = string, TAccountDefenderRewardsRegistry extends string = string, TAccountDefenderRewardsConfig extends string = string, TAccountDefenderRewardsEpoch extends string = string, TAccountDefenderRewardsContribution extends string = string, TAccountAttackerXpBudget extends string = string, TAccountDefenderXpBudget extends string = string, TAccountXpBudgetConfig extends string = string, > = { profileValidationSigner: TransactionSigner; profileValidationProfile: Address; profileValidationCertificate?: Address; profileValidationProgram?: Address; /** The character account */ character?: Address; /** * The `Fleet` account * Must be alive and have normalized crew */ fleet: Address; /** * The defending fleet. * Must be alive */ defendingFleet: Address; /** The defender's character account */ defenderCharacter: Address; /** The loot account */ loot: TransactionSigner; /** Region tracker account */ regionTracker: Address; /** The game account */ game: Address; /** Solana Instructions Sysvar */ instructionsSysvar?: Address; /** Recent slot hashes used to seed combat outcome randomness */ recentSlothashes: Address; /** The Solana System program */ systemProgram?: Address; /** * The asteroid that the defending fleet is mining * Must be provided only if the defending fleet is mining */ asteroid?: Address; /** * P3 diplomacy combat-gate (REQUIRED — enforced, non-bypassable). Always passed (one tracker per game, * created by `InitFactionRelationTracker`). When `combat_gating_enabled == 0` the gate is a no-op * (behavior-identical to pre-P3 — same-faction is still enforced by `validate()`'s `!=`); when `1`, it * forbids attacking an Allied/active-Ceasefire faction inside that faction's OWNED territory. */ factionRelationTracker: Address; crewBinding?: Address; /** * P5b: the ATTACKER fleet's `FactionOwnership(FLEET)` sidecar (Optional, read-only). Present ⇔ the * attacker is an NPC fleet — it supplies the dynamic controlling faction so `attacker_id` can resolve to * a minor id `> 3` (and the COMBATANT guard can bite). PDA seed-bound to `self.fleet`. Flag-OFF / a * player attack passes `None` ⇒ byte-identical to pre-P5b (the resolution falls back to the legacy enum). * Appended AFTER `crew_binding` so the canonical trailing-optional order is * asteroid → faction_relation_tracker → crew_binding → P5b's three (program-id-sentinel positional decode). */ attackerFleetOwnership?: Address; /** * P5b: the DEFENDER fleet's `FactionOwnership(FLEET)` sidecar (Optional, read-only). Resolves an NPC * defender's TRUE faction so the diplomacy gate + resolved same-faction guard don't mis-resolve it as * Unaligned (id 0). PDA seed-bound to `self.defending_fleet`. */ defenderFleetOwnership?: Address; /** * P5b: the attacker faction's registry account (Optional, read-only) — the COMBATANT capability guard * for a dynamic NPC attacker (`attacker_id > 3`). Its PDA is re-derived from the RESOLVED `attacker_id` * and `ensure_eq!`-bound in `process()`, so a caller can never pass a COMBATANT faction's account while * flying a non-COMBATANT faction's fleet. */ attackerFactionAccount?: Address; attackerRewardsRegistry: Address; attackerRewardsConfig: Address; attackerRewardsEpoch?: Address; attackerRewardsContribution?: Address; defenderRewardsRegistry: Address; defenderRewardsConfig: Address; defenderRewardsEpoch?: Address; defenderRewardsContribution?: Address; attackerXpBudget?: Address; defenderXpBudget?: Address; /** Game-scoped v1 budgets + earning rules (required on v1 games). */ xpBudgetConfig?: Address; keyIndex: AttackFleetInstructionDataArgs['keyIndex']; stance: AttackFleetInstructionDataArgs['stance']; }; export async function getAttackFleetInstructionAsync< TAccountProfileValidationSigner extends string, TAccountProfileValidationProfile extends string, TAccountProfileValidationCertificate extends string, TAccountProfileValidationProgram extends string, TAccountCharacter extends string, TAccountFleet extends string, TAccountDefendingFleet extends string, TAccountDefenderCharacter extends string, TAccountLoot extends string, TAccountRegionTracker extends string, TAccountGame extends string, TAccountInstructionsSysvar extends string, TAccountRecentSlothashes extends string, TAccountSystemProgram extends string, TAccountAsteroid extends string, TAccountFactionRelationTracker extends string, TAccountCrewBinding extends string, TAccountAttackerFleetOwnership extends string, TAccountDefenderFleetOwnership extends string, TAccountAttackerFactionAccount extends string, TAccountAttackerRewardsRegistry extends string, TAccountAttackerRewardsConfig extends string, TAccountAttackerRewardsEpoch extends string, TAccountAttackerRewardsContribution extends string, TAccountDefenderRewardsRegistry extends string, TAccountDefenderRewardsConfig extends string, TAccountDefenderRewardsEpoch extends string, TAccountDefenderRewardsContribution extends string, TAccountAttackerXpBudget extends string, TAccountDefenderXpBudget extends string, TAccountXpBudgetConfig extends string, TProgramAddress extends Address = typeof SAGE_PROGRAM_ADDRESS, >( input: AttackFleetAsyncInput< TAccountProfileValidationSigner, TAccountProfileValidationProfile, TAccountProfileValidationCertificate, TAccountProfileValidationProgram, TAccountCharacter, TAccountFleet, TAccountDefendingFleet, TAccountDefenderCharacter, TAccountLoot, TAccountRegionTracker, TAccountGame, TAccountInstructionsSysvar, TAccountRecentSlothashes, TAccountSystemProgram, TAccountAsteroid, TAccountFactionRelationTracker, TAccountCrewBinding, TAccountAttackerFleetOwnership, TAccountDefenderFleetOwnership, TAccountAttackerFactionAccount, TAccountAttackerRewardsRegistry, TAccountAttackerRewardsConfig, TAccountAttackerRewardsEpoch, TAccountAttackerRewardsContribution, TAccountDefenderRewardsRegistry, TAccountDefenderRewardsConfig, TAccountDefenderRewardsEpoch, TAccountDefenderRewardsContribution, TAccountAttackerXpBudget, TAccountDefenderXpBudget, TAccountXpBudgetConfig >, config?: { programAddress?: TProgramAddress }, ): Promise< AttackFleetInstruction< TProgramAddress, TAccountProfileValidationSigner, TAccountProfileValidationProfile, TAccountProfileValidationCertificate, TAccountProfileValidationProgram, TAccountCharacter, TAccountFleet, TAccountDefendingFleet, TAccountDefenderCharacter, TAccountLoot, TAccountRegionTracker, TAccountGame, TAccountInstructionsSysvar, TAccountRecentSlothashes, TAccountSystemProgram, TAccountAsteroid, TAccountFactionRelationTracker, TAccountCrewBinding, TAccountAttackerFleetOwnership, TAccountDefenderFleetOwnership, TAccountAttackerFactionAccount, TAccountAttackerRewardsRegistry, TAccountAttackerRewardsConfig, TAccountAttackerRewardsEpoch, TAccountAttackerRewardsContribution, TAccountDefenderRewardsRegistry, TAccountDefenderRewardsConfig, TAccountDefenderRewardsEpoch, TAccountDefenderRewardsContribution, TAccountAttackerXpBudget, TAccountDefenderXpBudget, TAccountXpBudgetConfig > > { // Program address. const programAddress = config?.programAddress ?? SAGE_PROGRAM_ADDRESS; // Original accounts. const originalAccounts = { profileValidationSigner: { value: input.profileValidationSigner ?? null, isWritable: false, }, profileValidationProfile: { value: input.profileValidationProfile ?? null, isWritable: true, }, profileValidationCertificate: { value: input.profileValidationCertificate ?? null, isWritable: false, }, profileValidationProgram: { value: input.profileValidationProgram ?? null, isWritable: false, }, character: { value: input.character ?? null, isWritable: true }, fleet: { value: input.fleet ?? null, isWritable: true }, defendingFleet: { value: input.defendingFleet ?? null, isWritable: true }, defenderCharacter: { value: input.defenderCharacter ?? null, isWritable: true, }, loot: { value: input.loot ?? null, isWritable: true }, regionTracker: { value: input.regionTracker ?? null, isWritable: false }, game: { value: input.game ?? null, isWritable: false }, instructionsSysvar: { value: input.instructionsSysvar ?? null, isWritable: false, }, recentSlothashes: { value: input.recentSlothashes ?? null, isWritable: false, }, systemProgram: { value: input.systemProgram ?? null, isWritable: false }, asteroid: { value: input.asteroid ?? null, isWritable: true }, factionRelationTracker: { value: input.factionRelationTracker ?? null, isWritable: false, }, crewBinding: { value: input.crewBinding ?? null, isWritable: true }, attackerFleetOwnership: { value: input.attackerFleetOwnership ?? null, isWritable: false, }, defenderFleetOwnership: { value: input.defenderFleetOwnership ?? null, isWritable: false, }, attackerFactionAccount: { value: input.attackerFactionAccount ?? null, isWritable: false, }, attackerRewardsRegistry: { value: input.attackerRewardsRegistry ?? null, isWritable: false, }, attackerRewardsConfig: { value: input.attackerRewardsConfig ?? null, isWritable: false, }, attackerRewardsEpoch: { value: input.attackerRewardsEpoch ?? null, isWritable: true, }, attackerRewardsContribution: { value: input.attackerRewardsContribution ?? null, isWritable: true, }, defenderRewardsRegistry: { value: input.defenderRewardsRegistry ?? null, isWritable: false, }, defenderRewardsConfig: { value: input.defenderRewardsConfig ?? null, isWritable: false, }, defenderRewardsEpoch: { value: input.defenderRewardsEpoch ?? null, isWritable: true, }, defenderRewardsContribution: { value: input.defenderRewardsContribution ?? null, isWritable: true, }, attackerXpBudget: { value: input.attackerXpBudget ?? null, isWritable: true, }, defenderXpBudget: { value: input.defenderXpBudget ?? null, isWritable: true, }, xpBudgetConfig: { value: input.xpBudgetConfig ?? null, isWritable: false }, }; const accounts = originalAccounts as Record< keyof typeof originalAccounts, ResolvedInstructionAccount >; // Original args. const args = { ...input }; // Resolve default values. if (!accounts.profileValidationProgram.value) { accounts.profileValidationProgram.value = 'C4PRoFNroxxzdgeCoM31LJjYRg7kT6ymogSTAT99iD1u' as Address<'C4PRoFNroxxzdgeCoM31LJjYRg7kT6ymogSTAT99iD1u'>; } if (!accounts.character.value) { accounts.character.value = await getProgramDerivedAddress({ programAddress, seeds: [ getBytesEncoder().encode( new Uint8Array([67, 104, 97, 114, 97, 99, 116, 101, 114]), ), getAddressEncoder().encode( getAddressFromResolvedInstructionAccount( 'profileValidationProfile', accounts.profileValidationProfile.value, ), ), getAddressEncoder().encode( getAddressFromResolvedInstructionAccount('game', accounts.game.value), ), ], }); } if (!accounts.instructionsSysvar.value) { accounts.instructionsSysvar.value = 'Sysvar1nstructions1111111111111111111111111' as Address<'Sysvar1nstructions1111111111111111111111111'>; } if (!accounts.systemProgram.value) { accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; } const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); return Object.freeze({ accounts: [ getAccountMeta( 'profileValidationSigner', accounts.profileValidationSigner, ), getAccountMeta( 'profileValidationProfile', accounts.profileValidationProfile, ), getAccountMeta( 'profileValidationCertificate', accounts.profileValidationCertificate, ), getAccountMeta( 'profileValidationProgram', accounts.profileValidationProgram, ), getAccountMeta('character', accounts.character), getAccountMeta('fleet', accounts.fleet), getAccountMeta('defendingFleet', accounts.defendingFleet), getAccountMeta('defenderCharacter', accounts.defenderCharacter), getAccountMeta('loot', accounts.loot), getAccountMeta('regionTracker', accounts.regionTracker), getAccountMeta('game', accounts.game), getAccountMeta('instructionsSysvar', accounts.instructionsSysvar), getAccountMeta('recentSlothashes', accounts.recentSlothashes), getAccountMeta('systemProgram', accounts.systemProgram), getAccountMeta('asteroid', accounts.asteroid), getAccountMeta('factionRelationTracker', accounts.factionRelationTracker), getAccountMeta('crewBinding', accounts.crewBinding), getAccountMeta('attackerFleetOwnership', accounts.attackerFleetOwnership), getAccountMeta('defenderFleetOwnership', accounts.defenderFleetOwnership), getAccountMeta('attackerFactionAccount', accounts.attackerFactionAccount), getAccountMeta( 'attackerRewardsRegistry', accounts.attackerRewardsRegistry, ), getAccountMeta('attackerRewardsConfig', accounts.attackerRewardsConfig), getAccountMeta('attackerRewardsEpoch', accounts.attackerRewardsEpoch), getAccountMeta( 'attackerRewardsContribution', accounts.attackerRewardsContribution, ), getAccountMeta( 'defenderRewardsRegistry', accounts.defenderRewardsRegistry, ), getAccountMeta('defenderRewardsConfig', accounts.defenderRewardsConfig), getAccountMeta('defenderRewardsEpoch', accounts.defenderRewardsEpoch), getAccountMeta( 'defenderRewardsContribution', accounts.defenderRewardsContribution, ), getAccountMeta('attackerXpBudget', accounts.attackerXpBudget), getAccountMeta('defenderXpBudget', accounts.defenderXpBudget), getAccountMeta('xpBudgetConfig', accounts.xpBudgetConfig), ], data: getAttackFleetInstructionDataEncoder().encode( args as AttackFleetInstructionDataArgs, ), programAddress, } as AttackFleetInstruction< TProgramAddress, TAccountProfileValidationSigner, TAccountProfileValidationProfile, TAccountProfileValidationCertificate, TAccountProfileValidationProgram, TAccountCharacter, TAccountFleet, TAccountDefendingFleet, TAccountDefenderCharacter, TAccountLoot, TAccountRegionTracker, TAccountGame, TAccountInstructionsSysvar, TAccountRecentSlothashes, TAccountSystemProgram, TAccountAsteroid, TAccountFactionRelationTracker, TAccountCrewBinding, TAccountAttackerFleetOwnership, TAccountDefenderFleetOwnership, TAccountAttackerFactionAccount, TAccountAttackerRewardsRegistry, TAccountAttackerRewardsConfig, TAccountAttackerRewardsEpoch, TAccountAttackerRewardsContribution, TAccountDefenderRewardsRegistry, TAccountDefenderRewardsConfig, TAccountDefenderRewardsEpoch, TAccountDefenderRewardsContribution, TAccountAttackerXpBudget, TAccountDefenderXpBudget, TAccountXpBudgetConfig >); } export type AttackFleetInput< TAccountProfileValidationSigner extends string = string, TAccountProfileValidationProfile extends string = string, TAccountProfileValidationCertificate extends string = string, TAccountProfileValidationProgram extends string = string, TAccountCharacter extends string = string, TAccountFleet extends string = string, TAccountDefendingFleet extends string = string, TAccountDefenderCharacter extends string = string, TAccountLoot extends string = string, TAccountRegionTracker extends string = string, TAccountGame extends string = string, TAccountInstructionsSysvar extends string = string, TAccountRecentSlothashes extends string = string, TAccountSystemProgram extends string = string, TAccountAsteroid extends string = string, TAccountFactionRelationTracker extends string = string, TAccountCrewBinding extends string = string, TAccountAttackerFleetOwnership extends string = string, TAccountDefenderFleetOwnership extends string = string, TAccountAttackerFactionAccount extends string = string, TAccountAttackerRewardsRegistry extends string = string, TAccountAttackerRewardsConfig extends string = string, TAccountAttackerRewardsEpoch extends string = string, TAccountAttackerRewardsContribution extends string = string, TAccountDefenderRewardsRegistry extends string = string, TAccountDefenderRewardsConfig extends string = string, TAccountDefenderRewardsEpoch extends string = string, TAccountDefenderRewardsContribution extends string = string, TAccountAttackerXpBudget extends string = string, TAccountDefenderXpBudget extends string = string, TAccountXpBudgetConfig extends string = string, > = { profileValidationSigner: TransactionSigner; profileValidationProfile: Address; profileValidationCertificate?: Address; profileValidationProgram?: Address; /** The character account */ character: Address; /** * The `Fleet` account * Must be alive and have normalized crew */ fleet: Address; /** * The defending fleet. * Must be alive */ defendingFleet: Address; /** The defender's character account */ defenderCharacter: Address; /** The loot account */ loot: TransactionSigner; /** Region tracker account */ regionTracker: Address; /** The game account */ game: Address; /** Solana Instructions Sysvar */ instructionsSysvar?: Address; /** Recent slot hashes used to seed combat outcome randomness */ recentSlothashes: Address; /** The Solana System program */ systemProgram?: Address; /** * The asteroid that the defending fleet is mining * Must be provided only if the defending fleet is mining */ asteroid?: Address; /** * P3 diplomacy combat-gate (REQUIRED — enforced, non-bypassable). Always passed (one tracker per game, * created by `InitFactionRelationTracker`). When `combat_gating_enabled == 0` the gate is a no-op * (behavior-identical to pre-P3 — same-faction is still enforced by `validate()`'s `!=`); when `1`, it * forbids attacking an Allied/active-Ceasefire faction inside that faction's OWNED territory. */ factionRelationTracker: Address; crewBinding?: Address; /** * P5b: the ATTACKER fleet's `FactionOwnership(FLEET)` sidecar (Optional, read-only). Present ⇔ the * attacker is an NPC fleet — it supplies the dynamic controlling faction so `attacker_id` can resolve to * a minor id `> 3` (and the COMBATANT guard can bite). PDA seed-bound to `self.fleet`. Flag-OFF / a * player attack passes `None` ⇒ byte-identical to pre-P5b (the resolution falls back to the legacy enum). * Appended AFTER `crew_binding` so the canonical trailing-optional order is * asteroid → faction_relation_tracker → crew_binding → P5b's three (program-id-sentinel positional decode). */ attackerFleetOwnership?: Address; /** * P5b: the DEFENDER fleet's `FactionOwnership(FLEET)` sidecar (Optional, read-only). Resolves an NPC * defender's TRUE faction so the diplomacy gate + resolved same-faction guard don't mis-resolve it as * Unaligned (id 0). PDA seed-bound to `self.defending_fleet`. */ defenderFleetOwnership?: Address; /** * P5b: the attacker faction's registry account (Optional, read-only) — the COMBATANT capability guard * for a dynamic NPC attacker (`attacker_id > 3`). Its PDA is re-derived from the RESOLVED `attacker_id` * and `ensure_eq!`-bound in `process()`, so a caller can never pass a COMBATANT faction's account while * flying a non-COMBATANT faction's fleet. */ attackerFactionAccount?: Address; attackerRewardsRegistry: Address; attackerRewardsConfig: Address; attackerRewardsEpoch?: Address; attackerRewardsContribution?: Address; defenderRewardsRegistry: Address; defenderRewardsConfig: Address; defenderRewardsEpoch?: Address; defenderRewardsContribution?: Address; attackerXpBudget?: Address; defenderXpBudget?: Address; /** Game-scoped v1 budgets + earning rules (required on v1 games). */ xpBudgetConfig?: Address; keyIndex: AttackFleetInstructionDataArgs['keyIndex']; stance: AttackFleetInstructionDataArgs['stance']; }; export function getAttackFleetInstruction< TAccountProfileValidationSigner extends string, TAccountProfileValidationProfile extends string, TAccountProfileValidationCertificate extends string, TAccountProfileValidationProgram extends string, TAccountCharacter extends string, TAccountFleet extends string, TAccountDefendingFleet extends string, TAccountDefenderCharacter extends string, TAccountLoot extends string, TAccountRegionTracker extends string, TAccountGame extends string, TAccountInstructionsSysvar extends string, TAccountRecentSlothashes extends string, TAccountSystemProgram extends string, TAccountAsteroid extends string, TAccountFactionRelationTracker extends string, TAccountCrewBinding extends string, TAccountAttackerFleetOwnership extends string, TAccountDefenderFleetOwnership extends string, TAccountAttackerFactionAccount extends string, TAccountAttackerRewardsRegistry extends string, TAccountAttackerRewardsConfig extends string, TAccountAttackerRewardsEpoch extends string, TAccountAttackerRewardsContribution extends string, TAccountDefenderRewardsRegistry extends string, TAccountDefenderRewardsConfig extends string, TAccountDefenderRewardsEpoch extends string, TAccountDefenderRewardsContribution extends string, TAccountAttackerXpBudget extends string, TAccountDefenderXpBudget extends string, TAccountXpBudgetConfig extends string, TProgramAddress extends Address = typeof SAGE_PROGRAM_ADDRESS, >( input: AttackFleetInput< TAccountProfileValidationSigner, TAccountProfileValidationProfile, TAccountProfileValidationCertificate, TAccountProfileValidationProgram, TAccountCharacter, TAccountFleet, TAccountDefendingFleet, TAccountDefenderCharacter, TAccountLoot, TAccountRegionTracker, TAccountGame, TAccountInstructionsSysvar, TAccountRecentSlothashes, TAccountSystemProgram, TAccountAsteroid, TAccountFactionRelationTracker, TAccountCrewBinding, TAccountAttackerFleetOwnership, TAccountDefenderFleetOwnership, TAccountAttackerFactionAccount, TAccountAttackerRewardsRegistry, TAccountAttackerRewardsConfig, TAccountAttackerRewardsEpoch, TAccountAttackerRewardsContribution, TAccountDefenderRewardsRegistry, TAccountDefenderRewardsConfig, TAccountDefenderRewardsEpoch, TAccountDefenderRewardsContribution, TAccountAttackerXpBudget, TAccountDefenderXpBudget, TAccountXpBudgetConfig >, config?: { programAddress?: TProgramAddress }, ): AttackFleetInstruction< TProgramAddress, TAccountProfileValidationSigner, TAccountProfileValidationProfile, TAccountProfileValidationCertificate, TAccountProfileValidationProgram, TAccountCharacter, TAccountFleet, TAccountDefendingFleet, TAccountDefenderCharacter, TAccountLoot, TAccountRegionTracker, TAccountGame, TAccountInstructionsSysvar, TAccountRecentSlothashes, TAccountSystemProgram, TAccountAsteroid, TAccountFactionRelationTracker, TAccountCrewBinding, TAccountAttackerFleetOwnership, TAccountDefenderFleetOwnership, TAccountAttackerFactionAccount, TAccountAttackerRewardsRegistry, TAccountAttackerRewardsConfig, TAccountAttackerRewardsEpoch, TAccountAttackerRewardsContribution, TAccountDefenderRewardsRegistry, TAccountDefenderRewardsConfig, TAccountDefenderRewardsEpoch, TAccountDefenderRewardsContribution, TAccountAttackerXpBudget, TAccountDefenderXpBudget, TAccountXpBudgetConfig > { // Program address. const programAddress = config?.programAddress ?? SAGE_PROGRAM_ADDRESS; // Original accounts. const originalAccounts = { profileValidationSigner: { value: input.profileValidationSigner ?? null, isWritable: false, }, profileValidationProfile: { value: input.profileValidationProfile ?? null, isWritable: true, }, profileValidationCertificate: { value: input.profileValidationCertificate ?? null, isWritable: false, }, profileValidationProgram: { value: input.profileValidationProgram ?? null, isWritable: false, }, character: { value: input.character ?? null, isWritable: true }, fleet: { value: input.fleet ?? null, isWritable: true }, defendingFleet: { value: input.defendingFleet ?? null, isWritable: true }, defenderCharacter: { value: input.defenderCharacter ?? null, isWritable: true, }, loot: { value: input.loot ?? null, isWritable: true }, regionTracker: { value: input.regionTracker ?? null, isWritable: false }, game: { value: input.game ?? null, isWritable: false }, instructionsSysvar: { value: input.instructionsSysvar ?? null, isWritable: false, }, recentSlothashes: { value: input.recentSlothashes ?? null, isWritable: false, }, systemProgram: { value: input.systemProgram ?? null, isWritable: false }, asteroid: { value: input.asteroid ?? null, isWritable: true }, factionRelationTracker: { value: input.factionRelationTracker ?? null, isWritable: false, }, crewBinding: { value: input.crewBinding ?? null, isWritable: true }, attackerFleetOwnership: { value: input.attackerFleetOwnership ?? null, isWritable: false, }, defenderFleetOwnership: { value: input.defenderFleetOwnership ?? null, isWritable: false, }, attackerFactionAccount: { value: input.attackerFactionAccount ?? null, isWritable: false, }, attackerRewardsRegistry: { value: input.attackerRewardsRegistry ?? null, isWritable: false, }, attackerRewardsConfig: { value: input.attackerRewardsConfig ?? null, isWritable: false, }, attackerRewardsEpoch: { value: input.attackerRewardsEpoch ?? null, isWritable: true, }, attackerRewardsContribution: { value: input.attackerRewardsContribution ?? null, isWritable: true, }, defenderRewardsRegistry: { value: input.defenderRewardsRegistry ?? null, isWritable: false, }, defenderRewardsConfig: { value: input.defenderRewardsConfig ?? null, isWritable: false, }, defenderRewardsEpoch: { value: input.defenderRewardsEpoch ?? null, isWritable: true, }, defenderRewardsContribution: { value: input.defenderRewardsContribution ?? null, isWritable: true, }, attackerXpBudget: { value: input.attackerXpBudget ?? null, isWritable: true, }, defenderXpBudget: { value: input.defenderXpBudget ?? null, isWritable: true, }, xpBudgetConfig: { value: input.xpBudgetConfig ?? null, isWritable: false }, }; const accounts = originalAccounts as Record< keyof typeof originalAccounts, ResolvedInstructionAccount >; // Original args. const args = { ...input }; // Resolve default values. if (!accounts.profileValidationProgram.value) { accounts.profileValidationProgram.value = 'C4PRoFNroxxzdgeCoM31LJjYRg7kT6ymogSTAT99iD1u' as Address<'C4PRoFNroxxzdgeCoM31LJjYRg7kT6ymogSTAT99iD1u'>; } if (!accounts.instructionsSysvar.value) { accounts.instructionsSysvar.value = 'Sysvar1nstructions1111111111111111111111111' as Address<'Sysvar1nstructions1111111111111111111111111'>; } if (!accounts.systemProgram.value) { accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; } const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); return Object.freeze({ accounts: [ getAccountMeta( 'profileValidationSigner', accounts.profileValidationSigner, ), getAccountMeta( 'profileValidationProfile', accounts.profileValidationProfile, ), getAccountMeta( 'profileValidationCertificate', accounts.profileValidationCertificate, ), getAccountMeta( 'profileValidationProgram', accounts.profileValidationProgram, ), getAccountMeta('character', accounts.character), getAccountMeta('fleet', accounts.fleet), getAccountMeta('defendingFleet', accounts.defendingFleet), getAccountMeta('defenderCharacter', accounts.defenderCharacter), getAccountMeta('loot', accounts.loot), getAccountMeta('regionTracker', accounts.regionTracker), getAccountMeta('game', accounts.game), getAccountMeta('instructionsSysvar', accounts.instructionsSysvar), getAccountMeta('recentSlothashes', accounts.recentSlothashes), getAccountMeta('systemProgram', accounts.systemProgram), getAccountMeta('asteroid', accounts.asteroid), getAccountMeta('factionRelationTracker', accounts.factionRelationTracker), getAccountMeta('crewBinding', accounts.crewBinding), getAccountMeta('attackerFleetOwnership', accounts.attackerFleetOwnership), getAccountMeta('defenderFleetOwnership', accounts.defenderFleetOwnership), getAccountMeta('attackerFactionAccount', accounts.attackerFactionAccount), getAccountMeta( 'attackerRewardsRegistry', accounts.attackerRewardsRegistry, ), getAccountMeta('attackerRewardsConfig', accounts.attackerRewardsConfig), getAccountMeta('attackerRewardsEpoch', accounts.attackerRewardsEpoch), getAccountMeta( 'attackerRewardsContribution', accounts.attackerRewardsContribution, ), getAccountMeta( 'defenderRewardsRegistry', accounts.defenderRewardsRegistry, ), getAccountMeta('defenderRewardsConfig', accounts.defenderRewardsConfig), getAccountMeta('defenderRewardsEpoch', accounts.defenderRewardsEpoch), getAccountMeta( 'defenderRewardsContribution', accounts.defenderRewardsContribution, ), getAccountMeta('attackerXpBudget', accounts.attackerXpBudget), getAccountMeta('defenderXpBudget', accounts.defenderXpBudget), getAccountMeta('xpBudgetConfig', accounts.xpBudgetConfig), ], data: getAttackFleetInstructionDataEncoder().encode( args as AttackFleetInstructionDataArgs, ), programAddress, } as AttackFleetInstruction< TProgramAddress, TAccountProfileValidationSigner, TAccountProfileValidationProfile, TAccountProfileValidationCertificate, TAccountProfileValidationProgram, TAccountCharacter, TAccountFleet, TAccountDefendingFleet, TAccountDefenderCharacter, TAccountLoot, TAccountRegionTracker, TAccountGame, TAccountInstructionsSysvar, TAccountRecentSlothashes, TAccountSystemProgram, TAccountAsteroid, TAccountFactionRelationTracker, TAccountCrewBinding, TAccountAttackerFleetOwnership, TAccountDefenderFleetOwnership, TAccountAttackerFactionAccount, TAccountAttackerRewardsRegistry, TAccountAttackerRewardsConfig, TAccountAttackerRewardsEpoch, TAccountAttackerRewardsContribution, TAccountDefenderRewardsRegistry, TAccountDefenderRewardsConfig, TAccountDefenderRewardsEpoch, TAccountDefenderRewardsContribution, TAccountAttackerXpBudget, TAccountDefenderXpBudget, TAccountXpBudgetConfig >); } export type ParsedAttackFleetInstruction< TProgram extends string = typeof SAGE_PROGRAM_ADDRESS, TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[], > = { programAddress: Address; accounts: { profileValidationSigner: TAccountMetas[0]; profileValidationProfile: TAccountMetas[1]; profileValidationCertificate?: TAccountMetas[2] | undefined; profileValidationProgram: TAccountMetas[3]; /** The character account */ character: TAccountMetas[4]; /** * The `Fleet` account * Must be alive and have normalized crew */ fleet: TAccountMetas[5]; /** * The defending fleet. * Must be alive */ defendingFleet: TAccountMetas[6]; /** The defender's character account */ defenderCharacter: TAccountMetas[7]; /** The loot account */ loot: TAccountMetas[8]; /** Region tracker account */ regionTracker: TAccountMetas[9]; /** The game account */ game: TAccountMetas[10]; /** Solana Instructions Sysvar */ instructionsSysvar: TAccountMetas[11]; /** Recent slot hashes used to seed combat outcome randomness */ recentSlothashes: TAccountMetas[12]; /** The Solana System program */ systemProgram: TAccountMetas[13]; /** * The asteroid that the defending fleet is mining * Must be provided only if the defending fleet is mining */ asteroid?: TAccountMetas[14] | undefined; /** * P3 diplomacy combat-gate (REQUIRED — enforced, non-bypassable). Always passed (one tracker per game, * created by `InitFactionRelationTracker`). When `combat_gating_enabled == 0` the gate is a no-op * (behavior-identical to pre-P3 — same-faction is still enforced by `validate()`'s `!=`); when `1`, it * forbids attacking an Allied/active-Ceasefire faction inside that faction's OWNED territory. */ factionRelationTracker: TAccountMetas[15]; crewBinding?: TAccountMetas[16] | undefined; /** * P5b: the ATTACKER fleet's `FactionOwnership(FLEET)` sidecar (Optional, read-only). Present ⇔ the * attacker is an NPC fleet — it supplies the dynamic controlling faction so `attacker_id` can resolve to * a minor id `> 3` (and the COMBATANT guard can bite). PDA seed-bound to `self.fleet`. Flag-OFF / a * player attack passes `None` ⇒ byte-identical to pre-P5b (the resolution falls back to the legacy enum). * Appended AFTER `crew_binding` so the canonical trailing-optional order is * asteroid → faction_relation_tracker → crew_binding → P5b's three (program-id-sentinel positional decode). */ attackerFleetOwnership?: TAccountMetas[17] | undefined; /** * P5b: the DEFENDER fleet's `FactionOwnership(FLEET)` sidecar (Optional, read-only). Resolves an NPC * defender's TRUE faction so the diplomacy gate + resolved same-faction guard don't mis-resolve it as * Unaligned (id 0). PDA seed-bound to `self.defending_fleet`. */ defenderFleetOwnership?: TAccountMetas[18] | undefined; /** * P5b: the attacker faction's registry account (Optional, read-only) — the COMBATANT capability guard * for a dynamic NPC attacker (`attacker_id > 3`). Its PDA is re-derived from the RESOLVED `attacker_id` * and `ensure_eq!`-bound in `process()`, so a caller can never pass a COMBATANT faction's account while * flying a non-COMBATANT faction's fleet. */ attackerFactionAccount?: TAccountMetas[19] | undefined; attackerRewardsRegistry: TAccountMetas[20]; attackerRewardsConfig: TAccountMetas[21]; attackerRewardsEpoch?: TAccountMetas[22] | undefined; attackerRewardsContribution?: TAccountMetas[23] | undefined; defenderRewardsRegistry: TAccountMetas[24]; defenderRewardsConfig: TAccountMetas[25]; defenderRewardsEpoch?: TAccountMetas[26] | undefined; defenderRewardsContribution?: TAccountMetas[27] | undefined; attackerXpBudget?: TAccountMetas[28] | undefined; defenderXpBudget?: TAccountMetas[29] | undefined; /** Game-scoped v1 budgets + earning rules (required on v1 games). */ xpBudgetConfig?: TAccountMetas[30] | undefined; }; data: AttackFleetInstructionData; }; export function parseAttackFleetInstruction< TProgram extends string, TAccountMetas extends readonly AccountMeta[], >( instruction: Instruction & InstructionWithAccounts & InstructionWithData, ): ParsedAttackFleetInstruction { if (instruction.accounts.length < 31) { throw new SolanaError( SOLANA_ERROR__PROGRAM_CLIENTS__INSUFFICIENT_ACCOUNT_METAS, { actualAccountMetas: instruction.accounts.length, expectedAccountMetas: 31, }, ); } let accountIndex = 0; const getNextAccount = () => { const accountMeta = (instruction.accounts as TAccountMetas)[accountIndex]!; accountIndex += 1; return accountMeta; }; const getNextOptionalAccount = () => { const accountMeta = getNextAccount(); return accountMeta.address === SAGE_PROGRAM_ADDRESS ? undefined : accountMeta; }; return { programAddress: instruction.programAddress, accounts: { profileValidationSigner: getNextAccount(), profileValidationProfile: getNextAccount(), profileValidationCertificate: getNextOptionalAccount(), profileValidationProgram: getNextAccount(), character: getNextAccount(), fleet: getNextAccount(), defendingFleet: getNextAccount(), defenderCharacter: getNextAccount(), loot: getNextAccount(), regionTracker: getNextAccount(), game: getNextAccount(), instructionsSysvar: getNextAccount(), recentSlothashes: getNextAccount(), systemProgram: getNextAccount(), asteroid: getNextOptionalAccount(), factionRelationTracker: getNextAccount(), crewBinding: getNextOptionalAccount(), attackerFleetOwnership: getNextOptionalAccount(), defenderFleetOwnership: getNextOptionalAccount(), attackerFactionAccount: getNextOptionalAccount(), attackerRewardsRegistry: getNextAccount(), attackerRewardsConfig: getNextAccount(), attackerRewardsEpoch: getNextOptionalAccount(), attackerRewardsContribution: getNextOptionalAccount(), defenderRewardsRegistry: getNextAccount(), defenderRewardsConfig: getNextAccount(), defenderRewardsEpoch: getNextOptionalAccount(), defenderRewardsContribution: getNextOptionalAccount(), attackerXpBudget: getNextOptionalAccount(), defenderXpBudget: getNextOptionalAccount(), xpBudgetConfig: getNextOptionalAccount(), }, data: getAttackFleetInstructionDataDecoder().decode(instruction.data), }; }