Skip to content

Crafting Process Workflow

Crafting turns input cargo into output cargo through a Recipe, optional crafting hab context, crew allocation, and a new CraftingProcess account.

Use this as the canonical review pattern for production workflows: read recipe and local player state, build the process instruction, summarize cost and writable accounts, simulate, then show the expected cargo/crew/process diffs.

Keep the economy context visible: crafted outputs can feed starbase upgrades, local markets, and Infrastructure Contracts, which are one of the loops that turn active production and SDU demand into ATLAS payouts.

What Start Crafting Touches

ts
import { getStartCraftingProcessInstruction } from '@staratlas/dev-sage';

Instruction data:

FieldMeaning
keyIndexPlayer Profile key index authorizing the action.
quantityNumber of recipe runs or output units, depending on the recipe semantics.
numCrewCrew allocated to the process.

Core accounts:

AccountRole in the workflow
profileValidationSignerWallet/profile signer.
profileValidationProfilePlayer Profile account.
characterSAGE Character for this profile/game.
gameRoot SAGE game account.
systemStar system containing the relevant starbase.
starbasePlayerPlayer state at that starbase.
recipeRecipe definition being started.
craftingProcessNew generated account signer for the crafting job.
craftingHabInstanceOptional player-owned hab used by the process.
currencyCacheRequired when a crafting hab instance is provided.

1. Read the state

Read the recipe and local player state before building:

ts
import {
	RecipeStatus,
	fetchMaybeRecipe,
	fetchMaybeStarbasePlayer
} from '@staratlas/dev-sage';

const [recipe, starbasePlayer] = await Promise.all([
	fetchMaybeRecipe(rpc, recipeAddress, { commitment: 'confirmed' }),
	fetchMaybeStarbasePlayer(rpc, starbasePlayerAddress, {
		commitment: 'confirmed'
	})
]);

if (!recipe.exists) throw new Error('Recipe not found');
if (!starbasePlayer.exists) throw new Error('Starbase player not found');
if (RecipeStatus[recipe.data.status] !== 'Active') {
	throw new Error(`Recipe is not active: ${RecipeStatus[recipe.data.status]}`);
}

console.log({
	recipe: recipe.data.name,
	duration: recipe.data.craftingDuration,
	inputs: recipe.data.inputs.size,
	outputs: recipe.data.outputs.size
});

The UI should also show whether the player's local cargo, crew, and ATLAS context satisfy the recipe.

2. Build the instruction

ts
import { generateKeyPairSigner } from '@solana/kit';
import { getStartCraftingProcessInstruction } from '@staratlas/dev-sage';

const craftingProcess = await generateKeyPairSigner();

const instruction = getStartCraftingProcessInstruction({
	profileValidationSigner: walletSigner,
	profileValidationProfile: profileAddress,
	character: characterAddress,
	game: gameAddress,
	system: systemAddress,
	starbasePlayer: starbasePlayerAddress,
	recipe: recipeAddress,
	craftingProcess,
	quantity: 1n,
	numCrew: 10,
	keyIndex: 0
});

Use getStartCraftingProcessInstructionAsync if you want the generated client to derive optional accounts it knows how to derive. Use the sync builder when review screens already have every address.

3. Review before signing

Show these items before a wallet signs:

  • Recipe name, duration, inputs, outputs, and status.
  • Quantity and crew allocation.
  • Player Profile and keyIndex.
  • Starbase/system context.
  • New crafting process address.
  • Optional crafting hab and currency cache.
  • Expected cargo, crew, ATLAS, fee, rent, and cooldown effects.

4. Simulate the full transaction

Simulation should catch missing optional accounts, stale recipe/starbase state, insufficient cargo, insufficient crew, and missing generated-account signatures before the user sees a wallet prompt.

ts
const simulation = await rpc
	.simulateTransaction(encodedTransactionBase64, {
		commitment: 'confirmed',
		encoding: 'base64',
		replaceRecentBlockhash: true,
		sigVerify: false
	})
	.send();

console.log({
	err: simulation.value.err,
	unitsConsumed: simulation.value.unitsConsumed,
	logs: simulation.value.logs
});

Live PTR shape

A recent PTR startCraftingProcess transaction created a signer/writable crafting-process account and wrote the profile, character, starbase-player, recipe, and new process accounts.

Decoded instruction data:

ts
{
	keyIndex: 0,
	quantity: '350000',
	numCrew: 350
}

Named account roles in the sampled transaction:

txt
profileValidationSigner
profileValidationProfile
profileValidationProgram
character
game
system
starbasePlayer
recipe
craftingProcess
systemProgram

Two optional account positions were filled with the SAGE program address sentinel. When decoding explorer transactions, treat that sentinel as "optional account absent", not as an extra SAGE account to fetch.

5. Diff targets

AccountExpected change
CraftingProcessNew account should exist and decode as CraftingProcess.
StarbasePlayerCargo, crew, or local production state may change.
CharacterXP, counters, or crafting-related state may change.
CraftingHabInstanceUsage, modifiers, or rent state may change when provided.
CurrencyConfigCacheUsually read/config context; include it when hab flows require it.

Use Transaction Review and Account Diffs for the generic simulation and diff pattern.