Crafting
Crafting has three moving parts, and separating them makes the API obvious:
- a recipe is the rule: these inputs become that output, taking this long;
- a hab is the place: a plot at a starbase where crafting can happen;
- a process is the run: one recipe executing in one hab, right now.
Recipes
Section titled “Recipes”Recipes are static definitions from the Game account, so they are the same for everyone and cheap to read:
const recipe = await sage.recipes.byId(recipeId);Habs and processes
Section titled “Habs and processes”Both hang off whoever owns them, which is usually a character or their state at a starbase:
const habs = await sage.craftingHabs.byCharacter(characterAddress);const running = await sage.craftingProcesses.byCharacter(characterAddress);A process is a lifecycle, not a boolean. It has a start, a duration derived from its recipe, and an end — which is why crafting occupies a hab for a period rather than completing instantly.
Why processes need discovery
Section titled “Why processes need discovery”Crafting processes have no derivable address. You cannot compute where one lives from the character or the recipe; it is assigned when the process is created.
That is why the reads above are byCharacter, byProfile, and
byStarbasePlayer rather than a single get(address) — each encodes a
verified way of finding processes, rather than pretending you can calculate
where they are. See the bindings escape hatch for the
broader pattern of accounts without derivable addresses.
Gotchas
Section titled “Gotchas”A finished process still exists. Completion is a state, not a deletion. Read the lifecycle rather than assuming presence means “in progress”.
Hab capacity is finite. A hab holds a limited number of concurrent processes, so “can this character craft” is not answerable from the recipe alone.
Recipe inputs are raw amounts. Like all quantities, they are bigint and
need the cargo definitions to render as names and decimals.