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