@aephia/atlas-kit 0.6.0-next.99 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cargo/actions/deposit.d.ts +4 -1
- package/dist/cargo/actions/deposit.d.ts.map +1 -1
- package/dist/cargo/actions/deposit.js +56 -133
- package/dist/cargo/actions/deposit.js.map +1 -1
- package/dist/cargo/actions/index.d.ts +14 -7
- package/dist/cargo/actions/index.d.ts.map +1 -1
- package/dist/cargo/actions/index.js +101 -89
- package/dist/cargo/actions/index.js.map +1 -1
- package/dist/cargo/actions/wallet-context.d.ts +52 -3
- package/dist/cargo/actions/wallet-context.d.ts.map +1 -1
- package/dist/cargo/actions/wallet-context.js +118 -7
- package/dist/cargo/actions/wallet-context.js.map +1 -1
- package/dist/cargo/actions/wallet-token.d.ts +1 -6
- package/dist/cargo/actions/wallet-token.d.ts.map +1 -1
- package/dist/cargo/actions/wallet-token.js +0 -45
- package/dist/cargo/actions/wallet-token.js.map +1 -1
- package/dist/cargo/actions/withdrawal.d.ts +1 -1
- package/dist/cargo/actions/withdrawal.d.ts.map +1 -1
- package/dist/cargo/actions/withdrawal.js +37 -163
- package/dist/cargo/actions/withdrawal.js.map +1 -1
- package/dist/cargo/index.d.ts.map +1 -1
- package/dist/cargo/index.js +2 -10
- package/dist/cargo/index.js.map +1 -1
- package/dist/claim-stakes/actions/index.d.ts +80 -14
- package/dist/claim-stakes/actions/index.d.ts.map +1 -1
- package/dist/claim-stakes/actions/index.js +660 -709
- package/dist/claim-stakes/actions/index.js.map +1 -1
- package/dist/claim-stakes/index.d.ts +8 -6
- package/dist/claim-stakes/index.d.ts.map +1 -1
- package/dist/claim-stakes/index.js +12 -18
- package/dist/claim-stakes/index.js.map +1 -1
- package/dist/client/context.d.ts.map +1 -1
- package/dist/client/context.js +353 -37
- package/dist/client/context.js.map +1 -1
- package/dist/client/contracts.d.ts +54 -1
- package/dist/client/contracts.d.ts.map +1 -1
- package/dist/client/deployments.d.ts +17 -0
- package/dist/client/deployments.d.ts.map +1 -1
- package/dist/client/deployments.js +17 -0
- package/dist/client/deployments.js.map +1 -1
- package/dist/client/index.d.ts +22 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +21 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/rpc-subscription-provider.d.ts +2 -0
- package/dist/client/rpc-subscription-provider.d.ts.map +1 -1
- package/dist/client/rpc-subscription-provider.js +135 -101
- package/dist/client/rpc-subscription-provider.js.map +1 -1
- package/dist/combat/actions/index.d.ts +30 -12
- package/dist/combat/actions/index.d.ts.map +1 -1
- package/dist/combat/actions/index.js +264 -252
- package/dist/combat/actions/index.js.map +1 -1
- package/dist/combat/index.d.ts +25 -8
- package/dist/combat/index.d.ts.map +1 -1
- package/dist/combat/index.js +21 -18
- package/dist/combat/index.js.map +1 -1
- package/dist/crafting/actions/fee-rate.d.ts +47 -0
- package/dist/crafting/actions/fee-rate.d.ts.map +1 -0
- package/dist/crafting/actions/fee-rate.js +58 -0
- package/dist/crafting/actions/fee-rate.js.map +1 -0
- package/dist/crafting/actions/index.d.ts +28 -28
- package/dist/crafting/actions/index.d.ts.map +1 -1
- package/dist/crafting/actions/index.js +243 -314
- package/dist/crafting/actions/index.js.map +1 -1
- package/dist/crafting/estimate.d.ts +101 -0
- package/dist/crafting/estimate.d.ts.map +1 -0
- package/dist/crafting/estimate.js +108 -0
- package/dist/crafting/estimate.js.map +1 -0
- package/dist/crafting/index.d.ts +6 -5
- package/dist/crafting/index.d.ts.map +1 -1
- package/dist/crafting/index.js +6 -13
- package/dist/crafting/index.js.map +1 -1
- package/dist/factions/actions/index.d.ts +1 -1
- package/dist/factions/actions/index.d.ts.map +1 -1
- package/dist/factions/actions/index.js +5 -4
- package/dist/factions/actions/index.js.map +1 -1
- package/dist/factions/index.d.ts +18 -1
- package/dist/factions/index.d.ts.map +1 -1
- package/dist/factions/index.js +24 -18
- package/dist/factions/index.js.map +1 -1
- package/dist/fleets/actions/add-ship.d.ts +18 -5
- package/dist/fleets/actions/add-ship.d.ts.map +1 -1
- package/dist/fleets/actions/add-ship.js +35 -48
- package/dist/fleets/actions/add-ship.js.map +1 -1
- package/dist/fleets/actions/create-fleet.d.ts +1 -1
- package/dist/fleets/actions/create-fleet.d.ts.map +1 -1
- package/dist/fleets/actions/create-fleet.js +8 -38
- package/dist/fleets/actions/create-fleet.js.map +1 -1
- package/dist/fleets/actions/crew-transfer.d.ts +8 -4
- package/dist/fleets/actions/crew-transfer.d.ts.map +1 -1
- package/dist/fleets/actions/crew-transfer.js +27 -42
- package/dist/fleets/actions/crew-transfer.js.map +1 -1
- package/dist/fleets/actions/deployment-storage.d.ts +161 -0
- package/dist/fleets/actions/deployment-storage.d.ts.map +1 -0
- package/dist/fleets/actions/deployment-storage.js +297 -0
- package/dist/fleets/actions/deployment-storage.js.map +1 -0
- package/dist/fleets/actions/disband.d.ts +42 -0
- package/dist/fleets/actions/disband.d.ts.map +1 -0
- package/dist/fleets/actions/disband.js +107 -0
- package/dist/fleets/actions/disband.js.map +1 -0
- package/dist/fleets/actions/index.d.ts +55 -11
- package/dist/fleets/actions/index.d.ts.map +1 -1
- package/dist/fleets/actions/index.js +282 -235
- package/dist/fleets/actions/index.js.map +1 -1
- package/dist/fleets/actions/respawn.d.ts +1 -1
- package/dist/fleets/actions/respawn.d.ts.map +1 -1
- package/dist/fleets/actions/respawn.js +8 -37
- package/dist/fleets/actions/respawn.js.map +1 -1
- package/dist/fleets/actions/ship-import.d.ts +1 -1
- package/dist/fleets/actions/ship-import.d.ts.map +1 -1
- package/dist/fleets/actions/ship-import.js +39 -91
- package/dist/fleets/actions/ship-import.js.map +1 -1
- package/dist/fleets/actions/sync.d.ts +24 -0
- package/dist/fleets/actions/sync.d.ts.map +1 -0
- package/dist/fleets/actions/sync.js +55 -0
- package/dist/fleets/actions/sync.js.map +1 -0
- package/dist/fleets/composition-stats.d.ts +101 -0
- package/dist/fleets/composition-stats.d.ts.map +1 -0
- package/dist/fleets/composition-stats.js +354 -0
- package/dist/fleets/composition-stats.js.map +1 -0
- package/dist/fleets/cooldown.d.ts +7 -4
- package/dist/fleets/cooldown.d.ts.map +1 -1
- package/dist/fleets/cooldown.js +11 -6
- package/dist/fleets/cooldown.js.map +1 -1
- package/dist/fleets/index.d.ts +1 -0
- package/dist/fleets/index.d.ts.map +1 -1
- package/dist/fleets/index.js +3 -10
- package/dist/fleets/index.js.map +1 -1
- package/dist/fleets/movement-arithmetic.d.ts.map +1 -1
- package/dist/fleets/movement-arithmetic.js +4 -0
- package/dist/fleets/movement-arithmetic.js.map +1 -1
- package/dist/fleets/subwarp-estimate.d.ts +3 -1
- package/dist/fleets/subwarp-estimate.d.ts.map +1 -1
- package/dist/fleets/subwarp-estimate.js +3 -1
- package/dist/fleets/subwarp-estimate.js.map +1 -1
- package/dist/fleets/warp-lane-policy.d.ts +13 -7
- package/dist/fleets/warp-lane-policy.d.ts.map +1 -1
- package/dist/fleets/warp-lane-policy.js +19 -7
- package/dist/fleets/warp-lane-policy.js.map +1 -1
- package/dist/identity/actions/create-profile.d.ts +1 -1
- package/dist/identity/actions/create-profile.d.ts.map +1 -1
- package/dist/identity/actions/create-profile.js +2 -2
- package/dist/identity/actions/create-profile.js.map +1 -1
- package/dist/identity/actions/index.d.ts +2 -1
- package/dist/identity/actions/index.d.ts.map +1 -1
- package/dist/identity/actions/index.js +6 -4
- package/dist/identity/actions/index.js.map +1 -1
- package/dist/identity/actions/research-unlock.d.ts +61 -0
- package/dist/identity/actions/research-unlock.d.ts.map +1 -0
- package/dist/identity/actions/research-unlock.js +166 -0
- package/dist/identity/actions/research-unlock.js.map +1 -0
- package/dist/identity/index.d.ts +62 -2
- package/dist/identity/index.d.ts.map +1 -1
- package/dist/identity/index.js +63 -12
- package/dist/identity/index.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/internal/c4/account-decoding.d.ts +49 -0
- package/dist/internal/c4/account-decoding.d.ts.map +1 -0
- package/dist/internal/c4/account-decoding.js +74 -0
- package/dist/internal/c4/account-decoding.js.map +1 -0
- package/dist/internal/c4/career-xp.d.ts +58 -0
- package/dist/internal/c4/career-xp.d.ts.map +1 -0
- package/dist/internal/c4/career-xp.js +80 -0
- package/dist/internal/c4/career-xp.js.map +1 -0
- package/dist/internal/c4/cargo-instructions.d.ts +24 -0
- package/dist/internal/c4/cargo-instructions.d.ts.map +1 -0
- package/dist/internal/c4/cargo-instructions.js +30 -0
- package/dist/internal/c4/cargo-instructions.js.map +1 -0
- package/dist/internal/c4/cargo-pod.d.ts +15 -0
- package/dist/internal/c4/cargo-pod.d.ts.map +1 -0
- package/dist/internal/c4/cargo-pod.js +13 -0
- package/dist/internal/c4/cargo-pod.js.map +1 -0
- package/dist/internal/c4/character-modifier.d.ts +1 -1
- package/dist/internal/c4/character-modifier.d.ts.map +1 -1
- package/dist/internal/c4/character.d.ts +157 -0
- package/dist/internal/c4/character.d.ts.map +1 -0
- package/dist/internal/c4/character.js +64 -0
- package/dist/internal/c4/character.js.map +1 -0
- package/dist/internal/c4/claim-stake-building-definitions.d.ts.map +1 -1
- package/dist/internal/c4/claim-stake-building-definitions.js +2 -1
- package/dist/internal/c4/claim-stake-building-definitions.js.map +1 -1
- package/dist/internal/c4/claim-stake-configuration.d.ts.map +1 -1
- package/dist/internal/c4/claim-stake-configuration.js +5 -36
- package/dist/internal/c4/claim-stake-configuration.js.map +1 -1
- package/dist/internal/c4/claim-stake-definitions.d.ts +4 -0
- package/dist/internal/c4/claim-stake-definitions.d.ts.map +1 -1
- package/dist/internal/c4/claim-stake-definitions.js +6 -2
- package/dist/internal/c4/claim-stake-definitions.js.map +1 -1
- package/dist/internal/c4/claim-stake-plots.d.ts +17 -0
- package/dist/internal/c4/claim-stake-plots.d.ts.map +1 -0
- package/dist/internal/c4/claim-stake-plots.js +29 -0
- package/dist/internal/c4/claim-stake-plots.js.map +1 -0
- package/dist/internal/c4/claim-stake-standing.d.ts +80 -0
- package/dist/internal/c4/claim-stake-standing.d.ts.map +1 -0
- package/dist/internal/c4/claim-stake-standing.js +61 -0
- package/dist/internal/c4/claim-stake-standing.js.map +1 -0
- package/dist/internal/c4/claim-stake-storage.d.ts +45 -0
- package/dist/internal/c4/claim-stake-storage.d.ts.map +1 -0
- package/dist/internal/c4/claim-stake-storage.js +207 -0
- package/dist/internal/c4/claim-stake-storage.js.map +1 -0
- package/dist/internal/c4/claim-stake.d.ts +9 -6
- package/dist/internal/c4/claim-stake.d.ts.map +1 -1
- package/dist/internal/c4/claim-stake.js +24 -56
- package/dist/internal/c4/claim-stake.js.map +1 -1
- package/dist/internal/c4/combat-storage.d.ts +20 -0
- package/dist/internal/c4/combat-storage.d.ts.map +1 -0
- package/dist/internal/c4/combat-storage.js +43 -0
- package/dist/internal/c4/combat-storage.js.map +1 -0
- package/dist/internal/c4/combat.d.ts +1 -55
- package/dist/internal/c4/combat.d.ts.map +1 -1
- package/dist/internal/c4/combat.js +16 -180
- package/dist/internal/c4/combat.js.map +1 -1
- package/dist/internal/c4/crafting-storage.d.ts +20 -0
- package/dist/internal/c4/crafting-storage.d.ts.map +1 -0
- package/dist/internal/c4/crafting-storage.js +54 -0
- package/dist/internal/c4/crafting-storage.js.map +1 -0
- package/dist/internal/c4/crafting.d.ts +9 -1
- package/dist/internal/c4/crafting.d.ts.map +1 -1
- package/dist/internal/c4/crafting.js +38 -98
- package/dist/internal/c4/crafting.js.map +1 -1
- package/dist/internal/c4/currency-cache.d.ts +1 -1
- package/dist/internal/c4/currency-cache.d.ts.map +1 -1
- package/dist/internal/c4/currency-cache.js +6 -9
- package/dist/internal/c4/currency-cache.js.map +1 -1
- package/dist/internal/c4/discriminators.d.ts +93 -0
- package/dist/internal/c4/discriminators.d.ts.map +1 -0
- package/dist/internal/c4/discriminators.js +190 -0
- package/dist/internal/c4/discriminators.js.map +1 -0
- package/dist/internal/c4/faction-epoch-meter.d.ts.map +1 -1
- package/dist/internal/c4/faction-epoch-meter.js +5 -10
- package/dist/internal/c4/faction-epoch-meter.js.map +1 -1
- package/dist/internal/c4/faction-treasury.d.ts.map +1 -1
- package/dist/internal/c4/faction-treasury.js +11 -18
- package/dist/internal/c4/faction-treasury.js.map +1 -1
- package/dist/internal/c4/faction.d.ts +21 -0
- package/dist/internal/c4/faction.d.ts.map +1 -0
- package/dist/internal/c4/faction.js +23 -0
- package/dist/internal/c4/faction.js.map +1 -0
- package/dist/internal/c4/factions.d.ts +31 -3
- package/dist/internal/c4/factions.d.ts.map +1 -1
- package/dist/internal/c4/factions.js +103 -104
- package/dist/internal/c4/factions.js.map +1 -1
- package/dist/internal/c4/fleet-creation.d.ts +9 -2
- package/dist/internal/c4/fleet-creation.d.ts.map +1 -1
- package/dist/internal/c4/fleet-creation.js +15 -18
- package/dist/internal/c4/fleet-creation.js.map +1 -1
- package/dist/internal/c4/fleet-crew-binding.d.ts.map +1 -1
- package/dist/internal/c4/fleet-crew-binding.js +21 -49
- package/dist/internal/c4/fleet-crew-binding.js.map +1 -1
- package/dist/internal/c4/fleet-disband-layout.d.ts +7 -0
- package/dist/internal/c4/fleet-disband-layout.d.ts.map +1 -0
- package/dist/internal/c4/fleet-disband-layout.js +7 -0
- package/dist/internal/c4/fleet-disband-layout.js.map +1 -0
- package/dist/internal/c4/fleet-disband.d.ts +41 -0
- package/dist/internal/c4/fleet-disband.d.ts.map +1 -0
- package/dist/internal/c4/fleet-disband.js +86 -0
- package/dist/internal/c4/fleet-disband.js.map +1 -0
- package/dist/internal/c4/fleet-points.d.ts +3 -0
- package/dist/internal/c4/fleet-points.d.ts.map +1 -0
- package/dist/internal/c4/fleet-points.js +8 -0
- package/dist/internal/c4/fleet-points.js.map +1 -0
- package/dist/internal/c4/fleet-ship-assembly.d.ts +20 -5
- package/dist/internal/c4/fleet-ship-assembly.d.ts.map +1 -1
- package/dist/internal/c4/fleet-ship-assembly.js +62 -10
- package/dist/internal/c4/fleet-ship-assembly.js.map +1 -1
- package/dist/internal/c4/fleet-storage.d.ts +44 -0
- package/dist/internal/c4/fleet-storage.d.ts.map +1 -0
- package/dist/internal/c4/fleet-storage.js +108 -0
- package/dist/internal/c4/fleet-storage.js.map +1 -0
- package/dist/internal/c4/fleet-sync.d.ts +5 -0
- package/dist/internal/c4/fleet-sync.d.ts.map +1 -0
- package/dist/internal/c4/fleet-sync.js +15 -0
- package/dist/internal/c4/fleet-sync.js.map +1 -0
- package/dist/internal/c4/fleet.d.ts +20 -5
- package/dist/internal/c4/fleet.d.ts.map +1 -1
- package/dist/internal/c4/fleet.js +24 -84
- package/dist/internal/c4/fleet.js.map +1 -1
- package/dist/internal/c4/game.d.ts +76 -21
- package/dist/internal/c4/game.d.ts.map +1 -1
- package/dist/internal/c4/game.js +127 -116
- package/dist/internal/c4/game.js.map +1 -1
- package/dist/internal/c4/identity.d.ts +2 -153
- package/dist/internal/c4/identity.d.ts.map +1 -1
- package/dist/internal/c4/identity.js +19 -126
- package/dist/internal/c4/identity.js.map +1 -1
- package/dist/internal/c4/local-market-order.d.ts +4 -6
- package/dist/internal/c4/local-market-order.d.ts.map +1 -1
- package/dist/internal/c4/local-market-order.js +5 -6
- package/dist/internal/c4/local-market-order.js.map +1 -1
- package/dist/internal/c4/loot-layout.js +1 -1
- package/dist/internal/c4/loot-layout.js.map +1 -1
- package/dist/internal/c4/loot.d.ts +89 -0
- package/dist/internal/c4/loot.d.ts.map +1 -0
- package/dist/internal/c4/loot.js +109 -0
- package/dist/internal/c4/loot.js.map +1 -0
- package/dist/internal/c4/loyalty.d.ts +7 -3
- package/dist/internal/c4/loyalty.d.ts.map +1 -1
- package/dist/internal/c4/loyalty.js +41 -130
- package/dist/internal/c4/loyalty.js.map +1 -1
- package/dist/internal/c4/market-storage.d.ts +25 -0
- package/dist/internal/c4/market-storage.d.ts.map +1 -0
- package/dist/internal/c4/market-storage.js +53 -0
- package/dist/internal/c4/market-storage.js.map +1 -0
- package/dist/internal/c4/market.d.ts +3 -0
- package/dist/internal/c4/market.d.ts.map +1 -1
- package/dist/internal/c4/market.js +20 -76
- package/dist/internal/c4/market.js.map +1 -1
- package/dist/internal/c4/mining-instructions.d.ts +1 -1
- package/dist/internal/c4/mining-instructions.d.ts.map +1 -1
- package/dist/internal/c4/mining-instructions.js +1 -1
- package/dist/internal/c4/mining-instructions.js.map +1 -1
- package/dist/internal/c4/open-signal.d.ts +1 -1
- package/dist/internal/c4/open-signal.d.ts.map +1 -1
- package/dist/internal/c4/open-signal.js +1 -1
- package/dist/internal/c4/open-signal.js.map +1 -1
- package/dist/internal/c4/pda.d.ts +49 -1
- package/dist/internal/c4/pda.d.ts.map +1 -1
- package/dist/internal/c4/pda.js +122 -17
- package/dist/internal/c4/pda.js.map +1 -1
- package/dist/internal/c4/profile-faction.d.ts +2 -1
- package/dist/internal/c4/profile-faction.d.ts.map +1 -1
- package/dist/internal/c4/profile-faction.js +36 -72
- package/dist/internal/c4/profile-faction.js.map +1 -1
- package/dist/internal/c4/profile-permissions.d.ts +1 -1
- package/dist/internal/c4/profile-permissions.d.ts.map +1 -1
- package/dist/internal/c4/profile-permissions.js +16 -1
- package/dist/internal/c4/profile-permissions.js.map +1 -1
- package/dist/internal/c4/rewards.d.ts +1 -34
- package/dist/internal/c4/rewards.d.ts.map +1 -1
- package/dist/internal/c4/rewards.js +23 -170
- package/dist/internal/c4/rewards.js.map +1 -1
- package/dist/internal/c4/runtime-bindings.d.ts +1 -1
- package/dist/internal/c4/runtime-bindings.d.ts.map +1 -1
- package/dist/internal/c4/runtime-bindings.js +1 -1
- package/dist/internal/c4/runtime-bindings.js.map +1 -1
- package/dist/internal/c4/scan-lifecycle.d.ts +21 -3
- package/dist/internal/c4/scan-lifecycle.d.ts.map +1 -1
- package/dist/internal/c4/scan-lifecycle.js +35 -44
- package/dist/internal/c4/scan-lifecycle.js.map +1 -1
- package/dist/internal/c4/scan-storage.d.ts +7 -0
- package/dist/internal/c4/scan-storage.d.ts.map +1 -0
- package/dist/internal/c4/scan-storage.js +10 -0
- package/dist/internal/c4/scan-storage.js.map +1 -0
- package/dist/internal/c4/scanning.d.ts +3 -13
- package/dist/internal/c4/scanning.d.ts.map +1 -1
- package/dist/internal/c4/scanning.js +25 -75
- package/dist/internal/c4/scanning.js.map +1 -1
- package/dist/internal/c4/ship-stats.d.ts.map +1 -1
- package/dist/internal/c4/ship-stats.js +24 -26
- package/dist/internal/c4/ship-stats.js.map +1 -1
- package/dist/internal/c4/starbase.d.ts.map +1 -1
- package/dist/internal/c4/starbase.js +24 -96
- package/dist/internal/c4/starbase.js.map +1 -1
- package/dist/internal/c4/stimulant.d.ts +26 -0
- package/dist/internal/c4/stimulant.d.ts.map +1 -0
- package/dist/internal/c4/stimulant.js +36 -0
- package/dist/internal/c4/stimulant.js.map +1 -0
- package/dist/internal/c4/wallet-cargo-cache.js +2 -1
- package/dist/internal/c4/wallet-cargo-cache.js.map +1 -1
- package/dist/internal/c4/world.d.ts +6 -2
- package/dist/internal/c4/world.d.ts.map +1 -1
- package/dist/internal/c4/world.js +32 -107
- package/dist/internal/c4/world.js.map +1 -1
- package/dist/internal/fleet-route.d.ts +12 -0
- package/dist/internal/fleet-route.d.ts.map +1 -0
- package/dist/internal/fleet-route.js +11 -0
- package/dist/internal/fleet-route.js.map +1 -0
- package/dist/internal/fleet.d.ts +3 -3
- package/dist/internal/fleet.d.ts.map +1 -1
- package/dist/internal/fleet.js +1 -5
- package/dist/internal/fleet.js.map +1 -1
- package/dist/internal/loyalty-atlas-bank-state.d.ts +3 -2
- package/dist/internal/loyalty-atlas-bank-state.d.ts.map +1 -1
- package/dist/internal/loyalty-atlas-bank-state.js +4 -3
- package/dist/internal/loyalty-atlas-bank-state.js.map +1 -1
- package/dist/internal/planning/account-state.d.ts +6 -0
- package/dist/internal/planning/account-state.d.ts.map +1 -1
- package/dist/internal/planning/account-state.js +13 -0
- package/dist/internal/planning/account-state.js.map +1 -1
- package/dist/internal/planning/arrival-guards.d.ts +0 -1
- package/dist/internal/planning/arrival-guards.d.ts.map +1 -1
- package/dist/internal/planning/arrival-guards.js +3 -18
- package/dist/internal/planning/arrival-guards.js.map +1 -1
- package/dist/internal/planning/authorization-adapter.d.ts +34 -11
- package/dist/internal/planning/authorization-adapter.d.ts.map +1 -1
- package/dist/internal/planning/authorization-adapter.js +116 -12
- package/dist/internal/planning/authorization-adapter.js.map +1 -1
- package/dist/internal/planning/cargo-storage-actions.d.ts +8 -0
- package/dist/internal/planning/cargo-storage-actions.d.ts.map +1 -0
- package/dist/internal/planning/cargo-storage-actions.js +97 -0
- package/dist/internal/planning/cargo-storage-actions.js.map +1 -0
- package/dist/internal/planning/character-access.d.ts +28 -0
- package/dist/internal/planning/character-access.d.ts.map +1 -0
- package/dist/internal/planning/character-access.js +41 -0
- package/dist/internal/planning/character-access.js.map +1 -0
- package/dist/internal/planning/character-registration-guard.d.ts.map +1 -1
- package/dist/internal/planning/character-registration-guard.js +2 -1
- package/dist/internal/planning/character-registration-guard.js.map +1 -1
- package/dist/internal/planning/character-registration.d.ts.map +1 -1
- package/dist/internal/planning/character-registration.js +2 -1
- package/dist/internal/planning/character-registration.js.map +1 -1
- package/dist/internal/planning/claim-stake-storage-actions.d.ts +12 -0
- package/dist/internal/planning/claim-stake-storage-actions.d.ts.map +1 -0
- package/dist/internal/planning/claim-stake-storage-actions.js +63 -0
- package/dist/internal/planning/claim-stake-storage-actions.js.map +1 -0
- package/dist/internal/planning/combat-storage-actions.d.ts +9 -0
- package/dist/internal/planning/combat-storage-actions.d.ts.map +1 -0
- package/dist/internal/planning/combat-storage-actions.js +55 -0
- package/dist/internal/planning/combat-storage-actions.js.map +1 -0
- package/dist/internal/planning/crafting-storage-actions.d.ts +7 -0
- package/dist/internal/planning/crafting-storage-actions.d.ts.map +1 -0
- package/dist/internal/planning/crafting-storage-actions.js +64 -0
- package/dist/internal/planning/crafting-storage-actions.js.map +1 -0
- package/dist/internal/planning/currency-cache-guard.d.ts +3 -1
- package/dist/internal/planning/currency-cache-guard.d.ts.map +1 -1
- package/dist/internal/planning/currency-cache-guard.js +47 -2
- package/dist/internal/planning/currency-cache-guard.js.map +1 -1
- package/dist/internal/planning/democracy-history.d.ts.map +1 -1
- package/dist/internal/planning/democracy-history.js +6 -15
- package/dist/internal/planning/democracy-history.js.map +1 -1
- package/dist/internal/planning/direct-options.d.ts +17 -0
- package/dist/internal/planning/direct-options.d.ts.map +1 -0
- package/dist/internal/planning/direct-options.js +43 -0
- package/dist/internal/planning/direct-options.js.map +1 -0
- package/dist/internal/planning/disband-storage-actions.d.ts +9 -0
- package/dist/internal/planning/disband-storage-actions.d.ts.map +1 -0
- package/dist/internal/planning/disband-storage-actions.js +24 -0
- package/dist/internal/planning/disband-storage-actions.js.map +1 -0
- package/dist/internal/planning/faction-enrollment.d.ts +0 -2
- package/dist/internal/planning/faction-enrollment.d.ts.map +1 -1
- package/dist/internal/planning/faction-enrollment.js +0 -9
- package/dist/internal/planning/faction-enrollment.js.map +1 -1
- package/dist/internal/planning/fleet-arrival.d.ts.map +1 -1
- package/dist/internal/planning/fleet-arrival.js +10 -8
- package/dist/internal/planning/fleet-arrival.js.map +1 -1
- package/dist/internal/planning/fleet-attack-xp.d.ts.map +1 -1
- package/dist/internal/planning/fleet-attack-xp.js +5 -11
- package/dist/internal/planning/fleet-attack-xp.js.map +1 -1
- package/dist/internal/planning/fleet-creation.d.ts.map +1 -1
- package/dist/internal/planning/fleet-creation.js +17 -36
- package/dist/internal/planning/fleet-creation.js.map +1 -1
- package/dist/internal/planning/fleet-crew-guard.d.ts +2 -1
- package/dist/internal/planning/fleet-crew-guard.d.ts.map +1 -1
- package/dist/internal/planning/fleet-crew-guard.js +2 -1
- package/dist/internal/planning/fleet-crew-guard.js.map +1 -1
- package/dist/internal/planning/fleet-crew-transfer.d.ts +1 -1
- package/dist/internal/planning/fleet-crew-transfer.d.ts.map +1 -1
- package/dist/internal/planning/fleet-crew-transfer.js +45 -24
- package/dist/internal/planning/fleet-crew-transfer.js.map +1 -1
- package/dist/internal/planning/fleet-disband-guard.d.ts +12 -0
- package/dist/internal/planning/fleet-disband-guard.d.ts.map +1 -0
- package/dist/internal/planning/fleet-disband-guard.js +54 -0
- package/dist/internal/planning/fleet-disband-guard.js.map +1 -0
- package/dist/internal/planning/fleet-disband.d.ts +36 -0
- package/dist/internal/planning/fleet-disband.d.ts.map +1 -0
- package/dist/internal/planning/fleet-disband.js +82 -0
- package/dist/internal/planning/fleet-disband.js.map +1 -0
- package/dist/internal/planning/fleet-dock-funding-guard.d.ts +3 -3
- package/dist/internal/planning/fleet-dock-funding-guard.d.ts.map +1 -1
- package/dist/internal/planning/fleet-dock-funding-guard.js +87 -96
- package/dist/internal/planning/fleet-dock-funding-guard.js.map +1 -1
- package/dist/internal/planning/fleet-dock-funding.d.ts.map +1 -1
- package/dist/internal/planning/fleet-dock-funding.js +10 -0
- package/dist/internal/planning/fleet-dock-funding.js.map +1 -1
- package/dist/internal/planning/fleet-docking-guard.d.ts.map +1 -1
- package/dist/internal/planning/fleet-docking-guard.js +3 -1
- package/dist/internal/planning/fleet-docking-guard.js.map +1 -1
- package/dist/internal/planning/fleet-docking.d.ts +17 -2
- package/dist/internal/planning/fleet-docking.d.ts.map +1 -1
- package/dist/internal/planning/fleet-docking.js +83 -62
- package/dist/internal/planning/fleet-docking.js.map +1 -1
- package/dist/internal/planning/fleet-rental.d.ts +5 -0
- package/dist/internal/planning/fleet-rental.d.ts.map +1 -0
- package/dist/internal/planning/fleet-rental.js +9 -0
- package/dist/internal/planning/fleet-rental.js.map +1 -0
- package/dist/internal/planning/fleet-respawn.d.ts.map +1 -1
- package/dist/internal/planning/fleet-respawn.js +10 -12
- package/dist/internal/planning/fleet-respawn.js.map +1 -1
- package/dist/internal/planning/fleet-ship-assembly.d.ts +2 -0
- package/dist/internal/planning/fleet-ship-assembly.d.ts.map +1 -1
- package/dist/internal/planning/fleet-ship-assembly.js +94 -64
- package/dist/internal/planning/fleet-ship-assembly.js.map +1 -1
- package/dist/internal/planning/fleet-state.d.ts +25 -0
- package/dist/internal/planning/fleet-state.d.ts.map +1 -0
- package/dist/internal/planning/fleet-state.js +28 -0
- package/dist/internal/planning/fleet-state.js.map +1 -0
- package/dist/internal/planning/governance-fees.d.ts.map +1 -1
- package/dist/internal/planning/governance-fees.js +7 -15
- package/dist/internal/planning/governance-fees.js.map +1 -1
- package/dist/internal/planning/local-market-order-funding.d.ts.map +1 -1
- package/dist/internal/planning/local-market-order-funding.js +4 -2
- package/dist/internal/planning/local-market-order-funding.js.map +1 -1
- package/dist/internal/planning/local-market-order.d.ts +4 -4
- package/dist/internal/planning/local-market-order.d.ts.map +1 -1
- package/dist/internal/planning/local-market-order.js +82 -109
- package/dist/internal/planning/local-market-order.js.map +1 -1
- package/dist/internal/planning/market-storage-actions.d.ts +7 -0
- package/dist/internal/planning/market-storage-actions.d.ts.map +1 -0
- package/dist/internal/planning/market-storage-actions.js +71 -0
- package/dist/internal/planning/market-storage-actions.js.map +1 -0
- package/dist/internal/planning/mining-stop.d.ts.map +1 -1
- package/dist/internal/planning/mining-stop.js +2 -1
- package/dist/internal/planning/mining-stop.js.map +1 -1
- package/dist/internal/planning/mining-storage-actions.d.ts +11 -0
- package/dist/internal/planning/mining-storage-actions.d.ts.map +1 -0
- package/dist/internal/planning/mining-storage-actions.js +57 -0
- package/dist/internal/planning/mining-storage-actions.js.map +1 -0
- package/dist/internal/planning/movement-storage-actions.d.ts +7 -0
- package/dist/internal/planning/movement-storage-actions.d.ts.map +1 -0
- package/dist/internal/planning/movement-storage-actions.js +38 -0
- package/dist/internal/planning/movement-storage-actions.js.map +1 -0
- package/dist/internal/planning/movement-xp-guard.d.ts.map +1 -1
- package/dist/internal/planning/movement-xp-guard.js +3 -2
- package/dist/internal/planning/movement-xp-guard.js.map +1 -1
- package/dist/internal/planning/open-signal-guard.d.ts.map +1 -1
- package/dist/internal/planning/open-signal-guard.js +2 -1
- package/dist/internal/planning/open-signal-guard.js.map +1 -1
- package/dist/internal/planning/open-signal.d.ts.map +1 -1
- package/dist/internal/planning/open-signal.js +16 -7
- package/dist/internal/planning/open-signal.js.map +1 -1
- package/dist/internal/planning/original-token.d.ts +40 -0
- package/dist/internal/planning/original-token.d.ts.map +1 -0
- package/dist/internal/planning/original-token.js +112 -0
- package/dist/internal/planning/original-token.js.map +1 -0
- package/dist/internal/planning/own-starbase-facts.d.ts +37 -0
- package/dist/internal/planning/own-starbase-facts.d.ts.map +1 -0
- package/dist/internal/planning/own-starbase-facts.js +52 -0
- package/dist/internal/planning/own-starbase-facts.js.map +1 -0
- package/dist/internal/planning/plan-fields.d.ts +60 -0
- package/dist/internal/planning/plan-fields.d.ts.map +1 -0
- package/dist/internal/planning/plan-fields.js +159 -0
- package/dist/internal/planning/plan-fields.js.map +1 -0
- package/dist/internal/planning/plan-guards.d.ts +4 -0
- package/dist/internal/planning/plan-guards.d.ts.map +1 -0
- package/dist/internal/planning/plan-guards.js +184 -0
- package/dist/internal/planning/plan-guards.js.map +1 -0
- package/dist/internal/planning/profile-key.d.ts +13 -0
- package/dist/internal/planning/profile-key.d.ts.map +1 -0
- package/dist/internal/planning/profile-key.js +20 -0
- package/dist/internal/planning/profile-key.js.map +1 -0
- package/dist/internal/planning/profile-storage-funding-guard.d.ts +29 -0
- package/dist/internal/planning/profile-storage-funding-guard.d.ts.map +1 -0
- package/dist/internal/planning/profile-storage-funding-guard.js +115 -0
- package/dist/internal/planning/profile-storage-funding-guard.js.map +1 -0
- package/dist/internal/planning/profile-storage-funding.d.ts +46 -0
- package/dist/internal/planning/profile-storage-funding.d.ts.map +1 -0
- package/dist/internal/planning/profile-storage-funding.js +58 -0
- package/dist/internal/planning/profile-storage-funding.js.map +1 -0
- package/dist/internal/planning/recipe-state.d.ts +4 -1
- package/dist/internal/planning/recipe-state.d.ts.map +1 -1
- package/dist/internal/planning/recipe-state.js +7 -4
- package/dist/internal/planning/recipe-state.js.map +1 -1
- package/dist/internal/planning/region-access.d.ts +30 -0
- package/dist/internal/planning/region-access.d.ts.map +1 -0
- package/dist/internal/planning/region-access.js +94 -0
- package/dist/internal/planning/region-access.js.map +1 -0
- package/dist/internal/planning/rent-catalog.d.ts +37 -0
- package/dist/internal/planning/rent-catalog.d.ts.map +1 -0
- package/dist/internal/planning/rent-catalog.js +165 -0
- package/dist/internal/planning/rent-catalog.js.map +1 -0
- package/dist/internal/planning/research-unlock.d.ts +69 -0
- package/dist/internal/planning/research-unlock.d.ts.map +1 -0
- package/dist/internal/planning/research-unlock.js +287 -0
- package/dist/internal/planning/research-unlock.js.map +1 -0
- package/dist/internal/planning/respawn-guards.js +2 -1
- package/dist/internal/planning/respawn-guards.js.map +1 -1
- package/dist/internal/planning/runtime-guards.d.ts +0 -2
- package/dist/internal/planning/runtime-guards.d.ts.map +1 -1
- package/dist/internal/planning/runtime-guards.js +49 -29
- package/dist/internal/planning/runtime-guards.js.map +1 -1
- package/dist/internal/planning/scan-completion-guard.d.ts +6 -6
- package/dist/internal/planning/scan-completion-guard.d.ts.map +1 -1
- package/dist/internal/planning/scan-completion-guard.js +8 -7
- package/dist/internal/planning/scan-completion-guard.js.map +1 -1
- package/dist/internal/planning/scan-completion.d.ts.map +1 -1
- package/dist/internal/planning/scan-completion.js +9 -7
- package/dist/internal/planning/scan-completion.js.map +1 -1
- package/dist/internal/planning/scan-detect-guard.d.ts +1 -1
- package/dist/internal/planning/scan-detect-guard.d.ts.map +1 -1
- package/dist/internal/planning/scan-detect-guard.js +2 -2
- package/dist/internal/planning/scan-detect-guard.js.map +1 -1
- package/dist/internal/planning/scan-detect.d.ts +1 -1
- package/dist/internal/planning/scan-detect.d.ts.map +1 -1
- package/dist/internal/planning/scan-detect.js +10 -8
- package/dist/internal/planning/scan-detect.js.map +1 -1
- package/dist/internal/planning/scan-idle-scope.d.ts +5 -0
- package/dist/internal/planning/scan-idle-scope.d.ts.map +1 -0
- package/dist/internal/planning/scan-idle-scope.js +5 -0
- package/dist/internal/planning/scan-idle-scope.js.map +1 -0
- package/dist/internal/planning/scan-storage-actions.d.ts +9 -0
- package/dist/internal/planning/scan-storage-actions.d.ts.map +1 -0
- package/dist/internal/planning/scan-storage-actions.js +27 -0
- package/dist/internal/planning/scan-storage-actions.js.map +1 -0
- package/dist/internal/planning/ship-import-funding.js +3 -2
- package/dist/internal/planning/ship-import-funding.js.map +1 -1
- package/dist/internal/planning/ship-token.d.ts +1 -5
- package/dist/internal/planning/ship-token.d.ts.map +1 -1
- package/dist/internal/planning/ship-token.js +0 -36
- package/dist/internal/planning/ship-token.js.map +1 -1
- package/dist/internal/planning/starbase-player-owner.d.ts +21 -0
- package/dist/internal/planning/starbase-player-owner.d.ts.map +1 -0
- package/dist/internal/planning/starbase-player-owner.js +17 -0
- package/dist/internal/planning/starbase-player-owner.js.map +1 -0
- package/dist/internal/planning/starbase-player-recovery-guard.d.ts +7 -0
- package/dist/internal/planning/starbase-player-recovery-guard.d.ts.map +1 -0
- package/dist/internal/planning/starbase-player-recovery-guard.js +39 -0
- package/dist/internal/planning/starbase-player-recovery-guard.js.map +1 -0
- package/dist/internal/planning/starbase-system-guard.d.ts.map +1 -1
- package/dist/internal/planning/starbase-system-guard.js +2 -1
- package/dist/internal/planning/starbase-system-guard.js.map +1 -1
- package/dist/internal/planning/starbase-system.d.ts +5 -2
- package/dist/internal/planning/starbase-system.d.ts.map +1 -1
- package/dist/internal/planning/starbase-system.js +6 -3
- package/dist/internal/planning/starbase-system.js.map +1 -1
- package/dist/internal/planning/storage-action-readers.d.ts +10 -0
- package/dist/internal/planning/storage-action-readers.d.ts.map +1 -0
- package/dist/internal/planning/storage-action-readers.js +58 -0
- package/dist/internal/planning/storage-action-readers.js.map +1 -0
- package/dist/internal/planning/storage-actions.d.ts +89 -0
- package/dist/internal/planning/storage-actions.d.ts.map +1 -0
- package/dist/internal/planning/storage-actions.js +183 -0
- package/dist/internal/planning/storage-actions.js.map +1 -0
- package/dist/internal/planning/token-mint.d.ts.map +1 -1
- package/dist/internal/planning/token-mint.js +2 -1
- package/dist/internal/planning/token-mint.js.map +1 -1
- package/dist/internal/planning/wallet-starbase.d.ts +34 -0
- package/dist/internal/planning/wallet-starbase.d.ts.map +1 -0
- package/dist/internal/planning/wallet-starbase.js +39 -0
- package/dist/internal/planning/wallet-starbase.js.map +1 -0
- package/dist/internal/planning/xp-runtime.d.ts.map +1 -1
- package/dist/internal/planning/xp-runtime.js +16 -20
- package/dist/internal/planning/xp-runtime.js.map +1 -1
- package/dist/internal/read-meta.d.ts +12 -0
- package/dist/internal/read-meta.d.ts.map +1 -1
- package/dist/internal/read-meta.js +10 -0
- package/dist/internal/read-meta.js.map +1 -1
- package/dist/loyalty/actions/index.d.ts +1 -1
- package/dist/loyalty/actions/index.d.ts.map +1 -1
- package/dist/loyalty/actions/index.js +12 -43
- package/dist/loyalty/actions/index.js.map +1 -1
- package/dist/loyalty/index.d.ts +4 -0
- package/dist/loyalty/index.d.ts.map +1 -1
- package/dist/loyalty/index.js +19 -27
- package/dist/loyalty/index.js.map +1 -1
- package/dist/markets/actions/index.d.ts +1 -1
- package/dist/markets/actions/index.d.ts.map +1 -1
- package/dist/markets/actions/index.js +138 -176
- package/dist/markets/actions/index.js.map +1 -1
- package/dist/markets/actions/trade-faction-market.d.ts +4 -2
- package/dist/markets/actions/trade-faction-market.d.ts.map +1 -1
- package/dist/markets/actions/trade-faction-market.js +59 -39
- package/dist/markets/actions/trade-faction-market.js.map +1 -1
- package/dist/markets/index.d.ts.map +1 -1
- package/dist/markets/index.js +3 -11
- package/dist/markets/index.js.map +1 -1
- package/dist/mining/actions/index.d.ts +1 -1
- package/dist/mining/actions/index.d.ts.map +1 -1
- package/dist/mining/actions/index.js +81 -44
- package/dist/mining/actions/index.js.map +1 -1
- package/dist/mining/estimate-input.d.ts +103 -0
- package/dist/mining/estimate-input.d.ts.map +1 -0
- package/dist/mining/estimate-input.js +86 -0
- package/dist/mining/estimate-input.js.map +1 -0
- package/dist/mining/index.d.ts +1 -0
- package/dist/mining/index.d.ts.map +1 -1
- package/dist/mining/index.js +4 -11
- package/dist/mining/index.js.map +1 -1
- package/dist/planning/assembly.d.ts +1 -1
- package/dist/planning/assembly.d.ts.map +1 -1
- package/dist/planning/assembly.js +6 -30
- package/dist/planning/assembly.js.map +1 -1
- package/dist/planning/execution.d.ts +1 -0
- package/dist/planning/execution.d.ts.map +1 -1
- package/dist/planning/execution.js +149 -45
- package/dist/planning/execution.js.map +1 -1
- package/dist/planning/index.d.ts +70 -7
- package/dist/planning/index.d.ts.map +1 -1
- package/dist/planning/index.js +28 -1141
- package/dist/planning/index.js.map +1 -1
- package/dist/planning/plan-construction.d.ts +25 -0
- package/dist/planning/plan-construction.d.ts.map +1 -0
- package/dist/planning/plan-construction.js +143 -0
- package/dist/planning/plan-construction.js.map +1 -0
- package/dist/planning/plan-sequence-execution.d.ts.map +1 -1
- package/dist/planning/plan-sequence-execution.js +1 -11
- package/dist/planning/plan-sequence-execution.js.map +1 -1
- package/dist/planning/plan-validation.d.ts +17 -0
- package/dist/planning/plan-validation.d.ts.map +1 -0
- package/dist/planning/plan-validation.js +147 -0
- package/dist/planning/plan-validation.js.map +1 -0
- package/dist/registry/cargo.d.ts +2 -2
- package/dist/registry/cargo.d.ts.map +1 -1
- package/dist/registry/cargo.js +3 -4
- package/dist/registry/cargo.js.map +1 -1
- package/dist/registry/definition-section-snapshot.d.ts +1 -1
- package/dist/registry/definition-section-snapshot.d.ts.map +1 -1
- package/dist/registry/definition-section-snapshot.js +10 -3
- package/dist/registry/definition-section-snapshot.js.map +1 -1
- package/dist/registry/index.d.ts +31 -4
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +226 -227
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/onboarding.d.ts.map +1 -1
- package/dist/registry/onboarding.js +4 -2
- package/dist/registry/onboarding.js.map +1 -1
- package/dist/registry/ship-stats-snapshot.d.ts.map +1 -1
- package/dist/registry/ship-stats-snapshot.js +19 -5
- package/dist/registry/ship-stats-snapshot.js.map +1 -1
- package/dist/registry/ships.js +1 -1
- package/dist/registry/ships.js.map +1 -1
- package/dist/rewards/index.d.ts +11 -5
- package/dist/rewards/index.d.ts.map +1 -1
- package/dist/rewards/index.js +10 -21
- package/dist/rewards/index.js.map +1 -1
- package/dist/scanning/actions/index.d.ts +1 -1
- package/dist/scanning/actions/index.d.ts.map +1 -1
- package/dist/scanning/actions/index.js +38 -8
- package/dist/scanning/actions/index.js.map +1 -1
- package/dist/scanning/index.d.ts +6 -11
- package/dist/scanning/index.d.ts.map +1 -1
- package/dist/scanning/index.js +7 -15
- package/dist/scanning/index.js.map +1 -1
- package/dist/scanning/odds.d.ts +5 -1
- package/dist/scanning/odds.d.ts.map +1 -1
- package/dist/scanning/odds.js.map +1 -1
- package/dist/scanning/signals.d.ts +6 -1
- package/dist/scanning/signals.d.ts.map +1 -1
- package/dist/scanning/signals.js +3 -1
- package/dist/scanning/signals.js.map +1 -1
- package/dist/starbases/actions/index.d.ts +49 -4
- package/dist/starbases/actions/index.d.ts.map +1 -1
- package/dist/starbases/actions/index.js +120 -69
- package/dist/starbases/actions/index.js.map +1 -1
- package/dist/starbases/index.d.ts +18 -0
- package/dist/starbases/index.d.ts.map +1 -1
- package/dist/starbases/index.js +24 -11
- package/dist/starbases/index.js.map +1 -1
- package/dist/world/index.d.ts +87 -13
- package/dist/world/index.d.ts.map +1 -1
- package/dist/world/index.js +88 -22
- package/dist/world/index.js.map +1 -1
- package/dist/world/planet-claim-stake-plots.d.ts +49 -40
- package/dist/world/planet-claim-stake-plots.d.ts.map +1 -1
- package/dist/world/planet-claim-stake-plots.js +47 -40
- package/dist/world/planet-claim-stake-plots.js.map +1 -1
- package/dist/world/starbase-status.d.ts +54 -13
- package/dist/world/starbase-status.d.ts.map +1 -1
- package/dist/world/starbase-status.js +65 -0
- package/dist/world/starbase-status.js.map +1 -1
- package/package.json +2 -2
- package/dist/internal/c4/faction-adapter.d.ts +0 -12
- package/dist/internal/c4/faction-adapter.d.ts.map +0 -1
- package/dist/internal/c4/faction-adapter.js +0 -52
- package/dist/internal/c4/faction-adapter.js.map +0 -1
- package/dist/internal/planning/movement-character.d.ts +0 -7
- package/dist/internal/planning/movement-character.d.ts.map +0 -1
- package/dist/internal/planning/movement-character.js +0 -41
- package/dist/internal/planning/movement-character.js.map +0 -1
|
@@ -1,24 +1,34 @@
|
|
|
1
1
|
import { deriveCurrencyCache, validateCurrencyCache, } from '../../internal/c4/currency-cache.js';
|
|
2
|
-
import {
|
|
2
|
+
import { isAddress } from '@solana/kit';
|
|
3
3
|
import { InvalidActionInputError, SageSdkError } from '../../client/errors.js';
|
|
4
4
|
import { readContextRawAccounts } from '../../client/reconciliation.js';
|
|
5
5
|
import { StarbaseLevel } from '../../internal/c4/runtime-bindings.js';
|
|
6
6
|
import { readFreshGameClaimStakeConfiguration, } from '../../registry/claim-stakes.js';
|
|
7
|
-
import { characterAccountDefinition, findCharacterPda, } from '../../internal/c4/
|
|
7
|
+
import { characterAccountDefinition, findCharacterPda, } from '../../internal/c4/character.js';
|
|
8
8
|
import { deriveFactionOwnershipAddress, factionOwnershipAccountDefinition, } from '../../internal/c4/factions.js';
|
|
9
9
|
import { claimStakeAccountDefinition } from '../../internal/c4/claim-stake.js';
|
|
10
|
+
import { deriveClaimStakeRegistration } from '../../internal/c4/claim-stake-standing.js';
|
|
11
|
+
import { CLAIM_STAKE_PLOT_ROWS, claimStakePlacementRow, claimStakePlotPositions, } from '../../internal/c4/claim-stake-plots.js';
|
|
12
|
+
import { factionValue } from '../../internal/c4/faction.js';
|
|
10
13
|
import { deriveFleetCrewBindingAddress, fleetCrewBindingAccountDefinition, matchesFleetCrewBindingIdentity, } from '../../internal/c4/fleet-crew-binding.js';
|
|
11
14
|
import { deriveFleetAddress, fleetAccountDefinition, } from '../../internal/c4/fleet.js';
|
|
12
15
|
import { deriveProfileFactionAddress, profileFactionIdentityAccountDefinition, } from '../../internal/c4/profile-faction.js';
|
|
13
16
|
import { deriveStarbasePlayerAddress, starbasePlayerAccountDefinition, } from '../../internal/c4/starbase.js';
|
|
14
17
|
import { celestialBodyAccountDefinition, deriveCelestialBodyAddress, deriveStarSystemAddress, starSystemAccountDefinition, } from '../../internal/c4/world.js';
|
|
15
18
|
import { resolveXpRuntime } from '../../internal/planning/xp-runtime.js';
|
|
19
|
+
import { readClaimStakeStorageAction } from '../../internal/planning/claim-stake-storage-actions.js';
|
|
20
|
+
import { RENT_ADDRESS } from '../../internal/planning/rent.js';
|
|
21
|
+
import { planStorageFunding } from '../../internal/planning/storage-actions.js';
|
|
22
|
+
import { requireDisabledStakeRent, requireNewStakeRent, } from '../../internal/planning/rent-catalog.js';
|
|
23
|
+
import { deriveStructureXpAccrualAddress } from '../../internal/c4/pda.js';
|
|
24
|
+
import { requireProfileStarbasePlayer } from '../../internal/planning/starbase-player-owner.js';
|
|
16
25
|
import { requireGameAddress } from '../../internal/game-context.js';
|
|
17
26
|
import { cargoStorageUnits } from '../../internal/cargo.js';
|
|
18
|
-
import { adaptCancelClaimStakeBuildingChangesInstruction, adaptClaimStakeBuildingChangesInstruction, adaptDeconstructClaimStakeInstruction, adaptFinalizeClaimStakeBuildingChangesInstruction, adaptPlaceClaimStakeInstruction, adaptRecoverClaimStakeFleetTransferInstruction, adaptStartClaimStakeFleetTransferInstruction, adaptTopUpClaimStakeRentInstruction,
|
|
19
|
-
import {
|
|
27
|
+
import { adaptCancelClaimStakeBuildingChangesInstruction, adaptClaimStakeBuildingChangesInstruction, adaptDeconstructClaimStakeInstruction, adaptFinalizeClaimStakeBuildingChangesInstruction, adaptPlaceClaimStakeInstruction, adaptRecoverClaimStakeFleetTransferInstruction, adaptStartClaimStakeFleetTransferInstruction, adaptTopUpClaimStakeRentInstruction, readPlanAuthorization, } from '../../internal/planning/authorization-adapter.js';
|
|
28
|
+
import { buildPlannerPlan } from '../../planning/plan-construction.js';
|
|
20
29
|
import { readFreshGameCargoDefinitions } from '../../registry/cargo.js';
|
|
21
30
|
import { resolveCargo } from '../../registry/index.js';
|
|
31
|
+
import { accountAbsentPrecondition, accountStatePrecondition, } from '../../internal/planning/account-state.js';
|
|
22
32
|
async function resolveClaimStakeXp(ctx, game, structure, character) {
|
|
23
33
|
const xp = await resolveXpRuntime(ctx, {
|
|
24
34
|
game,
|
|
@@ -101,51 +111,28 @@ function u16(value, field) {
|
|
|
101
111
|
}
|
|
102
112
|
function validateOptions(value) {
|
|
103
113
|
const options = record(value, 'options');
|
|
104
|
-
exactKeys(options, 'options', [
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
'
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const authorizationRecord = record(options.authorization, 'authorization');
|
|
112
|
-
exactKeys(authorizationRecord, 'authorization', ['profile', 'authority', 'keyIndex'], ['certificate']);
|
|
113
|
-
const authorization = authorizationRecord;
|
|
114
|
-
address(authorization.profile, 'authorization.profile');
|
|
115
|
-
address(authorization.authority, 'authorization.authority');
|
|
116
|
-
if (authorization.certificate !== undefined) {
|
|
117
|
-
address(authorization.certificate, 'authorization.certificate');
|
|
118
|
-
}
|
|
119
|
-
validatePlanAuthorization(authorization);
|
|
120
|
-
if (typeof options.initialRentAmount !== 'bigint' ||
|
|
121
|
-
options.initialRentAmount <= 0n ||
|
|
122
|
-
options.initialRentAmount > U64_MAX) {
|
|
123
|
-
invalid('initialRentAmount', options.initialRentAmount, `a positive raw bigint from 1 through ${String(U64_MAX)} (unsigned u64)`, 'Set initialRentAmount to the exact positive raw rent deposit within the instruction codec range.');
|
|
114
|
+
exactKeys(options, 'options', ['authorization', 'claimStake', 'claimStakeDefinitionId', 'hubBuildingId'], ['initialRentAmount']);
|
|
115
|
+
const authorization = readPlanAuthorization(options.authorization);
|
|
116
|
+
if (options.initialRentAmount !== undefined &&
|
|
117
|
+
(typeof options.initialRentAmount !== 'bigint' ||
|
|
118
|
+
options.initialRentAmount <= 0n ||
|
|
119
|
+
options.initialRentAmount > U64_MAX)) {
|
|
120
|
+
invalid('initialRentAmount', options.initialRentAmount, `a positive raw bigint from 1 through ${String(U64_MAX)} (unsigned u64)`, 'Set initialRentAmount to the exact positive raw rent deposit within the instruction codec range, or omit it to place without rent.');
|
|
124
121
|
}
|
|
125
122
|
return {
|
|
126
123
|
authorization,
|
|
127
124
|
claimStake: address(options.claimStake, 'claimStake'),
|
|
128
125
|
claimStakeDefinitionId: u16(options.claimStakeDefinitionId, 'claimStakeDefinitionId'),
|
|
129
126
|
hubBuildingId: u16(options.hubBuildingId, 'hubBuildingId'),
|
|
130
|
-
|
|
127
|
+
...(options.initialRentAmount === undefined
|
|
128
|
+
? {}
|
|
129
|
+
: { initialRentAmount: options.initialRentAmount }),
|
|
131
130
|
};
|
|
132
131
|
}
|
|
133
|
-
function validateAuthorization(value) {
|
|
134
|
-
const authorizationRecord = record(value, 'authorization');
|
|
135
|
-
exactKeys(authorizationRecord, 'authorization', ['profile', 'authority', 'keyIndex'], ['certificate']);
|
|
136
|
-
const authorization = authorizationRecord;
|
|
137
|
-
address(authorization.profile, 'authorization.profile');
|
|
138
|
-
address(authorization.authority, 'authorization.authority');
|
|
139
|
-
if (authorization.certificate !== undefined) {
|
|
140
|
-
address(authorization.certificate, 'authorization.certificate');
|
|
141
|
-
}
|
|
142
|
-
validatePlanAuthorization(authorization);
|
|
143
|
-
return authorization;
|
|
144
|
-
}
|
|
145
132
|
function validateBuildingChangeOptions(value) {
|
|
146
133
|
const options = record(value, 'options');
|
|
147
134
|
exactKeys(options, 'options', ['authorization', 'buildingChanges']);
|
|
148
|
-
const authorization =
|
|
135
|
+
const authorization = readPlanAuthorization(options.authorization);
|
|
149
136
|
const values = options.buildingChanges;
|
|
150
137
|
if (!Array.isArray(values) || values.length === 0) {
|
|
151
138
|
invalid('buildingChanges', values, 'a non-empty dense array of add/remove building changes', 'Provide at least one exact building change before retrying.');
|
|
@@ -186,22 +173,22 @@ function validateBuildingChangeOptions(value) {
|
|
|
186
173
|
function validateFinalizeBuildingChangeOptions(value) {
|
|
187
174
|
const options = record(value, 'options');
|
|
188
175
|
exactKeys(options, 'options', ['authorization']);
|
|
189
|
-
return { authorization:
|
|
176
|
+
return { authorization: readPlanAuthorization(options.authorization) };
|
|
190
177
|
}
|
|
191
178
|
function validateCancelBuildingChangeOptions(value) {
|
|
192
179
|
const options = record(value, 'options');
|
|
193
180
|
exactKeys(options, 'options', ['authorization']);
|
|
194
|
-
return { authorization:
|
|
181
|
+
return { authorization: readPlanAuthorization(options.authorization) };
|
|
195
182
|
}
|
|
196
183
|
function validateDeconstructOptions(value) {
|
|
197
184
|
const options = record(value, 'options');
|
|
198
185
|
exactKeys(options, 'options', ['authorization']);
|
|
199
|
-
return { authorization:
|
|
186
|
+
return { authorization: readPlanAuthorization(options.authorization) };
|
|
200
187
|
}
|
|
201
188
|
function validateTopUpRentOptions(value) {
|
|
202
189
|
const options = record(value, 'options');
|
|
203
190
|
exactKeys(options, 'options', ['amount', 'authorization']);
|
|
204
|
-
const authorization =
|
|
191
|
+
const authorization = readPlanAuthorization(options.authorization);
|
|
205
192
|
if (typeof options.amount !== 'bigint' ||
|
|
206
193
|
options.amount <= 0n ||
|
|
207
194
|
options.amount > U64_MAX) {
|
|
@@ -238,7 +225,7 @@ function validateCargoRequests(value, field, seen) {
|
|
|
238
225
|
function validateStartFleetTransferOptions(value) {
|
|
239
226
|
const options = record(value, 'options');
|
|
240
227
|
exactKeys(options, 'options', ['authorization', 'load', 'unload']);
|
|
241
|
-
const authorization =
|
|
228
|
+
const authorization = readPlanAuthorization(options.authorization);
|
|
242
229
|
const seen = new Set();
|
|
243
230
|
const load = validateCargoRequests(options.load, 'load', seen);
|
|
244
231
|
const unload = validateCargoRequests(options.unload, 'unload', seen);
|
|
@@ -250,7 +237,7 @@ function validateStartFleetTransferOptions(value) {
|
|
|
250
237
|
function validateRecoverFleetTransferOptions(value) {
|
|
251
238
|
const options = record(value, 'options');
|
|
252
239
|
exactKeys(options, 'options', ['atUnixSeconds', 'authorization']);
|
|
253
|
-
const authorization =
|
|
240
|
+
const authorization = readPlanAuthorization(options.authorization);
|
|
254
241
|
if (typeof options.atUnixSeconds !== 'bigint' ||
|
|
255
242
|
options.atUnixSeconds < 0n ||
|
|
256
243
|
options.atUnixSeconds > U64_MAX) {
|
|
@@ -261,29 +248,6 @@ function validateRecoverFleetTransferOptions(value) {
|
|
|
261
248
|
function requireAccount(account, accountAddress, message) {
|
|
262
249
|
return account ?? fail(message, accountAddress);
|
|
263
250
|
}
|
|
264
|
-
async function hashAccountState(account) {
|
|
265
|
-
const owner = getAddressEncoder().encode(account.owner);
|
|
266
|
-
const canonical = new Uint8Array(owner.length + account.data.length);
|
|
267
|
-
canonical.set(owner);
|
|
268
|
-
canonical.set(account.data, owner.length);
|
|
269
|
-
const digest = new Uint8Array(await globalThis.crypto.subtle.digest('SHA-256', canonical));
|
|
270
|
-
return [...digest].map((byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
271
|
-
}
|
|
272
|
-
async function precondition(account, describes) {
|
|
273
|
-
return Object.freeze({
|
|
274
|
-
address: account.address,
|
|
275
|
-
dataHash: await hashAccountState(account),
|
|
276
|
-
describes,
|
|
277
|
-
kind: 'account-state',
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
function absentPrecondition(accountAddress, describes) {
|
|
281
|
-
return Object.freeze({
|
|
282
|
-
address: accountAddress,
|
|
283
|
-
describes,
|
|
284
|
-
kind: 'account-absent',
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
251
|
function findDefinition(configuration, id, game) {
|
|
288
252
|
const definition = configuration.claimStakes.definitions.find((candidate) => candidate.id === id);
|
|
289
253
|
return (definition ??
|
|
@@ -294,18 +258,27 @@ function findHub(configuration, id, game) {
|
|
|
294
258
|
return (hub ??
|
|
295
259
|
fail(`Hub building ${String(id)} is not a member of the configured Game building catalog. Choose an exact current bundled hub id, refresh the Game definitions, and retry.`, game));
|
|
296
260
|
}
|
|
297
|
-
function claimedCount(details, definitionId) {
|
|
298
|
-
return (details.claimedPlots.find(({ key }) => key === definitionId)?.structures
|
|
299
|
-
.length ?? 0);
|
|
300
|
-
}
|
|
301
261
|
/** Plans placement of one Claim Stake with its exact bundled hub.
|
|
302
262
|
*
|
|
303
263
|
* The planner validates the configured Game/Profile/Character/System/Body
|
|
304
264
|
* graph, current catalog membership, known plot/cargo/crew availability, and
|
|
305
|
-
* absence of the caller-created Claim Stake account. It
|
|
265
|
+
* absence of the caller-created Claim Stake account. It also checks the
|
|
266
|
+
* Character's productive plot count and tier limits, the bundled hub's tags
|
|
267
|
+
* against the Planet and Claim Stake definition, and that the Character's
|
|
268
|
+
* ATLAS covers the placement fee plus any initial rent. It returns one inert Plan;
|
|
306
269
|
* permissions, placement races, rent arithmetic, and program capacity remain
|
|
307
270
|
* chain-authoritative.
|
|
308
271
|
*
|
|
272
|
+
* The new Claim Stake's rent settlement authority must not exist and stays
|
|
273
|
+
* guarded absent until signing.
|
|
274
|
+
*
|
|
275
|
+
* The program funds the new stake to its rent floor, the size it can reach
|
|
276
|
+
* once Deactivated with a cargo line for each resource it produces, and the
|
|
277
|
+
* Planet's claimed plot from the Profile vault with the signing key. The Plan
|
|
278
|
+
* bounds that debit; when it is positive the key must be Profile AUTH or hold
|
|
279
|
+
* `drainSolVault`, and the Profile needs that many lamports above its rent
|
|
280
|
+
* reserve. Execution checks again before signing.
|
|
281
|
+
*
|
|
309
282
|
* @example
|
|
310
283
|
* ```ts
|
|
311
284
|
* declare const ctx: SageContext;
|
|
@@ -329,21 +302,11 @@ export async function planPlaceClaimStake(ctx, body, player, input) {
|
|
|
329
302
|
if (canonicalBody !== body.address) {
|
|
330
303
|
fail(`Celestial Body ${body.address} is not the canonical Body ${String(body.id)} for the configured Game. Refresh the Body and retry.`, body.address);
|
|
331
304
|
}
|
|
332
|
-
|
|
333
|
-
fail(`Starbase Player ${player.address} does not belong to authorization Profile ${options.authorization.profile}. Refresh the Starbase Player for that Profile and retry.`, player.address);
|
|
334
|
-
}
|
|
335
|
-
const character = await findCharacterPda(options.authorization.profile, game);
|
|
336
|
-
if (player.character.address !== character) {
|
|
337
|
-
fail(`Starbase Player ${player.address} does not reference the canonical Character ${character} for authorization Profile ${options.authorization.profile}. Refresh the Starbase Player and retry.`, player.address);
|
|
338
|
-
}
|
|
339
|
-
const canonicalPlayer = await deriveStarbasePlayerAddress(player.system.address, character);
|
|
340
|
-
if (canonicalPlayer !== player.address) {
|
|
341
|
-
fail(`Starbase Player ${player.address} is not canonical for its Character and System. Refresh the Starbase Player and retry.`, player.address);
|
|
342
|
-
}
|
|
305
|
+
const character = await requireProfileStarbasePlayer(player, options.authorization.profile, game);
|
|
343
306
|
if (body.system.address !== player.system.address) {
|
|
344
307
|
fail(`Celestial Body ${body.address} belongs to System ${body.system.address}, but Starbase Player ${player.address} belongs to System ${player.system.address}. Choose both snapshots from the same System and retry.`, body.address);
|
|
345
308
|
}
|
|
346
|
-
const [freshGame, currentAccounts] = await Promise.all([
|
|
309
|
+
const [freshGame, currentAccounts, rent] = await Promise.all([
|
|
347
310
|
readFreshGameClaimStakeConfiguration(ctx),
|
|
348
311
|
readContextRawAccounts(ctx, [
|
|
349
312
|
body.address,
|
|
@@ -352,13 +315,15 @@ export async function planPlaceClaimStake(ctx, body, player, input) {
|
|
|
352
315
|
body.system.address,
|
|
353
316
|
options.claimStake,
|
|
354
317
|
]),
|
|
318
|
+
requireNewStakeRent(ctx, options.claimStake),
|
|
355
319
|
]);
|
|
356
320
|
if (freshGame === undefined) {
|
|
357
321
|
fail(`Configured Game ${game} is missing. Refresh the Game catalog and retry placement.`, game);
|
|
358
322
|
}
|
|
359
323
|
const definition = findDefinition(freshGame.data, options.claimStakeDefinitionId, game);
|
|
360
324
|
const hub = findHub(freshGame.data, options.hubBuildingId, game);
|
|
361
|
-
if (hub.hubValue
|
|
325
|
+
if (hub.hubValue <= 0 ||
|
|
326
|
+
hub.hubValue !== definition.hubValue ||
|
|
362
327
|
hub.minimumTier !== definition.tier ||
|
|
363
328
|
hub.constructionCost.length !== 0) {
|
|
364
329
|
fail(`Hub building ${hub.id} (${hub.name}) is not the exact zero-cost ${definition.tier} bundled hub for Claim Stake definition ${definition.id} (${definition.name}). Choose the matching bundled hub from the current Game catalog and retry.`, game);
|
|
@@ -382,11 +347,10 @@ export async function planPlaceClaimStake(ctx, body, player, input) {
|
|
|
382
347
|
}
|
|
383
348
|
const currentBodyAccount = requireAccount(bodyAccount, body.address, `Celestial Body ${body.address} is missing. Refresh the Body and retry placement.`);
|
|
384
349
|
const currentPlayerAccount = requireAccount(playerAccount, player.address, `Starbase Player ${player.address} is missing. Refresh it and retry placement.`);
|
|
385
|
-
const currentCharacterAccount = requireAccount(characterAccount, character, `Canonical Character ${character} is missing. Refresh the Profile Character and retry placement.`);
|
|
386
350
|
const currentSystemAccount = requireAccount(systemAccount, body.system.address, `Star System ${body.system.address} is missing. Refresh the System and retry placement.`);
|
|
387
351
|
const currentBody = celestialBodyAccountDefinition.decode(currentBodyAccount);
|
|
388
352
|
const currentPlayer = starbasePlayerAccountDefinition.decode(currentPlayerAccount);
|
|
389
|
-
const currentCharacter =
|
|
353
|
+
const { account: currentCharacterAccount, current: currentCharacter } = requireProfileCharacter(characterAccount, character, options.authorization.profile, game, 'placement');
|
|
390
354
|
const currentSystem = starSystemAccountDefinition.decode(currentSystemAccount);
|
|
391
355
|
const canonicalSystem = await deriveStarSystemAddress(game, currentSystem.systemId);
|
|
392
356
|
if (canonicalSystem !== body.system.address ||
|
|
@@ -408,10 +372,6 @@ export async function planPlaceClaimStake(ctx, body, player, input) {
|
|
|
408
372
|
currentPlayer.totalCrew - currentPlayer.busyCrew !== player.availableCrew) {
|
|
409
373
|
fail(`Starbase Player ${player.address} changed or does not match the authorization Profile, canonical Character, System, or available crew. Refresh it and retry.`, player.address);
|
|
410
374
|
}
|
|
411
|
-
if (currentCharacter.playerProfile !== options.authorization.profile ||
|
|
412
|
-
currentCharacter.game !== game) {
|
|
413
|
-
fail(`Character ${character} does not match authorization Profile ${options.authorization.profile} and configured Game ${game}. Refresh the Character and retry.`, character);
|
|
414
|
-
}
|
|
415
375
|
const currentCargo = currentPlayer.cargo.amounts.find(({ cargoId }) => cargoId === definition.cargoId)?.amount ?? 0n;
|
|
416
376
|
if (currentCargo !== cargoQuantity || currentCargo < 1n) {
|
|
417
377
|
fail(`Starbase Player ${player.address} Claim Stake cargo changed from the loaded snapshot or is no longer sufficient. Refresh its cargo and retry.`, player.address);
|
|
@@ -421,51 +381,100 @@ export async function planPlaceClaimStake(ctx, body, player, input) {
|
|
|
421
381
|
if (currentMissingTag !== undefined) {
|
|
422
382
|
fail(`Planet ${body.name} (${body.address}) no longer provides required Claim Stake tag ${String(currentMissingTag)} for ${definition.name}. Refresh it and retry.`, body.address);
|
|
423
383
|
}
|
|
384
|
+
// The bundled hub's tags must come from the Planet and the Claim Stake
|
|
385
|
+
// definition; the hub cannot satisfy its own requirements.
|
|
386
|
+
const hubMissingTag = hub.requiredTagIds.find((tag) => !currentDetails.providedTags.includes(tag) &&
|
|
387
|
+
!definition.providedTagIds.includes(tag));
|
|
388
|
+
if (hubMissingTag !== undefined) {
|
|
389
|
+
fail(`Bundled hub ${hub.name} requires tag ${String(hubMissingTag)}, which neither Planet ${body.name} nor ${definition.name} provides. Choose another Planet or definition.`, body.address);
|
|
390
|
+
}
|
|
424
391
|
const level = LEVEL_INDEX[currentSystem.starbase.level];
|
|
425
392
|
const tier = TIER_INDEX[definition.tier];
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
if (
|
|
429
|
-
fail(`Planet ${body.name} (${body.address}) has no
|
|
430
|
-
}
|
|
393
|
+
// The program places the stake in the first plot row up to the Starbase's
|
|
394
|
+
// level with room for its tier; stakes of every tier share each row.
|
|
395
|
+
if (claimStakePlacementRow(currentDetails.claimStakePlots, currentDetails.claimedPlots, tier, level) === undefined) {
|
|
396
|
+
fail(`Planet ${body.name} (${body.address}) has no free tier-${definition.tier} Claim Stake plot at Starbase ${currentSystem.starbase.level} or any lower level; every reachable plot row is full. Choose another eligible Planet or tier, refresh it, and retry.`, body.address);
|
|
397
|
+
}
|
|
398
|
+
// The Character's research caps the productive plot tier and count.
|
|
399
|
+
const modifiers = currentCharacter.modifiers.values;
|
|
400
|
+
if (modifiers.maxProductivePlotTier !== undefined &&
|
|
401
|
+
tier + 1 > modifiers.maxProductivePlotTier)
|
|
402
|
+
fail(`Character ${character} may place up to tier ${String(modifiers.maxProductivePlotTier)}, below ${definition.name}'s tier ${definition.tier}. Research a higher plot tier or pick a lower tier.`, character);
|
|
403
|
+
if (currentCharacter.counts.claimStakes >= modifiers.maxProductivePlots)
|
|
404
|
+
fail(`Character ${character} already holds ${String(currentCharacter.counts.claimStakes)} of its ${String(modifiers.maxProductivePlots)} productive plots. Research more plots or deconstruct a Claim Stake.`, character);
|
|
405
|
+
const placementFee = claimStakePlacementFee(currentDetails.baseClaimStakePlacementFee[level][tier].raw, definition.placementFeeMultiplier.raw);
|
|
406
|
+
const rentDeposit = options.initialRentAmount ?? 0n;
|
|
407
|
+
if (currentCharacter.atlasRaw < placementFee + rentDeposit)
|
|
408
|
+
fail(`Character ${character} has ${String(currentCharacter.atlasRaw)} raw ATLAS, below the ${String(placementFee)} raw placement fee plus ${String(rentDeposit)} raw initial rent. Add ATLAS or lower the rent, then retry.`, character);
|
|
431
409
|
const profileFaction = await deriveProfileFactionAddress(options.authorization.profile);
|
|
432
410
|
const currencyCache = await deriveCurrencyCache(game).then(([address]) => address);
|
|
433
|
-
const
|
|
434
|
-
|
|
411
|
+
const instruction = adaptPlaceClaimStakeInstruction({
|
|
412
|
+
authorization: options.authorization,
|
|
413
|
+
celestialBody: body.address,
|
|
414
|
+
character,
|
|
415
|
+
claimStakeDefinitionId: definition.id,
|
|
416
|
+
claimStakeInstance: options.claimStake,
|
|
417
|
+
currencyCache,
|
|
418
|
+
game,
|
|
419
|
+
hubBuildingId: hub.id,
|
|
420
|
+
initialRentAmount: options.initialRentAmount ?? null,
|
|
421
|
+
profileFaction,
|
|
422
|
+
rentAuthority: rent.rentAuthority,
|
|
423
|
+
systemAndStarbasePlayerStarbasePlayer: player.address,
|
|
424
|
+
systemAndStarbasePlayerSystem: body.system.address,
|
|
425
|
+
});
|
|
426
|
+
// The new stake and the claimed plot are funded from the Profile vault.
|
|
427
|
+
const storage = await planClaimStakeStorage(ctx, instruction, options.authorization.profile, [freshGame.account, currentBodyAccount, currentSystemAccount], 'Claim Stake placement');
|
|
428
|
+
const description = `Place ${definition.name} on Planet ${body.name} (${body.address}) with bundled hub ${hub.name}, ${String(hub.neededCrew)} crew, a ${String(placementFee)} raw ATLAS placement fee and ${String(rentDeposit)} raw initial rent. ${storage.disclosure}`;
|
|
429
|
+
return buildPlannerPlan({
|
|
435
430
|
kind: 'claim-stakes.place',
|
|
436
431
|
preconditions: [
|
|
437
432
|
...(await Promise.all([
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
433
|
+
accountStatePrecondition(freshGame.account, `The configured Game retains Claim Stake definition ${String(definition.id)} and bundled hub ${String(hub.id)} eligibility.`),
|
|
434
|
+
accountStatePrecondition(currentBodyAccount, `Planet ${body.name} retains an available ${definition.name} plot and its configured Game/System relationship.`),
|
|
435
|
+
accountStatePrecondition(currentPlayerAccount, `Starbase Player ${player.address} retains its Profile, Character, System, available crew, and ${cargoName} balance.`),
|
|
436
|
+
characterPrecondition(currentCharacterAccount, options.authorization.profile),
|
|
437
|
+
accountStatePrecondition(currentSystemAccount, `Star System ${currentSystem.name} retains its configured Game, sequence, and active Starbase level.`),
|
|
443
438
|
])),
|
|
444
|
-
|
|
439
|
+
accountAbsentPrecondition(options.claimStake, 'The caller-supplied Claim Stake signer address remains unallocated.'),
|
|
440
|
+
...rent.guards,
|
|
441
|
+
storage.guard,
|
|
445
442
|
],
|
|
446
443
|
steps: [
|
|
447
444
|
{
|
|
448
445
|
describes: description,
|
|
449
|
-
instruction
|
|
450
|
-
authorization: options.authorization,
|
|
451
|
-
celestialBody: body.address,
|
|
452
|
-
character,
|
|
453
|
-
claimStakeDefinitionId: definition.id,
|
|
454
|
-
claimStakeInstance: options.claimStake,
|
|
455
|
-
currencyCache,
|
|
456
|
-
game,
|
|
457
|
-
hubBuildingId: hub.id,
|
|
458
|
-
initialRentAmount: options.initialRentAmount,
|
|
459
|
-
profileFaction,
|
|
460
|
-
systemAndStarbasePlayerStarbasePlayer: player.address,
|
|
461
|
-
systemAndStarbasePlayerSystem: body.system.address,
|
|
462
|
-
}),
|
|
446
|
+
instruction,
|
|
463
447
|
signers: [options.authorization.authority, options.claimStake],
|
|
464
448
|
},
|
|
465
449
|
],
|
|
466
450
|
summary: description,
|
|
467
451
|
});
|
|
468
452
|
}
|
|
453
|
+
/** Plans a Claim Stake action's Profile storage funding from the fresh
|
|
454
|
+
* accounts the planner already read, plus the Profile and Rent sysvar. */
|
|
455
|
+
async function planClaimStakeStorage(ctx, instruction, profile, known, label) {
|
|
456
|
+
const [profileAccount, rentAccount] = await readContextRawAccounts(ctx, [
|
|
457
|
+
profile,
|
|
458
|
+
RENT_ADDRESS,
|
|
459
|
+
]);
|
|
460
|
+
const accounts = new Map([
|
|
461
|
+
...known.map((raw) => [raw.address, raw]),
|
|
462
|
+
[profile, profileAccount],
|
|
463
|
+
[RENT_ADDRESS, rentAccount],
|
|
464
|
+
]);
|
|
465
|
+
return planStorageFunding({
|
|
466
|
+
action: readClaimStakeStorageAction(instruction, accounts),
|
|
467
|
+
accounts,
|
|
468
|
+
label,
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
/** The ATLAS placement fee: the Planet's U32F32 base fee for the Starbase
|
|
472
|
+
* level and tier, times the definition's U8F56 multiplier, rounded to the
|
|
473
|
+
* nearest raw unit with halves rounded up. */
|
|
474
|
+
function claimStakePlacementFee(baseFeeRaw, multiplierRaw) {
|
|
475
|
+
const product = ((baseFeeRaw << 24n) * multiplierRaw) >> 56n;
|
|
476
|
+
return (product + (1n << 55n)) >> 56n;
|
|
477
|
+
}
|
|
469
478
|
function quantities(buildings) {
|
|
470
479
|
return new Map(buildings.map(({ buildingId, quantity }) => [buildingId, quantity]));
|
|
471
480
|
}
|
|
@@ -478,9 +487,10 @@ function sameQuantities(left, right) {
|
|
|
478
487
|
[...leftById].every(([buildingId, quantity]) => rightById.get(buildingId) === quantity));
|
|
479
488
|
}
|
|
480
489
|
function sameStakeState(left, right) {
|
|
481
|
-
if (left.kind === 'deactivated')
|
|
482
|
-
return false;
|
|
483
490
|
switch (left.kind) {
|
|
491
|
+
case 'deactivated':
|
|
492
|
+
return (right.kind === 'deactivated' &&
|
|
493
|
+
left.deactivatedAtUnixSeconds === right.deactivatedAtUnixSeconds);
|
|
484
494
|
case 'active':
|
|
485
495
|
return right.kind === 'active';
|
|
486
496
|
case 'design':
|
|
@@ -489,12 +499,192 @@ function sameStakeState(left, right) {
|
|
|
489
499
|
sameQuantities(left.buildings, right.buildings));
|
|
490
500
|
}
|
|
491
501
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
});
|
|
502
|
+
/** Finalization and deconstruction release crew the stake committed, which
|
|
503
|
+
* only a version-1 instance records; the program refuses a version-0 instance,
|
|
504
|
+
* whose stored crew is an unverified nominal value. */
|
|
505
|
+
function requireCommittedCrewVersion(current, stake, outcome) {
|
|
506
|
+
if (current.version !== 1) {
|
|
507
|
+
fail(`Claim Stake ${stake.address} is a version ${String(current.version)} instance, which records no committed crew, so it cannot be ${outcome}. Only version-1 Claim Stakes support this action; choose another Claim Stake.`, stake.address);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
// Common facts for planners acting on an owned, placed Claim Stake. Each
|
|
511
|
+
// planner keeps its own eligibility checks and Plan wording at its call site;
|
|
512
|
+
// `action` completes the shared remedies ("retry <action>").
|
|
513
|
+
/** Requires the loaded Claim Stake to belong to the configured Game and to the
|
|
514
|
+
* authorization Profile, and returns that Profile's canonical Character. */
|
|
515
|
+
async function requireOwnedStake(stake, game, profile) {
|
|
516
|
+
if (stake.game !== game) {
|
|
517
|
+
fail(`Claim Stake ${stake.address} does not match the configured Game ${game}. Refresh it through this context and retry.`, stake.address);
|
|
518
|
+
}
|
|
519
|
+
if (stake.ownerProfile.address !== profile) {
|
|
520
|
+
fail(`Claim Stake ${stake.address} belongs to Profile ${stake.ownerProfile.address}, not authorization Profile ${profile}. Choose a Claim Stake this Profile owns, refresh it, and retry.`, stake.address);
|
|
521
|
+
}
|
|
522
|
+
return findCharacterPda(profile, game);
|
|
523
|
+
}
|
|
524
|
+
/** Reads and decodes the fresh Claim Stake and Body, with `extra` accounts in
|
|
525
|
+
* the same batch. */
|
|
526
|
+
async function readOwnedStake(ctx, stake, action, extra = []) {
|
|
527
|
+
const [stakeCandidate, bodyCandidate, ...extraAccounts] = await readContextRawAccounts(ctx, [
|
|
528
|
+
stake.address,
|
|
529
|
+
stake.body.address,
|
|
530
|
+
...extra,
|
|
531
|
+
]);
|
|
532
|
+
const stakeAccount = requireAccount(stakeCandidate, stake.address, `Claim Stake ${stake.address} is missing. Refresh it and retry ${action}.`);
|
|
533
|
+
const bodyAccount = requireAccount(bodyCandidate, stake.body.address, `Celestial Body ${stake.body.address} is missing. Refresh the Claim Stake Body and retry ${action}.`);
|
|
534
|
+
return {
|
|
535
|
+
bodyAccount,
|
|
536
|
+
currentBody: celestialBodyAccountDefinition.decode(bodyAccount),
|
|
537
|
+
currentStake: claimStakeAccountDefinition.decode(stakeAccount),
|
|
538
|
+
extraAccounts,
|
|
539
|
+
stakeAccount,
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
/** Whether the fresh Claim Stake keeps the loaded ownership, Body,
|
|
543
|
+
* definitions, buildings and System generation. */
|
|
544
|
+
function sameOwnedStake(current, stake, game, profile) {
|
|
545
|
+
return (current.game === game &&
|
|
546
|
+
current.body === stake.body.address &&
|
|
547
|
+
current.ownerProfile === profile &&
|
|
548
|
+
current.claimStakeDefinitionId === stake.claimStakeDefinitionId &&
|
|
549
|
+
current.claimStakeDefinitionSeqId === stake.claimStakeDefinitionSeqId &&
|
|
550
|
+
current.buildingDefinitionSeqId === stake.buildingDefinitionSeqId &&
|
|
551
|
+
current.systemSeqId === stake.systemSeqId &&
|
|
552
|
+
sameQuantities(current.buildings, stake.buildings));
|
|
553
|
+
}
|
|
554
|
+
/** Whether the fresh Claim Stake keeps the loaded transfer facts: ownership,
|
|
555
|
+
* Body, active state, System generation, resources and capacity. */
|
|
556
|
+
function sameTransferStake(current, stake, game, profile) {
|
|
557
|
+
return (current.game === game &&
|
|
558
|
+
current.ownerProfile === profile &&
|
|
559
|
+
current.body === stake.body.address &&
|
|
560
|
+
current.systemSeqId === stake.systemSeqId &&
|
|
561
|
+
current.state.kind === 'active' &&
|
|
562
|
+
current.production.cargoPod.storageCost ===
|
|
563
|
+
stake.resources.capacity.usedRaw &&
|
|
564
|
+
current.production.resourceCapacityRaw ===
|
|
565
|
+
stake.resources.capacity.totalRaw &&
|
|
566
|
+
sameCargoAmounts(current.production.cargoPod.amounts, stake.resources.inventory.items.map(({ id, quantityRaw }) => ({
|
|
567
|
+
amount: quantityRaw,
|
|
568
|
+
id,
|
|
569
|
+
}))));
|
|
570
|
+
}
|
|
571
|
+
/** Whether the fresh Fleet keeps the loaded Game, owner, name, cargo and
|
|
572
|
+
* capacities. */
|
|
573
|
+
function sameTransferFleet(current, fleet, game, profile) {
|
|
574
|
+
return (current.game === game &&
|
|
575
|
+
current.ownerProfile === profile &&
|
|
576
|
+
current.name === fleet.name &&
|
|
577
|
+
current.ammoBank.cargoId === fleet.ammo.id &&
|
|
578
|
+
current.ammoBank.amount === fleet.ammo.amount &&
|
|
579
|
+
current.fuelTank.cargoId === fleet.fuel.id &&
|
|
580
|
+
current.fuelTank.amount === fleet.fuel.amount &&
|
|
581
|
+
current.cargoHold.storageCost === fleet.cargoHold.storageCost &&
|
|
582
|
+
sameCargoAmounts(current.cargoHold.amounts, fleet.cargoHold.items) &&
|
|
583
|
+
current.stats.cargo.ammoCapacity === fleet.capacities.ammo.total &&
|
|
584
|
+
current.stats.cargo.fuelCapacity === fleet.capacities.fuel.total &&
|
|
585
|
+
current.stats.cargo.cargoCapacity === fleet.capacities.cargo.total);
|
|
586
|
+
}
|
|
587
|
+
/** Requires the fresh Body to be the Claim Stake's canonical Planet in the
|
|
588
|
+
* configured Game at the Claim Stake's System generation. */
|
|
589
|
+
async function requireStakePlanet(currentBody, stake, game, action) {
|
|
590
|
+
if (currentBody.kind !== 'planet' ||
|
|
591
|
+
currentBody.game !== game ||
|
|
592
|
+
currentBody.systemSequenceId !== stake.systemSeqId ||
|
|
593
|
+
(await deriveCelestialBodyAddress(game, currentBody.id)) !==
|
|
594
|
+
stake.body.address) {
|
|
595
|
+
fail(`Celestial Body ${stake.body.address} does not match the Claim Stake's configured Game, canonical Planet identity, or System generation. Refresh the Body and Claim Stake before retrying ${action}.`, stake.body.address);
|
|
596
|
+
}
|
|
597
|
+
return currentBody;
|
|
598
|
+
}
|
|
599
|
+
/** Refuses a building change the game would refuse for the stake's Planet
|
|
600
|
+
* registration, which is independent of its rent. */
|
|
601
|
+
function requireStakeRegistered(claimedPlots, stake, starbaseLevel, action) {
|
|
602
|
+
const registration = deriveClaimStakeRegistration(stake, claimedPlots, starbaseLevel);
|
|
603
|
+
if (registration.kind === 'operable')
|
|
604
|
+
return;
|
|
605
|
+
fail(registration.kind === 'unregistered'
|
|
606
|
+
? `Planet ${stake.body.address} does not register Claim Stake ${stake.address}. Refresh the Body and Claim Stake before retrying ${action}.`
|
|
607
|
+
: registration.kind === 'off-level'
|
|
608
|
+
? `Claim Stake ${stake.address} is registered in plot row ${String(registration.plotRow)}, above the Starbase's current ${starbaseLevel}, so it is evicted and ${action} is refused. Respawn it to reclaim it.`
|
|
609
|
+
: `A Starbase takeover, destruction or downgrade evicted Claim Stake ${stake.address}, so ${action} is refused. Respawn it to reclaim it.`, stake.address);
|
|
610
|
+
}
|
|
611
|
+
/** {@link requireStakePlanet} for building changes. An eviction is reported
|
|
612
|
+
* first: a takeover or destruction also advances the System generation, which
|
|
613
|
+
* would otherwise hide the real cause behind a refresh remedy. */
|
|
614
|
+
async function requireDesignStakePlanet(currentBody, stake, game, action) {
|
|
615
|
+
if (currentBody.kind === 'planet')
|
|
616
|
+
requireStakeRegistered(currentBody.details.claimedPlots, stake, 'css', action);
|
|
617
|
+
return requireStakePlanet(currentBody, stake, game, action);
|
|
618
|
+
}
|
|
619
|
+
/** Requires and decodes the canonical Character of the authorization Profile in
|
|
620
|
+
* the configured Game. */
|
|
621
|
+
function requireProfileCharacter(candidate, character, profile, game, action) {
|
|
622
|
+
const account = requireAccount(candidate, character, `Canonical Character ${character} is missing. Refresh the Profile Character and retry ${action}.`);
|
|
623
|
+
const current = characterAccountDefinition.decode(account);
|
|
624
|
+
if (current.playerProfile !== profile || current.game !== game) {
|
|
625
|
+
fail(`Character ${character} does not match authorization Profile ${profile} and configured Game ${game}. Refresh the Character and retry ${action}.`, character);
|
|
626
|
+
}
|
|
627
|
+
return { account, current };
|
|
628
|
+
}
|
|
629
|
+
/** Reads the Claim Stake's System and the authorization Profile's canonical
|
|
630
|
+
* Starbase Player there, with `extra` accounts in the same batch. Requires a
|
|
631
|
+
* canonical, current System with an active Starbase that lists the Body, and a
|
|
632
|
+
* Starbase Player of the Profile, Character and System. */
|
|
633
|
+
async function readStakeStarbase(ctx, stake, game, system, character, profile, action, extra = []) {
|
|
634
|
+
const player = await deriveStarbasePlayerAddress(system, character);
|
|
635
|
+
const [systemCandidate, playerCandidate, ...extraAccounts] = await readContextRawAccounts(ctx, [system, player, ...extra]);
|
|
636
|
+
const systemAccount = requireAccount(systemCandidate, system, `Star System ${system} is missing. Refresh the Claim Stake's System and retry ${action}.`);
|
|
637
|
+
const playerAccount = requireAccount(playerCandidate, player, `Starbase Player ${player} is missing for authorization Profile ${profile}. Register or refresh it in the Claim Stake's System before retrying ${action}.`);
|
|
638
|
+
const currentSystem = starSystemAccountDefinition.decode(systemAccount);
|
|
639
|
+
const currentPlayer = starbasePlayerAccountDefinition.decode(playerAccount);
|
|
640
|
+
if (currentSystem.game !== game ||
|
|
641
|
+
currentSystem.sequenceId !== stake.systemSeqId ||
|
|
642
|
+
currentSystem.starbase === undefined ||
|
|
643
|
+
!currentSystem.celestialBodyAddresses.includes(stake.body.address) ||
|
|
644
|
+
(await deriveStarSystemAddress(game, currentSystem.systemId)) !== system) {
|
|
645
|
+
fail(`Star System ${system} does not match the configured Game, canonical identity, Claim Stake generation, active nested Starbase, or Claim Stake Body relationship. Refresh the System and retry ${action}.`, system);
|
|
646
|
+
}
|
|
647
|
+
if (currentPlayer.playerProfile !== profile ||
|
|
648
|
+
currentPlayer.character !== character ||
|
|
649
|
+
currentPlayer.system !== system) {
|
|
650
|
+
fail(`Starbase Player ${player} does not match the authorization Profile, canonical Character, and Claim Stake System. Refresh it and retry ${action}.`, player);
|
|
651
|
+
}
|
|
652
|
+
return {
|
|
653
|
+
currentPlayer,
|
|
654
|
+
currentSystem,
|
|
655
|
+
extraAccounts,
|
|
656
|
+
player,
|
|
657
|
+
playerAccount,
|
|
658
|
+
starbase: currentSystem.starbase,
|
|
659
|
+
systemAccount,
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
async function claimStakeCurrencyCache(game) {
|
|
663
|
+
const [currencyCache] = await deriveCurrencyCache(game);
|
|
664
|
+
return currencyCache;
|
|
665
|
+
}
|
|
666
|
+
/** Requires the canonical CurrencyCache and returns its Plan guard. */
|
|
667
|
+
async function requireCurrencyCache(candidate, currencyCache, game, action, planName) {
|
|
668
|
+
await validateCurrencyCache(requireAccount(candidate, currencyCache, `Canonical CurrencyCache ${currencyCache} is missing for configured Game ${game}. Refresh the Game currency configuration and retry ${action}.`), game, planName);
|
|
669
|
+
return {
|
|
670
|
+
kind: 'currency-cache',
|
|
671
|
+
address: currencyCache,
|
|
672
|
+
game,
|
|
673
|
+
describes: 'The canonical CurrencyCache remains assigned to the configured Game; shared accounting may change.',
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
function planetPrecondition(account, system) {
|
|
677
|
+
return accountStatePrecondition(account, `The Claim Stake Planet remains assigned to System ${system} at the current generation.`);
|
|
678
|
+
}
|
|
679
|
+
function characterPrecondition(account, profile) {
|
|
680
|
+
return accountStatePrecondition(account, `The canonical Character remains assigned to Profile ${profile} in the configured Game.`);
|
|
681
|
+
}
|
|
682
|
+
function systemPrecondition(account, name) {
|
|
683
|
+
return accountStatePrecondition(account, `Star System ${name} retains its configured Game, sequence, nested Starbase, and Claim Stake Body relationship.`);
|
|
684
|
+
}
|
|
685
|
+
function playerPrecondition(account, player, facts = 'Profile, Character, and System') {
|
|
686
|
+
return accountStatePrecondition(account, `Starbase Player ${player} retains its ${facts}.`);
|
|
687
|
+
}
|
|
498
688
|
function buildingDescription(change, name) {
|
|
499
689
|
return `${change.kind} ${String(change.quantity)} ${name}`;
|
|
500
690
|
}
|
|
@@ -502,13 +692,27 @@ function buildingDescription(change, name) {
|
|
|
502
692
|
*
|
|
503
693
|
* The planner verifies the fresh Claim Stake, definition sequences, canonical
|
|
504
694
|
* Profile/Character/Body/System/Starbase Player graph, optional
|
|
505
|
-
* FactionOwnership sidecar, building quantities, slots, crew,
|
|
506
|
-
*
|
|
507
|
-
*
|
|
695
|
+
* FactionOwnership sidecar, building quantities, slots, Starbase Player crew,
|
|
696
|
+
* non-negative power, a single unremovable hub of quantity one, building tags
|
|
697
|
+
* provided by the Claim Stake definition, the Planet and the buildings, and
|
|
698
|
+
* known construction cargo. A stake whose stored construction time is still
|
|
699
|
+
* running is refused; that time advances only on a production tick. Construction cargo is debited from the Starbase Player's
|
|
700
|
+
* Starbase cargo at finalization, never from the Claim Stake's own storage, so
|
|
701
|
+
* the planner checks the fresh Starbase Player pod. Rent synchronization and
|
|
702
|
+
* the final concurrent sequence race remain chain-authoritative.
|
|
703
|
+
*
|
|
704
|
+
* Entering a design adds the design state and an entry for each building id
|
|
705
|
+
* the design does not yet hold. The program funds that growth, up to the
|
|
706
|
+
* stake's rent floor, from the Profile vault with the signing key; the Plan
|
|
707
|
+
* bounds the debit with the same key and balance checks as placement.
|
|
508
708
|
*
|
|
509
709
|
* Requires Game 2 and its existing canonical Claim Stake XP ledger.
|
|
510
710
|
* Missing XP state must be repaired outside this Plan; no accounts are created.
|
|
511
711
|
*
|
|
712
|
+
* Requires Disabled rent: the Game's rent catalog and the Claim Stake's rent
|
|
713
|
+
* settlement authority must not exist, and both stay guarded absent until
|
|
714
|
+
* signing. The instruction carries no rent history.
|
|
715
|
+
*
|
|
512
716
|
* @example
|
|
513
717
|
* ```ts
|
|
514
718
|
* declare const ctx: SageContext;
|
|
@@ -521,88 +725,46 @@ function buildingDescription(change, name) {
|
|
|
521
725
|
export async function planClaimStakeBuildingChanges(ctx, stake, input) {
|
|
522
726
|
const options = validateBuildingChangeOptions(input);
|
|
523
727
|
const game = requireGameAddress(ctx);
|
|
728
|
+
const { profile } = options.authorization;
|
|
524
729
|
if (stake.state.kind === 'deactivated') {
|
|
525
730
|
fail(`Claim Stake ${stake.address} is deactivated; building changes require an active or design Claim Stake. Refresh it or choose another owned Claim Stake before retrying.`, stake.address);
|
|
526
731
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
const character = await findCharacterPda(options.authorization.profile, game);
|
|
531
|
-
if (stake.ownerCharacter.address !== character) {
|
|
532
|
-
fail(`Claim Stake ${stake.address} does not belong to authorization Profile ${options.authorization.profile}'s canonical Character ${character}. Choose an owned Claim Stake, refresh it, and retry.`, stake.address);
|
|
533
|
-
}
|
|
534
|
-
const [freshGame, firstAccounts] = await Promise.all([
|
|
732
|
+
const character = await requireOwnedStake(stake, game, profile);
|
|
733
|
+
const action = 'building changes';
|
|
734
|
+
const [freshGame, loaded, rent] = await Promise.all([
|
|
535
735
|
readFreshGameClaimStakeConfiguration(ctx),
|
|
536
|
-
|
|
736
|
+
readOwnedStake(ctx, stake, action, [character]),
|
|
737
|
+
requireDisabledStakeRent(ctx, game, stake.address, action),
|
|
537
738
|
]);
|
|
538
739
|
if (freshGame === undefined) {
|
|
539
740
|
fail(`Configured Game ${game} is missing. Refresh the Game catalog and retry building changes.`, game);
|
|
540
741
|
}
|
|
541
|
-
const
|
|
542
|
-
|
|
543
|
-
const characterAccount = requireAccount(firstAccounts[2], character, `Canonical Character ${character} is missing. Refresh the Profile Character and retry building changes.`);
|
|
544
|
-
const currentStake = claimStakeAccountDefinition.decode(stakeAccount);
|
|
545
|
-
const currentBody = celestialBodyAccountDefinition.decode(bodyAccount);
|
|
546
|
-
const currentCharacter = characterAccountDefinition.decode(characterAccount);
|
|
547
|
-
if (currentStake.game !== game ||
|
|
548
|
-
currentStake.body !== stake.body.address ||
|
|
549
|
-
currentStake.ownerCharacter !== character ||
|
|
550
|
-
currentStake.claimStakeDefinitionId !== stake.claimStakeDefinitionId ||
|
|
551
|
-
currentStake.claimStakeDefinitionSeqId !==
|
|
552
|
-
stake.claimStakeDefinitionSeqId ||
|
|
553
|
-
currentStake.buildingDefinitionSeqId !== stake.buildingDefinitionSeqId ||
|
|
554
|
-
currentStake.systemSeqId !== stake.systemSeqId ||
|
|
555
|
-
!sameQuantities(currentStake.buildings, stake.buildings) ||
|
|
742
|
+
const { bodyAccount, currentStake, stakeAccount } = loaded;
|
|
743
|
+
if (!sameOwnedStake(currentStake, stake, game, profile) ||
|
|
556
744
|
currentStake.neededCrew !== stake.neededCrew) {
|
|
557
745
|
fail(`Claim Stake ${stake.address} changed or does not match its loaded ownership, Body, definitions, buildings, crew, or System generation. Refresh it and retry building changes.`, stake.address);
|
|
558
746
|
}
|
|
559
|
-
if (
|
|
560
|
-
|
|
561
|
-
fail(`Character ${character} does not match authorization Profile ${options.authorization.profile} and configured Game ${game}. Refresh the Character and retry building changes.`, character);
|
|
747
|
+
if (currentStake.constructionRemainingSeconds > 0n) {
|
|
748
|
+
fail(`Claim Stake ${stake.address} records ${String(currentStake.constructionRemainingSeconds)} seconds of construction remaining, and a stake under construction cannot change its buildings. The stored time advances only when a production tick processes the stake: wait for construction to finish, let a production tick record it, refresh the Claim Stake, and retry.`, stake.address);
|
|
562
749
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
stake.body.address) {
|
|
568
|
-
fail(`Celestial Body ${stake.body.address} does not match the Claim Stake's configured Game, canonical Planet identity, or System generation. Refresh the Body and Claim Stake before retrying.`, stake.body.address);
|
|
569
|
-
}
|
|
570
|
-
const system = currentBody.system;
|
|
571
|
-
const [player, ownership, profileFaction] = await Promise.all([
|
|
572
|
-
deriveStarbasePlayerAddress(system, character),
|
|
750
|
+
const planetBody = await requireDesignStakePlanet(loaded.currentBody, stake, game, action);
|
|
751
|
+
const { system } = planetBody;
|
|
752
|
+
const { account: characterAccount } = requireProfileCharacter(loaded.extraAccounts[0], character, profile, game, action);
|
|
753
|
+
const [ownership, profileFaction] = await Promise.all([
|
|
573
754
|
deriveFactionOwnershipAddress(game, 'starbase', system),
|
|
574
|
-
deriveProfileFactionAddress(
|
|
575
|
-
]);
|
|
576
|
-
const [systemAccountCandidate, playerAccountCandidate, ownershipAccount, profileFactionAccountCandidate,] = await readContextRawAccounts(ctx, [
|
|
577
|
-
system,
|
|
578
|
-
player,
|
|
579
|
-
ownership,
|
|
580
|
-
profileFaction,
|
|
755
|
+
deriveProfileFactionAddress(profile),
|
|
581
756
|
]);
|
|
582
|
-
const
|
|
583
|
-
|
|
584
|
-
const profileFactionAccount = requireAccount(
|
|
585
|
-
const currentSystem = starSystemAccountDefinition.decode(systemAccount);
|
|
586
|
-
const currentPlayer = starbasePlayerAccountDefinition.decode(playerAccount);
|
|
757
|
+
const { currentPlayer, currentSystem, extraAccounts: [ownershipAccount, profileFactionCandidate], player, playerAccount, starbase, systemAccount, } = await readStakeStarbase(ctx, stake, game, system, character, profile, action, [ownership, profileFaction]);
|
|
758
|
+
requireStakeRegistered(planetBody.details.claimedPlots, stake, starbase.level, action);
|
|
759
|
+
const profileFactionAccount = requireAccount(profileFactionCandidate, profileFaction, `ProfileFaction ${profileFaction} is missing for authorization Profile ${profile}. Choose or repair the Profile faction, refresh it, and retry building changes.`);
|
|
587
760
|
const currentProfileFaction = profileFactionIdentityAccountDefinition.decode(profileFactionAccount);
|
|
588
|
-
if (
|
|
589
|
-
|
|
590
|
-
currentSystem.starbase === undefined ||
|
|
591
|
-
(await deriveStarSystemAddress(game, currentSystem.systemId)) !== system) {
|
|
592
|
-
fail(`Star System ${system} does not match the configured Game, canonical identity, Claim Stake generation, or an active nested Starbase. Refresh the System and retry building changes.`, system);
|
|
761
|
+
if (currentProfileFaction.profile !== profile) {
|
|
762
|
+
fail(`ProfileFaction ${profileFaction} does not match authorization Profile ${profile}. Refresh or repair the Profile faction before retrying building changes.`, profileFaction);
|
|
593
763
|
}
|
|
594
|
-
|
|
595
|
-
currentPlayer.character !== character ||
|
|
596
|
-
currentPlayer.system !== system) {
|
|
597
|
-
fail(`Starbase Player ${player} does not match the authorization Profile, canonical Character, and Claim Stake System. Refresh it and retry building changes.`, player);
|
|
598
|
-
}
|
|
599
|
-
if (currentProfileFaction.profile !== options.authorization.profile) {
|
|
600
|
-
fail(`ProfileFaction ${profileFaction} does not match authorization Profile ${options.authorization.profile}. Refresh or repair the Profile faction before retrying building changes.`, profileFaction);
|
|
601
|
-
}
|
|
602
|
-
let controllerFactionId = LEGACY_CONTROLLER_ID[currentSystem.starbase.owner];
|
|
764
|
+
let controllerFactionId = factionValue(starbase.owner);
|
|
603
765
|
let ownershipPrecondition;
|
|
604
766
|
if (ownershipAccount === undefined) {
|
|
605
|
-
ownershipPrecondition =
|
|
767
|
+
ownershipPrecondition = accountAbsentPrecondition(ownership, `The canonical Starbase FactionOwnership ${ownership} remains unallocated so the chain applies its legacy controller gate.`);
|
|
606
768
|
}
|
|
607
769
|
else {
|
|
608
770
|
const currentOwnership = factionOwnershipAccountDefinition.decode(ownershipAccount);
|
|
@@ -614,7 +776,7 @@ export async function planClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
614
776
|
}
|
|
615
777
|
controllerFactionId =
|
|
616
778
|
currentOwnership.controllingFactionId ?? controllerFactionId;
|
|
617
|
-
ownershipPrecondition = await
|
|
779
|
+
ownershipPrecondition = await accountStatePrecondition(ownershipAccount, `The Starbase FactionOwnership remains assigned to System ${system} at its current generation.`);
|
|
618
780
|
}
|
|
619
781
|
if (currentProfileFaction.factionId !== controllerFactionId) {
|
|
620
782
|
fail(`ProfileFaction ${profileFaction} faction ${String(currentProfileFaction.factionId)} does not match the current Starbase controller faction ${String(controllerFactionId)}. Use a Profile aligned with the current controller, refresh the faction relationship, and retry building changes.`, profileFaction);
|
|
@@ -647,6 +809,9 @@ export async function planClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
647
809
|
if (definition === undefined) {
|
|
648
810
|
fail(`Building ${String(change.buildingId)} has no definition in the current Game catalog. Refresh the definitions and choose a valid building before retrying.`, game);
|
|
649
811
|
}
|
|
812
|
+
if (change.kind === 'remove' && definition.hubValue > 0) {
|
|
813
|
+
fail(`Building ${definition.name} is Claim Stake ${stake.address}'s bundled hub and cannot be removed. Remove other buildings, or deconstruct the whole Claim Stake, instead.`, stake.address);
|
|
814
|
+
}
|
|
650
815
|
const current = result.get(change.buildingId) ?? 0;
|
|
651
816
|
const next = change.kind === 'add'
|
|
652
817
|
? current + change.quantity
|
|
@@ -664,10 +829,15 @@ export async function planClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
664
829
|
descriptions.push(buildingDescription(change, definition.name));
|
|
665
830
|
}
|
|
666
831
|
let usedSlots = 0;
|
|
667
|
-
let crewSlots = 0;
|
|
668
832
|
let neededCrew = 0;
|
|
833
|
+
let power = 0;
|
|
834
|
+
let hubs = 0;
|
|
669
835
|
let resourceStorageRaw = 0n;
|
|
670
|
-
|
|
836
|
+
// Tags come from the Claim Stake definition, the Planet and every building.
|
|
837
|
+
const providedTags = new Set([
|
|
838
|
+
...claimDefinition.providedTagIds,
|
|
839
|
+
...planetBody.details.providedTags,
|
|
840
|
+
]);
|
|
671
841
|
for (const [buildingId, quantity] of result) {
|
|
672
842
|
const definition = definitions.get(buildingId);
|
|
673
843
|
if (definition === undefined) {
|
|
@@ -680,9 +850,15 @@ export async function planClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
680
850
|
definition.hubValue !== claimDefinition.hubValue) {
|
|
681
851
|
fail(`Hub building ${definition.name} does not match Claim Stake ${claimDefinition.name}'s hub value. Choose the matching hub before retrying.`, stake.address);
|
|
682
852
|
}
|
|
853
|
+
if (definition.hubValue > 0) {
|
|
854
|
+
hubs += 1;
|
|
855
|
+
if (quantity !== 1) {
|
|
856
|
+
fail(`The resulting Claim Stake design has ${String(quantity)} of hub building ${definition.name}; a Claim Stake holds exactly one hub. Remove the extra hub before retrying.`, stake.address);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
683
859
|
usedSlots += definition.slots * quantity;
|
|
684
|
-
crewSlots += definition.crewSlots * quantity;
|
|
685
860
|
neededCrew += definition.neededCrew * quantity;
|
|
861
|
+
power += definition.power * quantity;
|
|
686
862
|
resourceStorageRaw += definition.resourceStorageRaw * BigInt(quantity);
|
|
687
863
|
if (neededCrew > U16_MAX) {
|
|
688
864
|
fail(`The resulting Claim Stake design has ${String(neededCrew)} needed crew, exceeding the ${String(U16_MAX)} maximum representable by its unsigned u16 needed-crew field. Remove crew-requiring buildings and retry.`, stake.address);
|
|
@@ -695,8 +871,11 @@ export async function planClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
695
871
|
if (usedSlots > claimDefinition.slots) {
|
|
696
872
|
fail(`Building changes require ${String(usedSlots)} slots, exceeding Claim Stake ${claimDefinition.name}'s ${String(claimDefinition.slots)} slot capacity. Remove buildings and retry.`, stake.address);
|
|
697
873
|
}
|
|
698
|
-
if (
|
|
699
|
-
fail(`
|
|
874
|
+
if (hubs > 1) {
|
|
875
|
+
fail(`The resulting Claim Stake design has ${String(hubs)} hub buildings; a Claim Stake holds exactly one hub. Remove the extra hubs before retrying.`, stake.address);
|
|
876
|
+
}
|
|
877
|
+
if (power < 0) {
|
|
878
|
+
fail(`The resulting Claim Stake design uses ${String(-power)} more power than its buildings generate. Add power-generating buildings or remove power consumers before retrying.`, stake.address);
|
|
700
879
|
}
|
|
701
880
|
for (const [buildingId] of result) {
|
|
702
881
|
const definition = definitions.get(buildingId);
|
|
@@ -714,10 +893,7 @@ export async function planClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
714
893
|
if (addedCrew > availableCrew) {
|
|
715
894
|
fail(`Building additions require ${String(addedCrew)} crew, but Starbase Player ${player} has only ${String(availableCrew)} known crew capacity available. Free crew, refresh the Starbase Player, and retry.`, player);
|
|
716
895
|
}
|
|
717
|
-
const cargo = new Map(
|
|
718
|
-
cargoId,
|
|
719
|
-
amount,
|
|
720
|
-
]));
|
|
896
|
+
const cargo = new Map(currentPlayer.cargo.amounts.map(({ cargoId, amount }) => [cargoId, amount]));
|
|
721
897
|
const constructionCosts = new Map();
|
|
722
898
|
for (const change of options.buildingChanges) {
|
|
723
899
|
if (change.kind !== 'add')
|
|
@@ -732,7 +908,7 @@ export async function planClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
732
908
|
const available = cargo.get(cargoId) ?? 0n;
|
|
733
909
|
if (required > available) {
|
|
734
910
|
const snapshotItem = stake.resources.inventory.items.find(({ id }) => id === cargoId);
|
|
735
|
-
fail(`Building construction requires ${String(required)} raw ${snapshotItem?.name ?? `cargo ${String(cargoId)}`}, but
|
|
911
|
+
fail(`Building construction requires ${String(required)} raw ${snapshotItem?.name ?? `cargo ${String(cargoId)}`}, but Starbase Player ${player} has only ${String(available)} known in Starbase cargo. Construction cargo is taken from the Starbase, not from the Claim Stake. Deposit it at the Starbase, refresh the Starbase Player, and retry.`, player);
|
|
736
912
|
}
|
|
737
913
|
}
|
|
738
914
|
if (currentStake.production.resourceCapacityRaw !==
|
|
@@ -744,41 +920,47 @@ export async function planClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
744
920
|
if (currentStake.production.cargoPod.storageCost > resourceStorageRaw) {
|
|
745
921
|
fail(`The resulting Claim Stake design provides ${String(resourceStorageRaw)} raw storage capacity, below the fresh known cargo usage of ${String(currentStake.production.cargoPod.storageCost)}. Keep enough storage buildings, remove cargo, refresh the Claim Stake, and retry building changes.`, stake.address);
|
|
746
922
|
}
|
|
747
|
-
const currencyCache = await
|
|
748
|
-
const description = `Change buildings on Claim Stake ${stake.address}: ${descriptions.join('; ')}.`;
|
|
923
|
+
const currencyCache = await claimStakeCurrencyCache(game);
|
|
749
924
|
const xp = await resolveClaimStakeXp(ctx, game, stake.address);
|
|
750
|
-
|
|
925
|
+
const instruction = adaptClaimStakeBuildingChangesInstruction({
|
|
926
|
+
...xp.accounts,
|
|
927
|
+
authorization: options.authorization,
|
|
928
|
+
buildingChanges: options.buildingChanges.map(({ buildingId, kind, quantity }) => [buildingId, kind === 'add' ? quantity : -quantity]),
|
|
929
|
+
celestialBody: stake.body.address,
|
|
930
|
+
claimStakeInstance: stake.address,
|
|
931
|
+
currencyCache,
|
|
932
|
+
factionOwnership: ownership,
|
|
933
|
+
game,
|
|
934
|
+
profileFaction,
|
|
935
|
+
...rent.accounts,
|
|
936
|
+
sequenceId,
|
|
937
|
+
starbasePlayer: player,
|
|
938
|
+
system,
|
|
939
|
+
});
|
|
940
|
+
// The grown design is funded from the Profile vault.
|
|
941
|
+
const storage = await planClaimStakeStorage(ctx, instruction, profile, [stakeAccount], 'Claim Stake building changes');
|
|
942
|
+
const description = `Change buildings on Claim Stake ${stake.address}: ${descriptions.join('; ')}. ${storage.disclosure}`;
|
|
943
|
+
return buildPlannerPlan({
|
|
751
944
|
kind: 'claim-stakes.building-changes',
|
|
752
945
|
preconditions: [
|
|
753
946
|
...(await Promise.all([
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
947
|
+
accountStatePrecondition(freshGame.account, 'The configured Game retains the exact Claim Stake and building definitions.'),
|
|
948
|
+
accountStatePrecondition(stakeAccount, `Claim Stake ${stake.address} retains its ownership, design sequence, buildings, cargo, crew, and Body relationship.`),
|
|
949
|
+
planetPrecondition(bodyAccount, system),
|
|
950
|
+
characterPrecondition(characterAccount, profile),
|
|
951
|
+
systemPrecondition(systemAccount, currentSystem.name),
|
|
952
|
+
playerPrecondition(playerAccount, player, 'Profile, Character, System, and available crew'),
|
|
953
|
+
accountStatePrecondition(profileFactionAccount, `ProfileFaction ${profileFaction} remains assigned to Profile ${profile} and aligned with the current Starbase controller.`),
|
|
761
954
|
])),
|
|
762
955
|
ownershipPrecondition,
|
|
763
956
|
xp.guard,
|
|
957
|
+
...rent.guards,
|
|
958
|
+
storage.guard,
|
|
764
959
|
],
|
|
765
960
|
steps: [
|
|
766
961
|
{
|
|
767
962
|
describes: description,
|
|
768
|
-
instruction
|
|
769
|
-
...xp.accounts,
|
|
770
|
-
authorization: options.authorization,
|
|
771
|
-
buildingChanges: options.buildingChanges.map(({ buildingId, kind, quantity }) => [buildingId, kind === 'add' ? quantity : -quantity]),
|
|
772
|
-
celestialBody: stake.body.address,
|
|
773
|
-
claimStakeInstance: stake.address,
|
|
774
|
-
currencyCache,
|
|
775
|
-
factionOwnership: ownership,
|
|
776
|
-
game,
|
|
777
|
-
profileFaction,
|
|
778
|
-
sequenceId,
|
|
779
|
-
starbasePlayer: player,
|
|
780
|
-
system,
|
|
781
|
-
}),
|
|
963
|
+
instruction,
|
|
782
964
|
signers: [options.authorization.authority],
|
|
783
965
|
},
|
|
784
966
|
],
|
|
@@ -792,10 +974,20 @@ export async function planClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
792
974
|
* CurrencyCache, and a known positive rent balance. Rent timing and the final
|
|
793
975
|
* crew/building validation remain chain-authoritative.
|
|
794
976
|
*
|
|
977
|
+
* Finalization can draw Profile storage this Plan does not bound: a removed
|
|
978
|
+
* building's refund can open a Starbase Player cargo line, and a final layout
|
|
979
|
+
* that produces a new resource raises the stake's rent floor. The program
|
|
980
|
+
* funds both from the Profile vault with the signing key, so simulate before
|
|
981
|
+
* signing.
|
|
982
|
+
*
|
|
795
983
|
* Requires Game 2 and its existing canonical Claim Stake XP ledger.
|
|
796
984
|
* The Character XP budget and configuration must also be reconciled.
|
|
797
985
|
* Missing XP state must be repaired outside this Plan; no accounts are created.
|
|
798
986
|
*
|
|
987
|
+
* Requires Disabled rent: the Game's rent catalog and the Claim Stake's rent
|
|
988
|
+
* settlement authority must not exist, and both stay guarded absent until
|
|
989
|
+
* signing. The instruction carries no rent history.
|
|
990
|
+
*
|
|
799
991
|
* @example
|
|
800
992
|
* ```ts
|
|
801
993
|
* declare const ctx: SageContext;
|
|
@@ -811,22 +1003,19 @@ export async function planClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
811
1003
|
export async function planFinalizeClaimStakeBuildingChanges(ctx, stake, input) {
|
|
812
1004
|
const options = validateFinalizeBuildingChangeOptions(input);
|
|
813
1005
|
const game = requireGameAddress(ctx);
|
|
1006
|
+
const { profile } = options.authorization;
|
|
814
1007
|
if (stake.state.kind !== 'design') {
|
|
815
1008
|
fail(`Claim Stake ${stake.address} is not in design state. Refresh it and finalize only a pending building design.`, stake.address);
|
|
816
1009
|
}
|
|
817
|
-
|
|
818
|
-
fail(`Claim Stake ${stake.address} does not match the configured Game ${game}. Refresh it through this context and retry.`, stake.address);
|
|
819
|
-
}
|
|
820
|
-
const character = await findCharacterPda(options.authorization.profile, game);
|
|
821
|
-
if (stake.ownerCharacter.address !== character) {
|
|
822
|
-
fail(`Claim Stake ${stake.address} does not belong to authorization Profile ${options.authorization.profile}'s canonical Character ${character}. Choose an owned Claim Stake, refresh it, and retry.`, stake.address);
|
|
823
|
-
}
|
|
1010
|
+
const character = await requireOwnedStake(stake, game, profile);
|
|
824
1011
|
if (stake.rentBalanceRaw <= 0n) {
|
|
825
1012
|
fail(`Claim Stake ${stake.address} has a known delinquent rent balance of ${String(stake.rentBalanceRaw)} raw units. Top up rent, refresh the Claim Stake, and retry finalization.`, stake.address);
|
|
826
1013
|
}
|
|
827
|
-
const
|
|
1014
|
+
const action = 'finalization';
|
|
1015
|
+
const [freshGame, loaded, rent] = await Promise.all([
|
|
828
1016
|
readFreshGameClaimStakeConfiguration(ctx),
|
|
829
|
-
|
|
1017
|
+
readOwnedStake(ctx, stake, action, [character]),
|
|
1018
|
+
requireDisabledStakeRent(ctx, game, stake.address, action),
|
|
830
1019
|
]);
|
|
831
1020
|
if (freshGame === undefined) {
|
|
832
1021
|
fail(`Configured Game ${game} is missing. Refresh the Game catalog and retry finalization.`, game);
|
|
@@ -835,79 +1024,38 @@ export async function planFinalizeClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
835
1024
|
freshGame.data.buildings.sequenceId !== stake.buildingDefinitionSeqId) {
|
|
836
1025
|
fail(`Claim Stake ${stake.address} definition sequence is stale against the current Game catalog. Refresh the Claim Stake and definitions to rule out stale local data. If the on-chain generation still differs, use a Claim Stake matching the current catalog before retrying finalization.`, stake.address);
|
|
837
1026
|
}
|
|
838
|
-
const
|
|
839
|
-
|
|
840
|
-
const characterAccount = requireAccount(firstAccounts[2], character, `Canonical Character ${character} is missing. Refresh the Profile Character and retry finalization.`);
|
|
841
|
-
const currentStake = claimStakeAccountDefinition.decode(stakeAccount);
|
|
842
|
-
const currentBody = celestialBodyAccountDefinition.decode(bodyAccount);
|
|
843
|
-
const currentCharacter = characterAccountDefinition.decode(characterAccount);
|
|
844
|
-
if (currentStake.game !== game ||
|
|
845
|
-
currentStake.body !== stake.body.address ||
|
|
846
|
-
currentStake.ownerCharacter !== character ||
|
|
847
|
-
currentStake.claimStakeDefinitionId !== stake.claimStakeDefinitionId ||
|
|
848
|
-
currentStake.claimStakeDefinitionSeqId !==
|
|
849
|
-
stake.claimStakeDefinitionSeqId ||
|
|
850
|
-
currentStake.buildingDefinitionSeqId !== stake.buildingDefinitionSeqId ||
|
|
851
|
-
currentStake.systemSeqId !== stake.systemSeqId ||
|
|
1027
|
+
const { bodyAccount, currentStake, stakeAccount } = loaded;
|
|
1028
|
+
if (!sameOwnedStake(currentStake, stake, game, profile) ||
|
|
852
1029
|
currentStake.rentBalanceRaw !== stake.rentBalanceRaw ||
|
|
853
|
-
!sameQuantities(currentStake.buildings, stake.buildings) ||
|
|
854
1030
|
currentStake.state.kind !== 'design' ||
|
|
855
1031
|
currentStake.state.sequenceId !== stake.state.sequenceId ||
|
|
856
1032
|
!sameQuantities(currentStake.state.buildings, stake.state.buildings)) {
|
|
857
1033
|
fail(`Claim Stake ${stake.address} changed or does not match its loaded ownership, Body, definitions, buildings, design sequence, rent, or System generation. Refresh it and retry finalization.`, stake.address);
|
|
858
1034
|
}
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
fail(`Celestial Body ${stake.body.address} does not match the Claim Stake's configured Game, canonical Planet identity, or System generation. Refresh the Body and Claim Stake before retrying finalization.`, stake.body.address);
|
|
869
|
-
}
|
|
870
|
-
const system = currentBody.system;
|
|
871
|
-
const player = await deriveStarbasePlayerAddress(system, character);
|
|
872
|
-
const currencyCache = await deriveCurrencyCache(game).then(([address]) => address);
|
|
873
|
-
const [systemCandidate, playerCandidate, currencyCandidate] = await readContextRawAccounts(ctx, [system, player, currencyCache]);
|
|
874
|
-
const systemAccount = requireAccount(systemCandidate, system, `Star System ${system} is missing. Refresh the Claim Stake's System and retry finalization.`);
|
|
875
|
-
const playerAccount = requireAccount(playerCandidate, player, `Starbase Player ${player} is missing for authorization Profile ${options.authorization.profile}. Register or refresh it in the Claim Stake's System before retrying finalization.`);
|
|
876
|
-
const currencyAccount = requireAccount(currencyCandidate, currencyCache, `Canonical CurrencyCache ${currencyCache} is missing for configured Game ${game}. Refresh the Game currency configuration and retry finalization.`);
|
|
877
|
-
const currentSystem = starSystemAccountDefinition.decode(systemAccount);
|
|
878
|
-
const currentPlayer = starbasePlayerAccountDefinition.decode(playerAccount);
|
|
879
|
-
if (currentSystem.game !== game ||
|
|
880
|
-
currentSystem.sequenceId !== stake.systemSeqId ||
|
|
881
|
-
currentSystem.starbase === undefined ||
|
|
882
|
-
(await deriveStarSystemAddress(game, currentSystem.systemId)) !== system) {
|
|
883
|
-
fail(`Star System ${system} does not match the configured Game, canonical identity, Claim Stake generation, or an active nested Starbase. Refresh the System and retry finalization.`, system);
|
|
884
|
-
}
|
|
885
|
-
if (currentPlayer.playerProfile !== options.authorization.profile ||
|
|
886
|
-
currentPlayer.character !== character ||
|
|
887
|
-
currentPlayer.system !== system) {
|
|
888
|
-
fail(`Starbase Player ${player} does not match the authorization Profile, canonical Character, and Claim Stake System. Refresh it and retry finalization.`, player);
|
|
889
|
-
}
|
|
890
|
-
await validateCurrencyCache(currencyAccount, game, 'Claim Stake finalization');
|
|
891
|
-
const description = `Finalize building changes on Claim Stake ${stake.address}.`;
|
|
1035
|
+
requireCommittedCrewVersion(currentStake, stake, 'finalized');
|
|
1036
|
+
const planet = await requireDesignStakePlanet(loaded.currentBody, stake, game, action);
|
|
1037
|
+
const { system } = planet;
|
|
1038
|
+
const { account: characterAccount } = requireProfileCharacter(loaded.extraAccounts[0], character, profile, game, action);
|
|
1039
|
+
const currencyCache = await claimStakeCurrencyCache(game);
|
|
1040
|
+
const { currentSystem, extraAccounts: [currencyCandidate], player, playerAccount, starbase, systemAccount, } = await readStakeStarbase(ctx, stake, game, system, character, profile, action, [currencyCache]);
|
|
1041
|
+
requireStakeRegistered(planet.details.claimedPlots, stake, starbase.level, action);
|
|
1042
|
+
const currencyGuard = await requireCurrencyCache(currencyCandidate, currencyCache, game, action, 'Claim Stake finalization');
|
|
1043
|
+
const description = `Finalize building changes on Claim Stake ${stake.address}. A building refund that opens a Starbase Player cargo line, or a new resource that raises the stake's rent floor, is funded from the Profile vault with the signing key, which this Plan does not bound; simulate before signing.`;
|
|
892
1044
|
const xp = await resolveClaimStakeXp(ctx, game, stake.address, character);
|
|
893
|
-
return
|
|
1045
|
+
return buildPlannerPlan({
|
|
894
1046
|
kind: 'claim-stakes.finalize-building-changes',
|
|
895
1047
|
preconditions: [
|
|
896
1048
|
xp.guard,
|
|
897
1049
|
...(await Promise.all([
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
1050
|
+
accountStatePrecondition(freshGame.account, 'The configured Game remains current.'),
|
|
1051
|
+
accountStatePrecondition(stakeAccount, `Claim Stake ${stake.address} retains its ownership, design sequence, rent balance, Body, and System generation.`),
|
|
1052
|
+
characterPrecondition(characterAccount, profile),
|
|
1053
|
+
planetPrecondition(bodyAccount, system),
|
|
1054
|
+
systemPrecondition(systemAccount, currentSystem.name),
|
|
1055
|
+
playerPrecondition(playerAccount, player),
|
|
904
1056
|
])),
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
address: currencyCache,
|
|
908
|
-
game,
|
|
909
|
-
describes: 'The canonical CurrencyCache remains assigned to the configured Game; shared accounting may change.',
|
|
910
|
-
},
|
|
1057
|
+
currencyGuard,
|
|
1058
|
+
...rent.guards,
|
|
911
1059
|
],
|
|
912
1060
|
steps: [
|
|
913
1061
|
{
|
|
@@ -920,6 +1068,7 @@ export async function planFinalizeClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
920
1068
|
claimStakeInstance: stake.address,
|
|
921
1069
|
currencyCache,
|
|
922
1070
|
game,
|
|
1071
|
+
...rent.accounts,
|
|
923
1072
|
systemAndStarbasePlayerStarbasePlayer: player,
|
|
924
1073
|
systemAndStarbasePlayerSystem: system,
|
|
925
1074
|
}),
|
|
@@ -940,6 +1089,10 @@ export async function planFinalizeClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
940
1089
|
* Requires Game 2 and its existing canonical Claim Stake XP ledger.
|
|
941
1090
|
* Missing XP state must be repaired outside this Plan; no accounts are created.
|
|
942
1091
|
*
|
|
1092
|
+
* Requires Disabled rent: the Game's rent catalog and the Claim Stake's rent
|
|
1093
|
+
* settlement authority must not exist, and both stay guarded absent until
|
|
1094
|
+
* signing. The instruction carries no rent history.
|
|
1095
|
+
*
|
|
943
1096
|
* @example
|
|
944
1097
|
* ```ts
|
|
945
1098
|
* declare const ctx: SageContext;
|
|
@@ -954,84 +1107,42 @@ export async function planFinalizeClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
954
1107
|
export async function planCancelClaimStakeBuildingChanges(ctx, stake, input) {
|
|
955
1108
|
const options = validateCancelBuildingChangeOptions(input);
|
|
956
1109
|
const game = requireGameAddress(ctx);
|
|
1110
|
+
const { profile } = options.authorization;
|
|
957
1111
|
if (stake.state.kind !== 'design') {
|
|
958
1112
|
fail(`Claim Stake ${stake.address} is not in design state. Refresh it and cancel only a pending building design.`, stake.address);
|
|
959
1113
|
}
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
fail(`Claim Stake ${stake.address} does not belong to authorization Profile ${options.authorization.profile}'s canonical Character ${character}. Choose an owned Claim Stake, refresh it, and retry.`, stake.address);
|
|
966
|
-
}
|
|
967
|
-
const firstAccounts = await readContextRawAccounts(ctx, [
|
|
968
|
-
stake.address,
|
|
969
|
-
stake.body.address,
|
|
1114
|
+
const character = await requireOwnedStake(stake, game, profile);
|
|
1115
|
+
const action = 'cancellation';
|
|
1116
|
+
const [{ bodyAccount, currentBody, currentStake, stakeAccount }, rent] = await Promise.all([
|
|
1117
|
+
readOwnedStake(ctx, stake, action),
|
|
1118
|
+
requireDisabledStakeRent(ctx, game, stake.address, action),
|
|
970
1119
|
]);
|
|
971
|
-
|
|
972
|
-
const bodyAccount = requireAccount(firstAccounts[1], stake.body.address, `Celestial Body ${stake.body.address} is missing. Refresh the Claim Stake Body and retry cancellation.`);
|
|
973
|
-
const currentStake = claimStakeAccountDefinition.decode(stakeAccount);
|
|
974
|
-
const currentBody = celestialBodyAccountDefinition.decode(bodyAccount);
|
|
975
|
-
if (currentStake.game !== game ||
|
|
976
|
-
currentStake.body !== stake.body.address ||
|
|
977
|
-
currentStake.ownerCharacter !== character ||
|
|
978
|
-
currentStake.claimStakeDefinitionId !== stake.claimStakeDefinitionId ||
|
|
979
|
-
currentStake.claimStakeDefinitionSeqId !==
|
|
980
|
-
stake.claimStakeDefinitionSeqId ||
|
|
981
|
-
currentStake.buildingDefinitionSeqId !== stake.buildingDefinitionSeqId ||
|
|
982
|
-
currentStake.systemSeqId !== stake.systemSeqId ||
|
|
983
|
-
!sameQuantities(currentStake.buildings, stake.buildings) ||
|
|
1120
|
+
if (!sameOwnedStake(currentStake, stake, game, profile) ||
|
|
984
1121
|
currentStake.state.kind !== 'design' ||
|
|
985
1122
|
currentStake.state.sequenceId !== stake.state.sequenceId ||
|
|
986
1123
|
!sameQuantities(currentStake.state.buildings, stake.state.buildings)) {
|
|
987
1124
|
fail(`Claim Stake ${stake.address} changed or does not match its loaded ownership, Body, definitions, buildings, design sequence, or System generation. Refresh it and retry cancellation.`, stake.address);
|
|
988
1125
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
}
|
|
996
|
-
const system = currentBody.system;
|
|
997
|
-
const player = await deriveStarbasePlayerAddress(system, character);
|
|
998
|
-
const currencyCache = await deriveCurrencyCache(game).then(([address]) => address);
|
|
999
|
-
const [systemCandidate, playerCandidate, currencyCandidate] = await readContextRawAccounts(ctx, [system, player, currencyCache]);
|
|
1000
|
-
const systemAccount = requireAccount(systemCandidate, system, `Star System ${system} is missing. Refresh the Claim Stake's System and retry cancellation.`);
|
|
1001
|
-
const playerAccount = requireAccount(playerCandidate, player, `Starbase Player ${player} is missing for authorization Profile ${options.authorization.profile}. Register or refresh it in the Claim Stake's System before retrying cancellation.`);
|
|
1002
|
-
const currencyAccount = requireAccount(currencyCandidate, currencyCache, `Canonical CurrencyCache ${currencyCache} is missing for configured Game ${game}. Refresh the Game currency configuration and retry cancellation.`);
|
|
1003
|
-
const currentSystem = starSystemAccountDefinition.decode(systemAccount);
|
|
1004
|
-
const currentPlayer = starbasePlayerAccountDefinition.decode(playerAccount);
|
|
1005
|
-
if (currentSystem.game !== game ||
|
|
1006
|
-
currentSystem.sequenceId !== stake.systemSeqId ||
|
|
1007
|
-
currentSystem.starbase === undefined ||
|
|
1008
|
-
(await deriveStarSystemAddress(game, currentSystem.systemId)) !== system) {
|
|
1009
|
-
fail(`Star System ${system} does not match the configured Game, canonical identity, Claim Stake generation, or an active nested Starbase. Refresh the System and retry cancellation.`, system);
|
|
1010
|
-
}
|
|
1011
|
-
if (currentPlayer.playerProfile !== options.authorization.profile ||
|
|
1012
|
-
currentPlayer.character !== character ||
|
|
1013
|
-
currentPlayer.system !== system) {
|
|
1014
|
-
fail(`Starbase Player ${player} does not match the authorization Profile, canonical Character, and Claim Stake System. Refresh it and retry cancellation.`, player);
|
|
1015
|
-
}
|
|
1016
|
-
await validateCurrencyCache(currencyAccount, game, 'Claim Stake cancellation');
|
|
1126
|
+
const planet = await requireDesignStakePlanet(currentBody, stake, game, action);
|
|
1127
|
+
const { system } = planet;
|
|
1128
|
+
const currencyCache = await claimStakeCurrencyCache(game);
|
|
1129
|
+
const { currentSystem, extraAccounts: [currencyCandidate], player, playerAccount, starbase, systemAccount, } = await readStakeStarbase(ctx, stake, game, system, character, profile, action, [currencyCache]);
|
|
1130
|
+
requireStakeRegistered(planet.details.claimedPlots, stake, starbase.level, action);
|
|
1131
|
+
const currencyGuard = await requireCurrencyCache(currencyCandidate, currencyCache, game, action, 'Claim Stake cancellation');
|
|
1017
1132
|
const description = `Cancel the pending building design on Claim Stake ${stake.address} and return it to active state.`;
|
|
1018
1133
|
const xp = await resolveClaimStakeXp(ctx, game, stake.address);
|
|
1019
|
-
return
|
|
1134
|
+
return buildPlannerPlan({
|
|
1020
1135
|
kind: 'claim-stakes.cancel-building-changes',
|
|
1021
1136
|
preconditions: [
|
|
1022
1137
|
xp.guard,
|
|
1023
1138
|
...(await Promise.all([
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1139
|
+
accountStatePrecondition(stakeAccount, `Claim Stake ${stake.address} retains its ownership, design sequence, buildings, Body, and System generation.`),
|
|
1140
|
+
planetPrecondition(bodyAccount, system),
|
|
1141
|
+
systemPrecondition(systemAccount, currentSystem.name),
|
|
1142
|
+
playerPrecondition(playerAccount, player),
|
|
1028
1143
|
])),
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
address: currencyCache,
|
|
1032
|
-
game,
|
|
1033
|
-
describes: 'The canonical CurrencyCache remains assigned to the configured Game; shared accounting may change.',
|
|
1034
|
-
},
|
|
1144
|
+
currencyGuard,
|
|
1145
|
+
...rent.guards,
|
|
1035
1146
|
],
|
|
1036
1147
|
steps: [
|
|
1037
1148
|
{
|
|
@@ -1043,6 +1154,7 @@ export async function planCancelClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
1043
1154
|
claimStakeInstance: stake.address,
|
|
1044
1155
|
currencyCache,
|
|
1045
1156
|
game,
|
|
1157
|
+
...rent.accounts,
|
|
1046
1158
|
starbasePlayer: player,
|
|
1047
1159
|
system,
|
|
1048
1160
|
}),
|
|
@@ -1054,13 +1166,19 @@ export async function planCancelClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
1054
1166
|
}
|
|
1055
1167
|
/** Plans deconstruction of one owned active Claim Stake.
|
|
1056
1168
|
*
|
|
1057
|
-
* The planner derives the
|
|
1058
|
-
*
|
|
1169
|
+
* The planner derives the plot level from the fresh Planet plot row that
|
|
1170
|
+
* records the stake, and the index from its position in that row. The only
|
|
1059
1171
|
* remaining building must be the definition-compatible zero-cost bundled hub,
|
|
1060
1172
|
* which deconstruction discards.
|
|
1061
1173
|
* Rent settlement, cargo return, account closure, and concurrent races remain
|
|
1062
1174
|
* chain-authoritative; the Plan does not estimate a refund.
|
|
1063
1175
|
*
|
|
1176
|
+
* Requires Disabled rent: the Game's rent catalog and the Claim Stake's rent
|
|
1177
|
+
* settlement authority must not exist, and both stay guarded absent until
|
|
1178
|
+
* signing. The instruction carries no rent history. Deconstruction also
|
|
1179
|
+
* requires the canonical Currency Cache and closes the Claim Stake's XP ledger;
|
|
1180
|
+
* a Claim Stake without a ledger accrued no XP.
|
|
1181
|
+
*
|
|
1064
1182
|
* @example
|
|
1065
1183
|
* ```ts
|
|
1066
1184
|
* declare const ctx: SageContext;
|
|
@@ -1073,46 +1191,27 @@ export async function planCancelClaimStakeBuildingChanges(ctx, stake, input) {
|
|
|
1073
1191
|
export async function planDeconstructClaimStake(ctx, stake, input) {
|
|
1074
1192
|
const options = validateDeconstructOptions(input);
|
|
1075
1193
|
const game = requireGameAddress(ctx);
|
|
1194
|
+
const { profile } = options.authorization;
|
|
1076
1195
|
if (stake.state.kind !== 'active') {
|
|
1077
1196
|
fail(`Claim Stake ${stake.address} is not in active state. Refresh it, finalize or cancel any pending design, and retry deconstruction.`, stake.address);
|
|
1078
1197
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
}
|
|
1082
|
-
const character = await findCharacterPda(options.authorization.profile, game);
|
|
1083
|
-
if (stake.ownerCharacter.address !== character) {
|
|
1084
|
-
fail(`Claim Stake ${stake.address} does not belong to authorization Profile ${options.authorization.profile}'s canonical Character ${character}. Choose an owned Claim Stake, refresh it, and retry.`, stake.address);
|
|
1085
|
-
}
|
|
1086
|
-
const [freshGame, firstAccounts] = await Promise.all([
|
|
1198
|
+
const character = await requireOwnedStake(stake, game, profile);
|
|
1199
|
+
const action = 'deconstruction';
|
|
1200
|
+
const [freshGame, { bodyAccount, currentBody, currentStake, stakeAccount }, rent,] = await Promise.all([
|
|
1087
1201
|
readFreshGameClaimStakeConfiguration(ctx),
|
|
1088
|
-
|
|
1202
|
+
readOwnedStake(ctx, stake, action),
|
|
1203
|
+
requireDisabledStakeRent(ctx, game, stake.address, action),
|
|
1089
1204
|
]);
|
|
1090
1205
|
if (freshGame === undefined) {
|
|
1091
1206
|
fail(`Configured Game ${game} is missing. Refresh the Game definitions and retry deconstruction.`, game);
|
|
1092
1207
|
}
|
|
1093
|
-
|
|
1094
|
-
const bodyAccount = requireAccount(firstAccounts[1], stake.body.address, `Celestial Body ${stake.body.address} is missing. Refresh the Claim Stake Body and retry deconstruction.`);
|
|
1095
|
-
const currentStake = claimStakeAccountDefinition.decode(stakeAccount);
|
|
1096
|
-
const currentBody = celestialBodyAccountDefinition.decode(bodyAccount);
|
|
1097
|
-
if (currentStake.game !== game ||
|
|
1098
|
-
currentStake.body !== stake.body.address ||
|
|
1099
|
-
currentStake.ownerCharacter !== character ||
|
|
1100
|
-
currentStake.claimStakeDefinitionId !== stake.claimStakeDefinitionId ||
|
|
1101
|
-
currentStake.claimStakeDefinitionSeqId !==
|
|
1102
|
-
stake.claimStakeDefinitionSeqId ||
|
|
1103
|
-
currentStake.buildingDefinitionSeqId !== stake.buildingDefinitionSeqId ||
|
|
1104
|
-
currentStake.systemSeqId !== stake.systemSeqId ||
|
|
1105
|
-
!sameQuantities(currentStake.buildings, stake.buildings) ||
|
|
1208
|
+
if (!sameOwnedStake(currentStake, stake, game, profile) ||
|
|
1106
1209
|
currentStake.state.kind !== 'active') {
|
|
1107
1210
|
fail(`Claim Stake ${stake.address} changed or does not match its loaded ownership, Body, definitions, buildings, active state, or System generation. Refresh it and retry deconstruction.`, stake.address);
|
|
1108
1211
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
(await deriveCelestialBodyAddress(game, currentBody.id)) !==
|
|
1113
|
-
stake.body.address) {
|
|
1114
|
-
fail(`Celestial Body ${stake.body.address} does not match the Claim Stake's configured Game, canonical Planet identity, or System generation. Refresh the Body and Claim Stake before retrying deconstruction.`, stake.body.address);
|
|
1115
|
-
}
|
|
1212
|
+
requireCommittedCrewVersion(currentStake, stake, 'deconstructed');
|
|
1213
|
+
const planet = await requireStakePlanet(currentBody, stake, game, action);
|
|
1214
|
+
const { system } = planet;
|
|
1116
1215
|
if (freshGame.data.claimStakes.sequenceId !== stake.claimStakeDefinitionSeqId) {
|
|
1117
1216
|
fail(`Claim Stake ${stake.address} definition generation is stale against the current Game catalog. Refresh the Claim Stake and definitions to rule out stale local data. If the on-chain generation still differs, use a Claim Stake matching the current catalog before retrying deconstruction.`, stake.address);
|
|
1118
1217
|
}
|
|
@@ -1146,81 +1245,72 @@ export async function planDeconstructClaimStake(ctx, stake, input) {
|
|
|
1146
1245
|
? `Claim Stake ${stake.address} does not contain exactly one verified bundled hub. Refresh it and restore the definition-compatible bundled hub before retrying deconstruction.`
|
|
1147
1246
|
: `Claim Stake ${stake.address} holds ${bundledHub.name} (${String(bundledHub.id)}), which is not the zero-cost ${claimDefinition.tier} bundled hub for Claim Stake definition ${String(claimDefinition.id)} (${claimDefinition.name}). Refresh the Claim Stake and Game definitions so the recorded hub matches its definition before retrying deconstruction.`, stake.address);
|
|
1148
1247
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
if (
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1248
|
+
// Each plot row is a Starbase level; the stake's row and its position in
|
|
1249
|
+
// that row's chronology give the deconstruction level and index.
|
|
1250
|
+
const positions = claimStakePlotPositions(planet.details.claimedPlots, stake.address);
|
|
1251
|
+
if (positions.length !== 1) {
|
|
1252
|
+
fail(`Claim Stake ${stake.address} must appear exactly once in Planet ${stake.body.address}'s plot chronology before its deconstruction level and index can be derived. Refresh the Body and retry.`, stake.body.address);
|
|
1253
|
+
}
|
|
1254
|
+
const { index: claimStakeIndex, row } = positions[0];
|
|
1255
|
+
const rowGroups = planet.details.claimedPlots.filter(({ key }) => key === row);
|
|
1256
|
+
if (!Number.isInteger(row) ||
|
|
1257
|
+
row < 0 ||
|
|
1258
|
+
row >= CLAIM_STAKE_PLOT_ROWS ||
|
|
1259
|
+
rowGroups.length !== 1) {
|
|
1260
|
+
fail(`Planet ${stake.body.address} records Claim Stake ${stake.address} in plot row ${String(row)}, which is not exactly one Starbase level row. Refresh the Body and verify the pinned binding version before retrying deconstruction.`, stake.body.address);
|
|
1261
|
+
}
|
|
1262
|
+
const activeStructures = rowGroups[0].structures.filter(({ address, deactivationTimeUnixSeconds }) => address === stake.address && deactivationTimeUnixSeconds === 0n);
|
|
1161
1263
|
if (activeStructures.length !== 1) {
|
|
1162
1264
|
fail(`Claim Stake ${stake.address} is not represented exactly once as an active structure in the Planet Body data. Refresh the Body and retry deconstruction.`, stake.body.address);
|
|
1163
1265
|
}
|
|
1164
|
-
const
|
|
1165
|
-
const
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
const
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
const systemAccount = requireAccount(systemCandidate, system, `Star System ${system} is missing. Refresh the Claim Stake's System and retry deconstruction.`);
|
|
1180
|
-
const playerAccount = requireAccount(playerCandidate, player, `Starbase Player ${player} is missing for authorization Profile ${options.authorization.profile}. Register or refresh it in the Claim Stake's System before retrying deconstruction.`);
|
|
1181
|
-
const currentCharacter = characterAccountDefinition.decode(characterAccount);
|
|
1182
|
-
const currentSystem = starSystemAccountDefinition.decode(systemAccount);
|
|
1183
|
-
const currentPlayer = starbasePlayerAccountDefinition.decode(playerAccount);
|
|
1184
|
-
if (currentCharacter.playerProfile !== options.authorization.profile ||
|
|
1185
|
-
currentCharacter.game !== game) {
|
|
1186
|
-
fail(`Character ${character} does not match authorization Profile ${options.authorization.profile} and configured Game ${game}. Refresh the Character and retry deconstruction.`, character);
|
|
1187
|
-
}
|
|
1188
|
-
if (currentSystem.game !== game ||
|
|
1189
|
-
currentSystem.sequenceId !== stake.systemSeqId ||
|
|
1190
|
-
currentSystem.starbase === undefined ||
|
|
1191
|
-
!currentSystem.celestialBodyAddresses.includes(stake.body.address) ||
|
|
1192
|
-
(await deriveStarSystemAddress(game, currentSystem.systemId)) !== system) {
|
|
1193
|
-
fail(`Star System ${system} does not match the configured Game, canonical identity, Claim Stake generation, or an active nested Starbase. Refresh the System and retry deconstruction.`, system);
|
|
1194
|
-
}
|
|
1195
|
-
if (currentPlayer.playerProfile !== options.authorization.profile ||
|
|
1196
|
-
currentPlayer.character !== character ||
|
|
1197
|
-
currentPlayer.system !== system) {
|
|
1198
|
-
fail(`Starbase Player ${player} does not match the authorization Profile, canonical Character, and Claim Stake System. Refresh it and retry deconstruction.`, player);
|
|
1199
|
-
}
|
|
1266
|
+
const claimStakeLevel = CLAIM_STAKE_PLOT_LEVELS[row];
|
|
1267
|
+
const [currencyCache, [xpAccrual]] = await Promise.all([
|
|
1268
|
+
claimStakeCurrencyCache(game),
|
|
1269
|
+
deriveStructureXpAccrualAddress(stake.address),
|
|
1270
|
+
]);
|
|
1271
|
+
const { currentSystem, extraAccounts: [characterCandidate, currencyCandidate, ledgerCandidate], player, playerAccount, systemAccount, } = await readStakeStarbase(ctx, stake, game, system, character, profile, action, [character, currencyCache, xpAccrual]);
|
|
1272
|
+
const { account: characterAccount } = requireProfileCharacter(characterCandidate, character, profile, game, action);
|
|
1273
|
+
const currencyGuard = await requireCurrencyCache(currencyCandidate, currencyCache, game, action, 'Claim Stake deconstruction');
|
|
1274
|
+
// Deconstruction closes an existing XP ledger; a stake without one accrued nothing.
|
|
1275
|
+
const xp = ledgerCandidate === undefined
|
|
1276
|
+
? {
|
|
1277
|
+
accounts: {},
|
|
1278
|
+
guard: accountAbsentPrecondition(xpAccrual, `Claim Stake ${stake.address} XP ledger ${xpAccrual} remains absent, so no Building XP has accrued.`),
|
|
1279
|
+
}
|
|
1280
|
+
: await resolveClaimStakeXp(ctx, game, stake.address, character);
|
|
1200
1281
|
const description = `Deconstruct Claim Stake ${stake.address} and discard its bundled hub ${bundledHub.name}; rent settlement, cargo return, account closure, and any refund remain chain-authoritative.`;
|
|
1201
|
-
return
|
|
1282
|
+
return buildPlannerPlan({
|
|
1202
1283
|
kind: 'claim-stakes.deconstruct',
|
|
1203
|
-
preconditions:
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1284
|
+
preconditions: [
|
|
1285
|
+
...(await Promise.all([
|
|
1286
|
+
accountStatePrecondition(freshGame.account, `The configured Game retains Claim Stake definition ${String(claimDefinition.id)}, bundled hub ${String(bundledHub.id)}, and their current generations.`),
|
|
1287
|
+
accountStatePrecondition(stakeAccount, `Claim Stake ${stake.address} retains its ownership, active state, definitions, bundled hub, Body, and System generation.`),
|
|
1288
|
+
accountStatePrecondition(bodyAccount, `The Planet retains Claim Stake ${stake.address} at chronology index ${String(claimStakeIndex)} in definition group ${String(claimDefinition.id)}.`),
|
|
1289
|
+
characterPrecondition(characterAccount, profile),
|
|
1290
|
+
systemPrecondition(systemAccount, currentSystem.name),
|
|
1291
|
+
playerPrecondition(playerAccount, player),
|
|
1292
|
+
])),
|
|
1293
|
+
currencyGuard,
|
|
1294
|
+
xp.guard,
|
|
1295
|
+
...rent.guards,
|
|
1296
|
+
],
|
|
1211
1297
|
steps: [
|
|
1212
1298
|
{
|
|
1213
1299
|
describes: description,
|
|
1214
1300
|
instruction: adaptDeconstructClaimStakeInstruction({
|
|
1301
|
+
...xp.accounts,
|
|
1215
1302
|
authorization: options.authorization,
|
|
1216
1303
|
celestialBody: stake.body.address,
|
|
1217
1304
|
character,
|
|
1218
1305
|
claimStakeIndex,
|
|
1219
1306
|
claimStakeInstance: stake.address,
|
|
1220
1307
|
claimStakeLevel,
|
|
1308
|
+
currencyCache,
|
|
1221
1309
|
game,
|
|
1310
|
+
...rent.accounts,
|
|
1222
1311
|
systemAndStarbasePlayerStarbasePlayer: player,
|
|
1223
1312
|
systemAndStarbasePlayerSystem: system,
|
|
1313
|
+
xpAccrual,
|
|
1224
1314
|
}),
|
|
1225
1315
|
signers: [options.authorization.authority],
|
|
1226
1316
|
},
|
|
@@ -1228,13 +1318,19 @@ export async function planDeconstructClaimStake(ctx, stake, input) {
|
|
|
1228
1318
|
summary: description,
|
|
1229
1319
|
});
|
|
1230
1320
|
}
|
|
1231
|
-
/** Plans one exact raw rent top-up for an owned
|
|
1321
|
+
/** Plans one exact raw rent top-up for an owned Claim Stake.
|
|
1232
1322
|
*
|
|
1323
|
+
* Active, design and Deactivated (rent-delinquent) stakes all accept a top-up;
|
|
1324
|
+
* topping up a Deactivated stake is how its owner keeps it from eviction.
|
|
1233
1325
|
* The planner validates the fresh Claim Stake and its canonical
|
|
1234
1326
|
* Profile/Character/Planet/System/Starbase Player graph, plus the Character's
|
|
1235
1327
|
* known raw ATLAS balance. Permission checks, concurrent balance changes, rent
|
|
1236
1328
|
* arithmetic, and duration purchased remain chain-authoritative.
|
|
1237
1329
|
*
|
|
1330
|
+
* Requires Disabled rent: the Game's rent catalog and the Claim Stake's rent
|
|
1331
|
+
* settlement authority must not exist, and both stay guarded absent until
|
|
1332
|
+
* signing. The instruction carries no rent history.
|
|
1333
|
+
*
|
|
1238
1334
|
* @example
|
|
1239
1335
|
* ```ts
|
|
1240
1336
|
* declare const ctx: SageContext;
|
|
@@ -1250,87 +1346,40 @@ export async function planDeconstructClaimStake(ctx, stake, input) {
|
|
|
1250
1346
|
export async function planTopUpClaimStakeRent(ctx, stake, input) {
|
|
1251
1347
|
const options = validateTopUpRentOptions(input);
|
|
1252
1348
|
const game = requireGameAddress(ctx);
|
|
1349
|
+
const { profile } = options.authorization;
|
|
1350
|
+
// Under Disabled rent a top-up has no lifecycle gate: a Deactivated stake
|
|
1351
|
+
// accepts one, and that is how its owner avoids eviction.
|
|
1253
1352
|
const loadedState = stake.state;
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
}
|
|
1260
|
-
const character = await findCharacterPda(options.authorization.profile, game);
|
|
1261
|
-
if (stake.ownerCharacter.address !== character) {
|
|
1262
|
-
fail(`Claim Stake ${stake.address} does not belong to authorization Profile ${options.authorization.profile}'s canonical Character ${character}. Choose an owned Claim Stake, refresh it, and retry.`, stake.address);
|
|
1263
|
-
}
|
|
1264
|
-
const firstAccounts = await readContextRawAccounts(ctx, [
|
|
1265
|
-
stake.address,
|
|
1266
|
-
stake.body.address,
|
|
1267
|
-
character,
|
|
1353
|
+
const character = await requireOwnedStake(stake, game, profile);
|
|
1354
|
+
const action = 'the rent top-up';
|
|
1355
|
+
const [{ bodyAccount, currentBody, currentStake, extraAccounts: [characterCandidate], stakeAccount, }, rent,] = await Promise.all([
|
|
1356
|
+
readOwnedStake(ctx, stake, action, [character]),
|
|
1357
|
+
requireDisabledStakeRent(ctx, game, stake.address, action),
|
|
1268
1358
|
]);
|
|
1269
|
-
|
|
1270
|
-
const bodyAccount = requireAccount(firstAccounts[1], stake.body.address, `Celestial Body ${stake.body.address} is missing. Refresh the Claim Stake Body and retry the rent top-up.`);
|
|
1271
|
-
const characterAccount = requireAccount(firstAccounts[2], character, `Canonical Character ${character} is missing. Refresh the Profile Character and retry the rent top-up.`);
|
|
1272
|
-
const currentStake = claimStakeAccountDefinition.decode(stakeAccount);
|
|
1273
|
-
const currentBody = celestialBodyAccountDefinition.decode(bodyAccount);
|
|
1274
|
-
const currentCharacter = characterAccountDefinition.decode(characterAccount);
|
|
1275
|
-
if (currentStake.game !== game ||
|
|
1276
|
-
currentStake.body !== stake.body.address ||
|
|
1277
|
-
currentStake.ownerCharacter !== character ||
|
|
1278
|
-
currentStake.claimStakeDefinitionId !== stake.claimStakeDefinitionId ||
|
|
1279
|
-
currentStake.claimStakeDefinitionSeqId !==
|
|
1280
|
-
stake.claimStakeDefinitionSeqId ||
|
|
1281
|
-
currentStake.buildingDefinitionSeqId !== stake.buildingDefinitionSeqId ||
|
|
1282
|
-
currentStake.systemSeqId !== stake.systemSeqId ||
|
|
1359
|
+
if (!sameOwnedStake(currentStake, stake, game, profile) ||
|
|
1283
1360
|
currentStake.rentBalanceRaw !== stake.rentBalanceRaw ||
|
|
1284
|
-
!sameQuantities(currentStake.buildings, stake.buildings) ||
|
|
1285
1361
|
!sameStakeState(currentStake.state, loadedState)) {
|
|
1286
|
-
fail(`Claim Stake ${stake.address} changed or does not match its loaded ownership, Body, definitions, buildings, rent balance,
|
|
1287
|
-
}
|
|
1288
|
-
if (currentBody.kind !== 'planet' ||
|
|
1289
|
-
currentBody.game !== game ||
|
|
1290
|
-
currentBody.systemSequenceId !== stake.systemSeqId ||
|
|
1291
|
-
(await deriveCelestialBodyAddress(game, currentBody.id)) !==
|
|
1292
|
-
stake.body.address) {
|
|
1293
|
-
fail(`Celestial Body ${stake.body.address} does not match the Claim Stake's configured Game, canonical Planet identity, or System generation. Refresh the Body and Claim Stake before retrying the rent top-up.`, stake.body.address);
|
|
1294
|
-
}
|
|
1295
|
-
if (currentCharacter.playerProfile !== options.authorization.profile ||
|
|
1296
|
-
currentCharacter.game !== game) {
|
|
1297
|
-
fail(`Character ${character} does not match authorization Profile ${options.authorization.profile} and configured Game ${game}. Refresh the Character and retry the rent top-up.`, character);
|
|
1362
|
+
fail(`Claim Stake ${stake.address} changed or does not match its loaded ownership, Body, definitions, buildings, rent balance, lifecycle state, or System generation. Refresh it and retry the rent top-up.`, stake.address);
|
|
1298
1363
|
}
|
|
1364
|
+
const { system } = await requireStakePlanet(currentBody, stake, game, action);
|
|
1365
|
+
const { account: characterAccount, current: currentCharacter } = requireProfileCharacter(characterCandidate, character, profile, game, action);
|
|
1299
1366
|
if (currentCharacter.atlasRaw < options.amount) {
|
|
1300
1367
|
fail(`Character ${character} has only ${String(currentCharacter.atlasRaw)} known raw ATLAS, below the requested ${String(options.amount)} raw rent top-up. Reduce the amount or add ATLAS, refresh the Character, and retry.`, character);
|
|
1301
1368
|
}
|
|
1302
|
-
const
|
|
1303
|
-
const player = await deriveStarbasePlayerAddress(system, character);
|
|
1304
|
-
const [systemCandidate, playerCandidate] = await readContextRawAccounts(ctx, [
|
|
1305
|
-
system,
|
|
1306
|
-
player,
|
|
1307
|
-
]);
|
|
1308
|
-
const systemAccount = requireAccount(systemCandidate, system, `Star System ${system} is missing. Refresh the Claim Stake's System and retry the rent top-up.`);
|
|
1309
|
-
const playerAccount = requireAccount(playerCandidate, player, `Starbase Player ${player} is missing for authorization Profile ${options.authorization.profile}. Register or refresh it in the Claim Stake's System before retrying the rent top-up.`);
|
|
1310
|
-
const currentSystem = starSystemAccountDefinition.decode(systemAccount);
|
|
1311
|
-
const currentPlayer = starbasePlayerAccountDefinition.decode(playerAccount);
|
|
1312
|
-
if (currentSystem.game !== game ||
|
|
1313
|
-
currentSystem.sequenceId !== stake.systemSeqId ||
|
|
1314
|
-
currentSystem.starbase === undefined ||
|
|
1315
|
-
!currentSystem.celestialBodyAddresses.includes(stake.body.address) ||
|
|
1316
|
-
(await deriveStarSystemAddress(game, currentSystem.systemId)) !== system) {
|
|
1317
|
-
fail(`Star System ${system} does not match the configured Game, canonical identity, Claim Stake generation, active nested Starbase, or Claim Stake Body relationship. Refresh the System and retry the rent top-up.`, system);
|
|
1318
|
-
}
|
|
1319
|
-
if (currentPlayer.playerProfile !== options.authorization.profile ||
|
|
1320
|
-
currentPlayer.character !== character ||
|
|
1321
|
-
currentPlayer.system !== system) {
|
|
1322
|
-
fail(`Starbase Player ${player} does not match the authorization Profile, canonical Character, and Claim Stake System. Refresh it and retry the rent top-up.`, player);
|
|
1323
|
-
}
|
|
1369
|
+
const { currentSystem, player, playerAccount, systemAccount } = await readStakeStarbase(ctx, stake, game, system, character, profile, action);
|
|
1324
1370
|
const description = `Top up Claim Stake ${stake.address} rent with ${String(options.amount)} raw rent units; rent arithmetic remains chain-authoritative.`;
|
|
1325
|
-
return
|
|
1371
|
+
return buildPlannerPlan({
|
|
1326
1372
|
kind: 'claim-stakes.top-up-rent',
|
|
1327
|
-
preconditions:
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1373
|
+
preconditions: [
|
|
1374
|
+
...(await Promise.all([
|
|
1375
|
+
accountStatePrecondition(stakeAccount, `Claim Stake ${stake.address} retains its ownership, rent balance, lifecycle state, Body, and System generation.`),
|
|
1376
|
+
planetPrecondition(bodyAccount, system),
|
|
1377
|
+
accountStatePrecondition(characterAccount, `The canonical Character remains assigned to Profile ${profile} with at least ${String(options.amount)} known raw ATLAS.`),
|
|
1378
|
+
systemPrecondition(systemAccount, currentSystem.name),
|
|
1379
|
+
playerPrecondition(playerAccount, player),
|
|
1380
|
+
])),
|
|
1381
|
+
...rent.guards,
|
|
1382
|
+
],
|
|
1334
1383
|
steps: [
|
|
1335
1384
|
{
|
|
1336
1385
|
describes: description,
|
|
@@ -1341,6 +1390,7 @@ export async function planTopUpClaimStakeRent(ctx, stake, input) {
|
|
|
1341
1390
|
character,
|
|
1342
1391
|
claimStakeInstance: stake.address,
|
|
1343
1392
|
game,
|
|
1393
|
+
...rent.accounts,
|
|
1344
1394
|
systemAndStarbasePlayerStarbasePlayer: player,
|
|
1345
1395
|
systemAndStarbasePlayerSystem: system,
|
|
1346
1396
|
}),
|
|
@@ -1372,10 +1422,10 @@ function requireTransferCapacity(destination, address, used, requested, total) {
|
|
|
1372
1422
|
fail(`${destination} has ${String(remaining)} raw capacity units remaining, but this transfer requires ${String(requested)}. Reduce the request or free capacity, refresh both snapshots, and retry.`, address);
|
|
1373
1423
|
}
|
|
1374
1424
|
}
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1425
|
+
/** Reads a Fleet's cargo-hold balance; Claim Stake transfers never touch the
|
|
1426
|
+
* fuel tank or ammo bank, so Fuel and Ammunition count only when in the hold. */
|
|
1427
|
+
function fleetCargoHoldAmount(fleet, cargoId) {
|
|
1428
|
+
return cargoAmount(fleet.cargoHold.amounts, cargoId);
|
|
1379
1429
|
}
|
|
1380
1430
|
function describeCargoRequests(direction, requests) {
|
|
1381
1431
|
return requests.map(({ amount, cargoId }) => `${direction} cargo id ${String(cargoId)} = ${String(amount)} raw ${amount === 1n ? 'unit' : 'units'}`);
|
|
@@ -1385,12 +1435,25 @@ function describeCargoRequests(direction, requests) {
|
|
|
1385
1435
|
* The planner validates the shared Profile/Game, idle Fleet with normalized
|
|
1386
1436
|
* crew, active Claim Stake, canonical Planet/System/Starbase Player graph,
|
|
1387
1437
|
* exact source balances, exact destination capacities, and an optional present
|
|
1388
|
-
* FleetCrewBinding.
|
|
1389
|
-
*
|
|
1438
|
+
* FleetCrewBinding. Both legs use the Fleet cargo hold only: loaded Fuel and
|
|
1439
|
+
* Ammunition arrive in the cargo hold and consume cargo capacity, and unloads
|
|
1440
|
+
* are sourced from the cargo hold, never from the fuel tank or ammo bank. The
|
|
1441
|
+
* chain remains authoritative for range, duration, permission bits, concurrent
|
|
1442
|
+
* state changes, and transfer arithmetic.
|
|
1443
|
+
*
|
|
1444
|
+
* The Fleet stores the requested load and unload lines while the transfer
|
|
1445
|
+
* runs. The program settles the Fleet and stake together: the stake's lamports
|
|
1446
|
+
* above its rent floor fund the Fleet first and the Profile vault, with the
|
|
1447
|
+
* signing key, funds the rest. The Plan bounds that debit with the same key and
|
|
1448
|
+
* balance checks as placement.
|
|
1390
1449
|
*
|
|
1391
1450
|
* Requires Game 2 and its existing canonical Claim Stake XP ledger.
|
|
1392
1451
|
* Missing XP state must be repaired outside this Plan; no accounts are created.
|
|
1393
1452
|
*
|
|
1453
|
+
* Requires Disabled rent: the Game's rent catalog and the Claim Stake's rent
|
|
1454
|
+
* settlement authority must not exist, and both stay guarded absent until
|
|
1455
|
+
* signing. The instruction carries no rent history.
|
|
1456
|
+
*
|
|
1394
1457
|
* @example
|
|
1395
1458
|
* ```ts
|
|
1396
1459
|
* declare const ctx: SageContext;
|
|
@@ -1408,118 +1471,56 @@ function describeCargoRequests(direction, requests) {
|
|
|
1408
1471
|
export async function planStartClaimStakeFleetTransfer(ctx, fleet, stake, input) {
|
|
1409
1472
|
const options = validateStartFleetTransferOptions(input);
|
|
1410
1473
|
const game = requireGameAddress(ctx);
|
|
1474
|
+
const { profile } = options.authorization;
|
|
1411
1475
|
if (fleet.game !== game || stake.game !== game) {
|
|
1412
1476
|
fail(`Fleet ${fleet.address} and Claim Stake ${stake.address} must both belong to configured Game ${game}. Refresh both snapshots through this context and retry.`, fleet.game !== game ? fleet.address : stake.address);
|
|
1413
1477
|
}
|
|
1414
|
-
if (fleet.ownerProfile.address !==
|
|
1415
|
-
fail(`Fleet ${fleet.name} belongs to Profile ${fleet.ownerProfile.address}, not authorization Profile ${
|
|
1478
|
+
if (fleet.ownerProfile.address !== profile) {
|
|
1479
|
+
fail(`Fleet ${fleet.name} belongs to Profile ${fleet.ownerProfile.address}, not authorization Profile ${profile}. Use the owning Profile, refresh the Fleet, and retry.`, fleet.address);
|
|
1416
1480
|
}
|
|
1417
1481
|
if (fleet.state.kind !== 'idle') {
|
|
1418
1482
|
fail(`Fleet ${fleet.name} is ${fleet.state.kind}, but starting a Claim Stake transfer requires an idle Fleet. Return it to idle state, refresh it, and retry.`, fleet.address);
|
|
1419
1483
|
}
|
|
1484
|
+
const crewFailure = `Fleet ${fleet.name} has no valid normalized crew and cannot start a Claim Stake transfer. Crew the Fleet, refresh it, and retry.`;
|
|
1420
1485
|
if (!Number.isSafeInteger(fleet.crewCount) || fleet.crewCount <= 0) {
|
|
1421
|
-
fail(
|
|
1486
|
+
fail(crewFailure, fleet.address);
|
|
1422
1487
|
}
|
|
1423
1488
|
if (stake.state.kind !== 'active') {
|
|
1424
1489
|
fail(`Claim Stake ${stake.address} is ${stake.state.kind}, but starting a Fleet transfer requires an active Claim Stake. Activate or restore it, refresh it, and retry.`, stake.address);
|
|
1425
1490
|
}
|
|
1426
|
-
const character = await
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
fleet.address,
|
|
1432
|
-
stake.address,
|
|
1433
|
-
stake.body.address,
|
|
1434
|
-
character,
|
|
1491
|
+
const character = await requireOwnedStake(stake, game, profile);
|
|
1492
|
+
const action = 'the Fleet transfer';
|
|
1493
|
+
const [{ bodyAccount, currentBody, currentStake, extraAccounts: [fleetCandidate, characterCandidate], stakeAccount, }, rent,] = await Promise.all([
|
|
1494
|
+
readOwnedStake(ctx, stake, action, [fleet.address, character]),
|
|
1495
|
+
requireDisabledStakeRent(ctx, game, stake.address, action),
|
|
1435
1496
|
]);
|
|
1436
|
-
const fleetAccount = requireAccount(fleetCandidate, fleet.address, `Fleet ${fleet.name} is missing. Refresh it and retry the
|
|
1437
|
-
const stakeAccount = requireAccount(stakeCandidate, stake.address, `Claim Stake ${stake.address} is missing. Refresh it and retry the Fleet transfer.`);
|
|
1438
|
-
const bodyAccount = requireAccount(bodyCandidate, stake.body.address, `Celestial Body ${stake.body.address} is missing. Refresh the Claim Stake Body and retry the Fleet transfer.`);
|
|
1439
|
-
const characterAccount = requireAccount(characterCandidate, character, `Canonical Character ${character} is missing. Refresh the Profile Character and retry the Claim Stake transfer.`);
|
|
1497
|
+
const fleetAccount = requireAccount(fleetCandidate, fleet.address, `Fleet ${fleet.name} is missing. Refresh it and retry the Fleet transfer.`);
|
|
1440
1498
|
const currentFleet = fleetAccountDefinition.decode(fleetAccount);
|
|
1441
|
-
const currentStake = claimStakeAccountDefinition.decode(stakeAccount);
|
|
1442
|
-
const currentBody = celestialBodyAccountDefinition.decode(bodyAccount);
|
|
1443
|
-
const currentCharacter = characterAccountDefinition.decode(characterAccount);
|
|
1444
1499
|
if (!Number.isSafeInteger(currentFleet.crewCount) ||
|
|
1445
1500
|
currentFleet.crewCount <= 0) {
|
|
1446
|
-
fail(
|
|
1501
|
+
fail(crewFailure, fleet.address);
|
|
1447
1502
|
}
|
|
1448
|
-
if (currentFleet
|
|
1449
|
-
currentFleet.ownerProfile !== options.authorization.profile ||
|
|
1450
|
-
currentFleet.name !== fleet.name ||
|
|
1503
|
+
if (!sameTransferFleet(currentFleet, fleet, game, profile) ||
|
|
1451
1504
|
currentFleet.state.kind !== 'idle' ||
|
|
1452
1505
|
currentFleet.crewCount !== fleet.crewCount ||
|
|
1453
|
-
(await deriveFleetAddress(currentFleet)) !== fleet.address
|
|
1454
|
-
currentFleet.ammoBank.cargoId !== fleet.ammo.id ||
|
|
1455
|
-
currentFleet.ammoBank.amount !== fleet.ammo.amount ||
|
|
1456
|
-
currentFleet.fuelTank.cargoId !== fleet.fuel.id ||
|
|
1457
|
-
currentFleet.fuelTank.amount !== fleet.fuel.amount ||
|
|
1458
|
-
currentFleet.cargoHold.storageCost !== fleet.cargoHold.storageCost ||
|
|
1459
|
-
!sameCargoAmounts(currentFleet.cargoHold.amounts, fleet.cargoHold.items) ||
|
|
1460
|
-
currentFleet.stats.cargo.ammoCapacity !== fleet.capacities.ammo.total ||
|
|
1461
|
-
currentFleet.stats.cargo.fuelCapacity !== fleet.capacities.fuel.total ||
|
|
1462
|
-
currentFleet.stats.cargo.cargoCapacity !== fleet.capacities.cargo.total) {
|
|
1506
|
+
(await deriveFleetAddress(currentFleet)) !== fleet.address) {
|
|
1463
1507
|
fail(`Fleet ${fleet.name} changed or no longer matches its loaded Game, owner, canonical address, name, idle state, normalized crew, cargo, or capacities. Refresh it and create a new Claim Stake transfer Plan.`, fleet.address);
|
|
1464
1508
|
}
|
|
1465
|
-
if (currentStake
|
|
1466
|
-
currentStake.ownerCharacter !== character ||
|
|
1467
|
-
currentStake.body !== stake.body.address ||
|
|
1468
|
-
currentStake.systemSeqId !== stake.systemSeqId ||
|
|
1469
|
-
currentStake.state.kind !== 'active' ||
|
|
1470
|
-
currentStake.production.cargoPod.storageCost !==
|
|
1471
|
-
stake.resources.capacity.usedRaw ||
|
|
1472
|
-
currentStake.production.resourceCapacityRaw !==
|
|
1473
|
-
stake.resources.capacity.totalRaw ||
|
|
1474
|
-
!sameCargoAmounts(currentStake.production.cargoPod.amounts, stake.resources.inventory.items.map(({ id, quantityRaw }) => ({
|
|
1475
|
-
amount: quantityRaw,
|
|
1476
|
-
id,
|
|
1477
|
-
})))) {
|
|
1509
|
+
if (!sameTransferStake(currentStake, stake, game, profile)) {
|
|
1478
1510
|
fail(`Claim Stake ${stake.address} changed or no longer matches its loaded Game, owner, Body, active state, resources, capacity, or System generation. Refresh it and create a new Fleet transfer Plan.`, stake.address);
|
|
1479
1511
|
}
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
(
|
|
1484
|
-
|
|
1485
|
-
fail(`Celestial Body ${stake.body.address} does not match the Claim Stake's configured Game, canonical Planet identity, or System generation. Refresh the Body and Claim Stake before retrying the Fleet transfer.`, stake.body.address);
|
|
1486
|
-
}
|
|
1487
|
-
if (currentCharacter.playerProfile !== options.authorization.profile ||
|
|
1488
|
-
currentCharacter.game !== game) {
|
|
1489
|
-
fail(`Character ${character} does not match authorization Profile ${options.authorization.profile} and configured Game ${game}. Refresh the Character and retry the Claim Stake transfer.`, character);
|
|
1490
|
-
}
|
|
1491
|
-
const system = currentBody.system;
|
|
1492
|
-
const player = await deriveStarbasePlayerAddress(system, character);
|
|
1493
|
-
const currencyCache = await deriveCurrencyCache(game).then(([address]) => address);
|
|
1494
|
-
const crewBinding = await deriveFleetCrewBindingAddress(fleet.address);
|
|
1495
|
-
const [systemCandidate, playerCandidate, currencyCandidate, crewCandidate] = await readContextRawAccounts(ctx, [
|
|
1496
|
-
system,
|
|
1497
|
-
player,
|
|
1498
|
-
currencyCache,
|
|
1499
|
-
crewBinding,
|
|
1512
|
+
const { system } = await requireStakePlanet(currentBody, stake, game, action);
|
|
1513
|
+
const { account: characterAccount } = requireProfileCharacter(characterCandidate, character, profile, game, action);
|
|
1514
|
+
const [currencyCache, crewBinding] = await Promise.all([
|
|
1515
|
+
claimStakeCurrencyCache(game),
|
|
1516
|
+
deriveFleetCrewBindingAddress(fleet.address),
|
|
1500
1517
|
]);
|
|
1501
|
-
const
|
|
1502
|
-
const
|
|
1503
|
-
const currencyAccount = requireAccount(currencyCandidate, currencyCache, `Canonical CurrencyCache ${currencyCache} is missing for configured Game ${game}. Refresh the Game currency configuration and retry the Fleet transfer.`);
|
|
1504
|
-
const currentSystem = starSystemAccountDefinition.decode(systemAccount);
|
|
1505
|
-
const currentPlayer = starbasePlayerAccountDefinition.decode(playerAccount);
|
|
1506
|
-
if (currentSystem.game !== game ||
|
|
1507
|
-
currentSystem.sequenceId !== stake.systemSeqId ||
|
|
1508
|
-
currentSystem.starbase === undefined ||
|
|
1509
|
-
!currentSystem.celestialBodyAddresses.includes(stake.body.address) ||
|
|
1510
|
-
(await deriveStarSystemAddress(game, currentSystem.systemId)) !== system) {
|
|
1511
|
-
fail(`Star System ${system} does not match the configured Game, canonical identity, Claim Stake generation, nested Starbase, or Claim Stake Body relationship. Refresh the System and retry the Fleet transfer.`, system);
|
|
1512
|
-
}
|
|
1513
|
-
if (currentPlayer.playerProfile !== options.authorization.profile ||
|
|
1514
|
-
currentPlayer.character !== character ||
|
|
1515
|
-
currentPlayer.system !== system) {
|
|
1516
|
-
fail(`Starbase Player ${player} does not match the authorization Profile, canonical Character, and Claim Stake System. Refresh it and retry the Fleet transfer.`, player);
|
|
1517
|
-
}
|
|
1518
|
-
await validateCurrencyCache(currencyAccount, game, 'Claim Stake Fleet transfer');
|
|
1518
|
+
const { currentSystem, extraAccounts: [currencyCandidate, crewCandidate], player, playerAccount, systemAccount, } = await readStakeStarbase(ctx, stake, game, system, character, profile, action, [currencyCache, crewBinding]);
|
|
1519
|
+
const currencyGuard = await requireCurrencyCache(currencyCandidate, currencyCache, game, action, 'Claim Stake Fleet transfer');
|
|
1519
1520
|
if (crewCandidate !== undefined) {
|
|
1520
1521
|
const currentCrewBinding = fleetCrewBindingAccountDefinition.decode(crewCandidate);
|
|
1521
1522
|
if (crewCandidate.address !== crewBinding ||
|
|
1522
|
-
!matchesFleetCrewBindingIdentity(currentCrewBinding, fleet.address,
|
|
1523
|
+
!matchesFleetCrewBindingIdentity(currentCrewBinding, fleet.address, profile)) {
|
|
1523
1524
|
fail(`FleetCrewBinding ${crewCandidate.address} does not match Fleet ${fleet.address}, its owner Profile, or its canonical PDA. Refresh the Fleet crew registration or remove the invalid binding before retrying.`, crewCandidate.address);
|
|
1524
1525
|
}
|
|
1525
1526
|
}
|
|
@@ -1531,21 +1532,10 @@ export async function planStartClaimStakeFleetTransfer(ctx, fleet, stake, input)
|
|
|
1531
1532
|
requireCargoBalance(`Claim Stake ${stake.address}`, stake.address, request.cargoId, cargoAmount(currentStake.production.cargoPod.amounts, request.cargoId), request.amount);
|
|
1532
1533
|
}
|
|
1533
1534
|
for (const request of options.unload) {
|
|
1534
|
-
requireCargoBalance(`Fleet ${fleet.name}`, fleet.address, request.cargoId,
|
|
1535
|
-
}
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
.reduce((total, { amount }) => total + amount, 0n);
|
|
1539
|
-
const loadFuel = options.load
|
|
1540
|
-
.filter(({ cargoId }) => cargoId === currentFleet.fuelTank.cargoId)
|
|
1541
|
-
.reduce((total, { amount }) => total + amount, 0n);
|
|
1542
|
-
const loadCargoStorage = options.load
|
|
1543
|
-
.filter(({ cargoId }) => cargoId !== currentFleet.ammoBank.cargoId &&
|
|
1544
|
-
cargoId !== currentFleet.fuelTank.cargoId)
|
|
1545
|
-
.reduce((total, { amount, cargoId }) => total +
|
|
1546
|
-
cargoStorageUnits(amount, definitions.get(cargoId).storageCost), 0n);
|
|
1547
|
-
requireTransferCapacity(`Fleet ${fleet.name} ammo destination`, fleet.address, currentFleet.ammoBank.amount, loadAmmo, currentFleet.stats.cargo.ammoCapacity);
|
|
1548
|
-
requireTransferCapacity(`Fleet ${fleet.name} fuel destination`, fleet.address, currentFleet.fuelTank.amount, loadFuel, currentFleet.stats.cargo.fuelCapacity);
|
|
1535
|
+
requireCargoBalance(`Fleet ${fleet.name}`, fleet.address, request.cargoId, fleetCargoHoldAmount(currentFleet, request.cargoId), request.amount);
|
|
1536
|
+
}
|
|
1537
|
+
// Every load, including Fuel and Ammunition, lands in the cargo hold.
|
|
1538
|
+
const loadCargoStorage = options.load.reduce((total, { amount, cargoId }) => total + cargoStorageUnits(amount, definitions.get(cargoId).storageCost), 0n);
|
|
1549
1539
|
requireTransferCapacity(`Fleet ${fleet.name} cargo destination`, fleet.address, currentFleet.cargoHold.storageCost, loadCargoStorage, currentFleet.stats.cargo.cargoCapacity);
|
|
1550
1540
|
const unloadStorage = options.unload.reduce((total, { amount, cargoId }) => total + cargoStorageUnits(amount, definitions.get(cargoId).storageCost), 0n);
|
|
1551
1541
|
requireTransferCapacity(`Claim Stake ${stake.address} resource destination`, stake.address, currentStake.production.cargoPod.storageCost, unloadStorage, currentStake.production.resourceCapacityRaw);
|
|
@@ -1553,53 +1543,52 @@ export async function planStartClaimStakeFleetTransfer(ctx, fleet, stake, input)
|
|
|
1553
1543
|
...describeCargoRequests('load', options.load),
|
|
1554
1544
|
...describeCargoRequests('unload', options.unload),
|
|
1555
1545
|
];
|
|
1556
|
-
const description = `Start fleet ${fleet.name}'s transfer to Claim Stake ${stake.address}: ${descriptions.join('; ')}. Range and transfer duration remain chain-authoritative.`;
|
|
1557
1546
|
const xp = await resolveClaimStakeXp(ctx, game, stake.address);
|
|
1558
|
-
|
|
1547
|
+
const instruction = adaptStartClaimStakeFleetTransferInstruction({
|
|
1548
|
+
...xp.accounts,
|
|
1549
|
+
authorization: options.authorization,
|
|
1550
|
+
celestialBody: stake.body.address,
|
|
1551
|
+
character,
|
|
1552
|
+
claimStakeInstance: stake.address,
|
|
1553
|
+
...(crewCandidate === undefined ? {} : { crewBinding }),
|
|
1554
|
+
currencyCache,
|
|
1555
|
+
fleet: fleet.address,
|
|
1556
|
+
game,
|
|
1557
|
+
...rent.accounts,
|
|
1558
|
+
systemAndStarbasePlayerStarbasePlayer: player,
|
|
1559
|
+
systemAndStarbasePlayerSystem: system,
|
|
1560
|
+
toLoad: options.load.map(({ amount, cargoId }) => [cargoId, amount]),
|
|
1561
|
+
toUnload: options.unload.map(({ amount, cargoId }) => [cargoId, amount]),
|
|
1562
|
+
});
|
|
1563
|
+
// The Fleet's transfer state is funded first from the stake's surplus over
|
|
1564
|
+
// its rent floor, then from the Profile vault.
|
|
1565
|
+
const storage = await planClaimStakeStorage(ctx, instruction, profile, [fleetAccount, stakeAccount], 'Claim Stake Fleet transfer start');
|
|
1566
|
+
const description = `Start fleet ${fleet.name}'s transfer to Claim Stake ${stake.address}: ${descriptions.join('; ')}. Loaded cargo, including Fuel and Ammunition, arrives in the Fleet cargo hold; unloads come from the cargo hold only. Range and transfer duration remain chain-authoritative. ${storage.disclosure}`;
|
|
1567
|
+
return buildPlannerPlan({
|
|
1559
1568
|
kind: 'claim-stakes.start-fleet-transfer',
|
|
1560
1569
|
preconditions: [
|
|
1561
1570
|
xp.guard,
|
|
1562
1571
|
...(await Promise.all([
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1572
|
+
accountStatePrecondition(fleetAccount, `Fleet ${fleet.name} retains its owner, name, idle state, normalized crew, cargo balances, and destination capacities.`),
|
|
1573
|
+
accountStatePrecondition(stakeAccount, `Claim Stake ${stake.address} retains its owner, active state, cargo balances, destination capacity, Body, and System generation.`),
|
|
1574
|
+
planetPrecondition(bodyAccount, system),
|
|
1575
|
+
characterPrecondition(characterAccount, profile),
|
|
1576
|
+
systemPrecondition(systemAccount, currentSystem.name),
|
|
1577
|
+
playerPrecondition(playerAccount, player),
|
|
1569
1578
|
...(crewCandidate === undefined
|
|
1570
1579
|
? []
|
|
1571
1580
|
: [
|
|
1572
|
-
|
|
1581
|
+
accountStatePrecondition(crewCandidate, `Fleet ${fleet.name}'s optional FleetCrewBinding remains assigned to the Fleet and owner Profile.`),
|
|
1573
1582
|
]),
|
|
1574
1583
|
])),
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
game,
|
|
1579
|
-
describes: 'The canonical CurrencyCache remains assigned to the configured Game; shared accounting may change.',
|
|
1580
|
-
},
|
|
1584
|
+
currencyGuard,
|
|
1585
|
+
...rent.guards,
|
|
1586
|
+
storage.guard,
|
|
1581
1587
|
],
|
|
1582
1588
|
steps: [
|
|
1583
1589
|
{
|
|
1584
1590
|
describes: description,
|
|
1585
|
-
instruction
|
|
1586
|
-
...xp.accounts,
|
|
1587
|
-
authorization: options.authorization,
|
|
1588
|
-
celestialBody: stake.body.address,
|
|
1589
|
-
character,
|
|
1590
|
-
claimStakeInstance: stake.address,
|
|
1591
|
-
...(crewCandidate === undefined ? {} : { crewBinding }),
|
|
1592
|
-
currencyCache,
|
|
1593
|
-
fleet: fleet.address,
|
|
1594
|
-
game,
|
|
1595
|
-
systemAndStarbasePlayerStarbasePlayer: player,
|
|
1596
|
-
systemAndStarbasePlayerSystem: system,
|
|
1597
|
-
toLoad: options.load.map(({ amount, cargoId }) => [cargoId, amount]),
|
|
1598
|
-
toUnload: options.unload.map(({ amount, cargoId }) => [
|
|
1599
|
-
cargoId,
|
|
1600
|
-
amount,
|
|
1601
|
-
]),
|
|
1602
|
-
}),
|
|
1591
|
+
instruction,
|
|
1603
1592
|
signers: [options.authorization.authority],
|
|
1604
1593
|
},
|
|
1605
1594
|
],
|
|
@@ -1650,10 +1639,7 @@ export async function planRecoverClaimStakeFleetTransfer(ctx, fleet, stake, inpu
|
|
|
1650
1639
|
if (options.atUnixSeconds < fleet.state.endAtUnixSeconds) {
|
|
1651
1640
|
fail(`Fleet ${fleet.name}'s Claim Stake transfer lock has not elapsed at Unix timestamp ${String(options.atUnixSeconds)}; it ends at ${String(fleet.state.endAtUnixSeconds)}. Wait until the lock elapses, provide a current timestamp, and retry recovery.`, fleet.address);
|
|
1652
1641
|
}
|
|
1653
|
-
const character = await
|
|
1654
|
-
if (stake.ownerCharacter.address !== character) {
|
|
1655
|
-
fail(`Claim Stake ${stake.address} does not belong to authorization Profile ${options.authorization.profile}'s canonical Character ${character}. Supply the owned current Claim Stake and retry recovery.`, stake.address);
|
|
1656
|
-
}
|
|
1642
|
+
const character = await requireOwnedStake(stake, game, options.authorization.profile);
|
|
1657
1643
|
const [fleetCandidate, stakeCandidate] = await readContextRawAccounts(ctx, [
|
|
1658
1644
|
fleet.address,
|
|
1659
1645
|
stake.address,
|
|
@@ -1662,40 +1648,17 @@ export async function planRecoverClaimStakeFleetTransfer(ctx, fleet, stake, inpu
|
|
|
1662
1648
|
const stakeAccount = requireAccount(stakeCandidate, stake.address, `Claim Stake ${stake.address} is missing. Refresh it and retry Fleet transfer recovery.`);
|
|
1663
1649
|
const currentFleet = fleetAccountDefinition.decode(fleetAccount);
|
|
1664
1650
|
const currentStake = claimStakeAccountDefinition.decode(stakeAccount);
|
|
1665
|
-
if (currentFleet
|
|
1666
|
-
currentFleet.ownerProfile !== options.authorization.profile ||
|
|
1667
|
-
currentFleet.name !== fleet.name ||
|
|
1651
|
+
if (!sameTransferFleet(currentFleet, fleet, game, options.authorization.profile) ||
|
|
1668
1652
|
currentFleet.state.kind !== 'claimStakeTransfer' ||
|
|
1669
1653
|
currentFleet.state.claimStake !== stake.address ||
|
|
1670
1654
|
currentFleet.state.planet !== stake.body.address ||
|
|
1671
1655
|
currentFleet.state.endAtUnixSeconds !== fleet.state.endAtUnixSeconds ||
|
|
1672
1656
|
!sameCargoAmounts(currentFleet.state.load, fleet.state.load) ||
|
|
1673
1657
|
!sameCargoAmounts(currentFleet.state.unload, fleet.state.unload) ||
|
|
1674
|
-
(await deriveFleetAddress(currentFleet)) !== fleet.address
|
|
1675
|
-
currentFleet.ammoBank.cargoId !== fleet.ammo.id ||
|
|
1676
|
-
currentFleet.ammoBank.amount !== fleet.ammo.amount ||
|
|
1677
|
-
currentFleet.fuelTank.cargoId !== fleet.fuel.id ||
|
|
1678
|
-
currentFleet.fuelTank.amount !== fleet.fuel.amount ||
|
|
1679
|
-
currentFleet.cargoHold.storageCost !== fleet.cargoHold.storageCost ||
|
|
1680
|
-
!sameCargoAmounts(currentFleet.cargoHold.amounts, fleet.cargoHold.items) ||
|
|
1681
|
-
currentFleet.stats.cargo.ammoCapacity !== fleet.capacities.ammo.total ||
|
|
1682
|
-
currentFleet.stats.cargo.fuelCapacity !== fleet.capacities.fuel.total ||
|
|
1683
|
-
currentFleet.stats.cargo.cargoCapacity !== fleet.capacities.cargo.total) {
|
|
1658
|
+
(await deriveFleetAddress(currentFleet)) !== fleet.address) {
|
|
1684
1659
|
fail(`Fleet ${fleet.name} changed or no longer matches its loaded owner, Game, canonical address, Claim Stake transfer snapshot, cargo, or capacities. Refresh it and retry recovery.`, fleet.address);
|
|
1685
1660
|
}
|
|
1686
|
-
if (currentStake
|
|
1687
|
-
currentStake.ownerCharacter !== character ||
|
|
1688
|
-
currentStake.body !== stake.body.address ||
|
|
1689
|
-
currentStake.systemSeqId !== stake.systemSeqId ||
|
|
1690
|
-
currentStake.state.kind !== 'active' ||
|
|
1691
|
-
currentStake.production.cargoPod.storageCost !==
|
|
1692
|
-
stake.resources.capacity.usedRaw ||
|
|
1693
|
-
currentStake.production.resourceCapacityRaw !==
|
|
1694
|
-
stake.resources.capacity.totalRaw ||
|
|
1695
|
-
!sameCargoAmounts(currentStake.production.cargoPod.amounts, stake.resources.inventory.items.map(({ id, quantityRaw }) => ({
|
|
1696
|
-
amount: quantityRaw,
|
|
1697
|
-
id,
|
|
1698
|
-
})))) {
|
|
1661
|
+
if (!sameTransferStake(currentStake, stake, game, options.authorization.profile)) {
|
|
1699
1662
|
fail(`Claim Stake ${stake.address} changed or no longer matches its loaded owner, Game, Body, active state, resources, capacity, or System generation. Refresh it and retry Fleet transfer recovery.`, stake.address);
|
|
1700
1663
|
}
|
|
1701
1664
|
let reason;
|
|
@@ -1708,7 +1671,7 @@ export async function planRecoverClaimStakeFleetTransfer(ctx, fleet, stake, inpu
|
|
|
1708
1671
|
}
|
|
1709
1672
|
if (reason === undefined) {
|
|
1710
1673
|
for (const request of currentFleet.state.unload) {
|
|
1711
|
-
const available =
|
|
1674
|
+
const available = fleetCargoHoldAmount(currentFleet, request.cargoId);
|
|
1712
1675
|
if (available < request.amount) {
|
|
1713
1676
|
reason = `Fleet source shortfall for cargo id ${String(request.cargoId)}`;
|
|
1714
1677
|
break;
|
|
@@ -1734,24 +1697,12 @@ export async function planRecoverClaimStakeFleetTransfer(ctx, fleet, stake, inpu
|
|
|
1734
1697
|
}
|
|
1735
1698
|
}
|
|
1736
1699
|
if (reason === undefined) {
|
|
1737
|
-
|
|
1738
|
-
const
|
|
1739
|
-
const loadCargoStorage = currentFleet.state.load
|
|
1740
|
-
.filter(({ cargoId }) => cargoId !== currentFleet.ammoBank.cargoId &&
|
|
1741
|
-
cargoId !== currentFleet.fuelTank.cargoId)
|
|
1742
|
-
.reduce((total, { amount, cargoId }) => total +
|
|
1700
|
+
// Every queued load, including Fuel and Ammunition, targets the cargo hold.
|
|
1701
|
+
const loadCargoStorage = currentFleet.state.load.reduce((total, { amount, cargoId }) => total +
|
|
1743
1702
|
cargoStorageUnits(amount, queuedDefinitions.get(cargoId).storageCost), 0n);
|
|
1744
1703
|
const unloadStorage = currentFleet.state.unload.reduce((total, { amount, cargoId }) => total +
|
|
1745
1704
|
cargoStorageUnits(amount, queuedDefinitions.get(cargoId).storageCost), 0n);
|
|
1746
|
-
if (currentFleet.
|
|
1747
|
-
currentFleet.stats.cargo.ammoCapacity) {
|
|
1748
|
-
reason = 'Fleet ammo destination overflow';
|
|
1749
|
-
}
|
|
1750
|
-
else if (currentFleet.fuelTank.amount + loadFuel >
|
|
1751
|
-
currentFleet.stats.cargo.fuelCapacity) {
|
|
1752
|
-
reason = 'Fleet fuel destination overflow';
|
|
1753
|
-
}
|
|
1754
|
-
else if (currentFleet.cargoHold.storageCost + loadCargoStorage >
|
|
1705
|
+
if (currentFleet.cargoHold.storageCost + loadCargoStorage >
|
|
1755
1706
|
currentFleet.stats.cargo.cargoCapacity) {
|
|
1756
1707
|
reason = 'Fleet cargo destination overflow';
|
|
1757
1708
|
}
|
|
@@ -1764,15 +1715,15 @@ export async function planRecoverClaimStakeFleetTransfer(ctx, fleet, stake, inpu
|
|
|
1764
1715
|
fail(`Fleet ${fleet.name}'s Claim Stake transfer is currently executable. Use the permissionless normal exit path; recovery is only for a locally proven non-executable transfer.`, fleet.address);
|
|
1765
1716
|
}
|
|
1766
1717
|
const description = `Recover fleet ${fleet.name} from its stuck Claim Stake transfer (${reason}); no cargo moves and the Fleet returns to idle.`;
|
|
1767
|
-
return
|
|
1718
|
+
return buildPlannerPlan({
|
|
1768
1719
|
kind: 'claim-stakes.recover-fleet-transfer',
|
|
1769
1720
|
preconditions: await Promise.all([
|
|
1770
|
-
|
|
1771
|
-
|
|
1721
|
+
accountStatePrecondition(fleetAccount, `Fleet ${fleet.name} retains its owner and exact elapsed, non-executable Claim Stake transfer snapshot.`),
|
|
1722
|
+
accountStatePrecondition(stakeAccount, `Claim Stake ${stake.address} remains active with the current owner, cargo, and capacity used to prove non-executability.`),
|
|
1772
1723
|
...(gameAccount === undefined
|
|
1773
1724
|
? []
|
|
1774
1725
|
: [
|
|
1775
|
-
|
|
1726
|
+
accountStatePrecondition(gameAccount, `Game ${game} retains the cargo definitions used to prove the transfer is non-executable.`),
|
|
1776
1727
|
]),
|
|
1777
1728
|
]),
|
|
1778
1729
|
steps: [
|