Identity
Almost every read starts by working out who you are asking about. That chain has three links, and one of them is harder than it looks.
Wallet ──▶ Profile ──▶ CharacterA wallet is a Solana account someone controls. A profileA player's on-chain identity across Star Atlas. Created by the player, so it cannot be derived from a wallet address. is their on-chain identity across Star Atlas. A characterA profile's presence inside SAGE. Owns fleets and accrues progress; one per profile. is that profile’s presence inside SAGEThe part of Star Atlas where fleets fly, mine, craft, and trade. specifically — the thing that owns fleets and accrues progress.
Getting a character
Section titled “Getting a character”If you already have a profile address, one call gets you the character:
const character = await sage.characters.forProfile(profileAddress);That is the normal starting point, and most guides here begin from it.
The part that surprises people
Section titled “The part that surprises people”You cannot calculate a profile address from a wallet address.
Many Solana accounts have a derivable addressAn address derived deterministically from known inputs, so it can be computed rather than searched for. computed from known inputs, so you can work them out offline. Profiles do not: a profile is created by its owner, and its address is assigned at creation. Nothing about the wallet predicts it.
So going wallet → profile is a search, not a calculation, and the SDK makes you choose how to search rather than guessing:
const sage = createSageClient({ cluster: 'zink-ptr', rpc, discovery: { walletProfiles },});
const wallet = sage.wallets.get(walletAddress);const profiles = await wallet.profiles.all({ strategy: 'provider' });walletProfiles is a provider you supply — a lookup table you maintain, an
indexer, or anything else that can answer “which profiles belong to this
wallet”. Without one, the provider strategy has no way to answer and says so.
If you already know the addresses, skip the provider entirely and pass them:
const profiles = await wallet.profiles.all({ strategy: 'known-addresses', addresses: [profileAddress],});What a character gives you
Section titled “What a character gives you”The character is the hub. Almost every gameplay read hangs off it:
const fleets = await character.fleets.all();const stakes = await character.claimStakes.all();const bases = await character.starbases.all();Each of those is a separate network read, which is why each is a method rather than a property. See how the SDK thinks for why that distinction is consistent across the whole API.
Gotchas
Section titled “Gotchas”A profile with no character is possible. Someone can hold a Star Atlas
profile without having entered SAGE. forProfile will tell you rather than
inventing an empty character.
A wallet can hold more than one profile. wallet.profiles.all() returns an
array for that reason. Do not assume the first is the one you want.
Progression is a separate read. XP and pilot level are not on the character snapshot; they are joined against the Game account’s XP definitions and fetched on their own.