Skip to Content
API ReferenceindividualityOverview

@parity/product-sdk-individuality

npm install @parity/product-sdk-individuality

Exports

Classes

NameSummary
AsPersonErrorBuilding an origin-modifying transaction extension — AsPerson or its
IndividualityDecodeErrorA raw storage value did not match the shape the descriptor promised — an
ProductIndividualityErrorBase class for errors raised by @parity/product-sdk-individuality.

Functions

NameSummary
airdropPhase()—
airdropVrfDomain()domain_for_event: label bytes then the event id. Exported as the one part
airdropVrfTranscript()The transcript for one draw.
buildLiteAliasBindTx()Build the unsigned V5 general extrinsic that binds a lite person’s alias to
canClaimFullUsername()Whether this account can still claim a bare name.
claimPrizeTx()Build the Game.claim_airdrop call, unsigned. Pays::No on success, so only a
confirmClaim()Did a submitted claim take effect? Re-reads the row rather than watching, so it
contextSuffixBytes()Expand a ContextSuffix to the 32 bytes the context hash consumes,
creditHash()The credit one attestation awards, as lowercase hex:
decodeAbsenceGracePolicy()Decode the grace policy from its strict 0x + four-hex-digit serialization.
decodeConsumerInfo()undefined in means the account has no record, which is an answer, not a failure.
deriveClaimEligibility()Decide whether one prize can be claimed. Never throws.
derivePersonhoodState()Derive a person’s membership standing from one pinned snapshot.
displayUsername()The host computes this same rule over the same record at session-pairing time
fromPapi()—
gameAirdropEventId()Mirrors Game::airdrop_event_id, a plain impl method, so only its base reaches
gameAirdropEventIds()Every draw id of one game, in airdrop-index order. airdropsScheduled only
gameTimeline()A line-for-line mirror of the runtime’s GameTimes trait, including
groupSeats()All maxGroupSize seats of the group the player at playerIndex sits in,
litePeopleRing()The people-lite ring on the chain with genesis genesisHash.
lookupUsername()Read the usernames registered for an account, from Resources.Consumers.
mintAccountAirdropVrfs()—
missesInWindow()Misses the window currently holds: the games inside it that were absences.
numberOfGroups()The groups a roster of playerCount splits into, 0 when there is no roster.
offboardTx()Build Game.offboard, unsigned.
parsePeopleAirdropsEventId()The draw index inside a PeopleAirdrops event id, or null if it is not one.
peopleAirdropsEventId()Derive a PeopleAirdrops draw’s event id, mirroring
peopleRing()The people ring on the chain with genesis genesisHash. The host resolves
personhoodContext()The personhood product’s context for name on the network issuing .<tld>
productContext()The 32-byte proof context of { productId, suffix }, mirroring
readAirdropDraw()A draw that is not in storage is not a failure, it is phase: "Gone" — the
readClaimEligibility()Check whether one prize can be claimed, from one pinned finalized block. The six
readCommunicationIdentifier()The key an account is reached on during the game, at one pinned finalized block.
readCreditCandidates()Every credit the attestee could earn in the running game, one per co-player per
readCurrentGame()No game running is not a failure, it is BetweenGames — the chain’s normal
readDrawRegistration()Whether an identity entered a draw, which readAirdropDraw cannot say: an
readGameAirdropEventIds()Every event id of one game’s draws, with the base read from the chain rather
readGameSignUpRequirement()What this player may do about the running game, at one pinned block. Between
readGroupMembers()The members of one group in one round, at one pinned finalized block.
readLiteSignUpRequirement()What this account may do about the free lite sign-up, at one pinned block:
readPersonhoodState()Read a person’s personhood state from one pinned finalized block.
readPlayerIndices()The index a player holds in each round, at one pinned finalized block.
readPrizeStatus()Not an authorization oracle. The chain re-checks eligibility on claim, and a
readRegistrationEligibility()Read Score.Participants and Score.PersonhoodThreshold at one pinned block
readScoreContext()Read Score.score_context and check it is the product derivation of
readSignUpFunds()The deposit, the free balance and the fee of a sign-up.
readyToRegister()Whether Score.register with a key would pass its guards now: the
registerMessage()"pop register using" ++ account — the 50 bytes the full member key signs.
registerPersonhoodTx()Build Score.register(Some((member_key, proof_of_ownership))), unsigned.
reportTx()Build Game.report, unsigned.
ringCollectionId()A personhood ring’s collection identifier: the human-readable name,
runScoreContextRead()Throws; readScoreContext owns the Result boundary. Exported so a
signUpWithAccountTx()Build Game.sign_up_with_account, unsigned. Pays::No on success, though a new
signUpWithLiteInviteTx()Build Game.sign_up_with_account_lite_invite, unsigned. Pays::No, no
statusTag()Validate a raw Status variant name. Exported so a read that only needs the
toAirdropEvent()—
toCurrentGame()Map the raw running game, selecting the deadline that belongs to its phase.
toGamePhaseDurations()Map the raw phase durations, from either source.
toGameSchedulePreview()Map one upcoming schedule, deriving its timeline from the given durations.
toPersonhoodParticipant()Map a raw PAPI participant to the domain shape the derivation consumes.
toRawRegistrationEntry()A domain registrant as the Winners key wants it.
usernameBase()The letters part of a lite username, which is what a claim would offer.
watchCurrentGame()Game.Game, which is null between games.
watchParticipant()Score.Participants, which is null for a player who has never been scored.
watchPlayer()Game.Players, which is null for a player who never signed up or was archived.
withAsPerson()Wrap a signer so its transactions run under a person origin.
withLiteAlias()Wrap a signer so its transactions run under a lite-person origin.
withScoreParticipant()Wrap a signer so its transactions run as the score participant, fee-free.

Interfaces

NameSummary
AbsenceGracePolicyThe absence-grace policy currently in force, decoded from
AccountVrfSignatureOne AirdropVrfs::Account entry, shaped as the host’s signVrf returns it.
AirdropAssetIdThe prize asset, as an XCM location. Opaque on purpose — this package does not
AirdropChainStructural, so a test double satisfies it. See IndividualityChain in read.ts
AirdropDrawOne draw at one pinned block. event is null exactly when phase is "Gone",
AirdropEventThe counters are null where the Status variant does not carry them — **not
AirdropPrizeThe prize a draw pays out, from AirdropPrize on chain.
AirdropVrfSignerAn sr25519 VRF over one draw’s transcript.
BuildLiteAliasBindTxOptionsOptions for buildLiteAliasBindTx.
CapturedGameA game identified by the caller rather than read from the chain.
ClaimChainThe Game.claim_airdrop call, plus the Score.Participants read the check
ClaimEligibilityWhether a specific prize can be claimed, and what stops it if not.
ClaimEligibilityResultThe result of checking a claim against the chain.
ClaimInputsEverything the predicate needs, all from one pinned block.
ClaimTargetEverything a claim addresses.
ClaimWindowWhen a claim stops being possible. Two deadlines apply and only one is a clock —
CommunicationIdentifierResult—
ConfirmClaimOptionsOptions for confirmClaim.
ConsumersChainThe chain surface this read needs, structural rather than a pinned descriptor.
ConsumerUsernamesThe usernames registered for one account, decoded.
CreditCandidateOne credit the attestee could earn this game: a co-player of one round, and the hash.
CreditCandidatesResult—
CurrentGameThe game that is running now.
CurrentGameWatchChainStructural, so a test double satisfies it.
DrawRegistrationOne draw’s registration for one identity.
EncodedCallSourceThe one call-encoding method the builder needs; PAPI transactions have it.
FeeEstimableA built transaction whose fee can be estimated, as every PAPI transaction can.
FinalizedBlockSourceThe one raw-client method the pinned reads use. Structural, so PolkadotClient fits.
FinalizedSnapshotThe finalized block every read in a result was pinned to.
GameChainStructural, so a test double satisfies it. Separate from AirdropChain because a
GamePhaseDurationsThe phase durations in force, from Game.StoredPhaseDurations when governance
GamePlayersChainThe registration entry, needed only when ReadCurrentGameOptions.players
GameScheduledAirdropOne prize draw a schedule will set up, with its timing relative to play time.
GameSchedulePreviewA game not created yet. The chain keeps Game.GameSchedules chronological —
GameSignUpRequirementWhat the chain will accept from this player, at one pinned block. Index and draw
GameTimelineA game’s phase boundaries, Unix seconds. Mirrors the runtime’s GameTimes
GroupMemberOne occupied seat, resolved to the player the chain keys it by.
GroupMembersResult—
GroupSeatOne position of a group, with whether a player was shuffled into it.
IndividualityChainThe chain surface this read needs — deliberately structural, not a pinned
LegacySuffixChainThe network suffix before #20. Previewnet only, and gone on its next upgrade.
LiteAliasBindChainWhat building the bind leg needs from a chain: the call codec, the current
LiteAliasBindTxWhat buildLiteAliasBindTx returns.
LiteSignUpChainThe lite sign-up call, plus the reads that decide whether it can dispatch.
LiteSignUpRequirementGameSignUpRequirement with the wider blocker union: what the chain
LookupUsernameOptionsOptions for lookupUsername.
MintAccountAirdropVrfsOptionsOptions for mintAccountAirdropVrfs.
NetworkSuffixChainThe network suffix since individuality-community #20. Root can move it between
PapiIndividualityChainWhat fromPapi returns, with the typed API preserved.
ParticipantWatchChain—
PersonhoodInputsEverything PersonhoodState is derived from, resolved for one account at
PersonhoodMetricsThe numbers behind a resolved state, carried alongside it.
PersonhoodParticipantA participant’s game record, as read from Score.Participants and decoded.
PlayerIndicesResult—
PlayerRecordA player record in Game.Players, present from the first sign-up until archival.
PlayerWatchChain—
RawAccountAliasAccountToAlias, narrowed to the contextual alias the read keys on.
RawActiveEventThe raw Airdrop.Events value, narrowed to what the domain reads.
RawAirdropEventInfoThe raw EventInfo. Every timestamp is a u64 of Unix seconds.
RawAirdropPrizeThe raw AirdropPrize, narrowed to the fields the domain carries.
RawAirdropStatusThe raw Status enum. The payload is loose on purpose: enumerating eight
RawConsumerInfoThe raw Resources.Consumers value, narrowed to the fields we read.
RawGameAirdropOne raw GameAirdrop from a schedule.
RawGameInfoThe raw Game.Game value, narrowed to the fields the domain carries.
RawGameScheduleOne raw GameSchedule from the Game.GameSchedules list.
RawGameStateThe raw GameState enum. Only the player count is read from its payload.
RawLiteAliasBindingPeopleLite.AccountToAlias, the alias binding the signed leg dispatches on.
RawLiteRingMembershipOne Members.Members entry, narrowed to the discriminant. Only Included
RawParticipantThe raw Score.Participants value, narrowed to the fields the domain reads.
RawPhaseDurationsThe raw PhaseDurationValues, from storage or from the runtime constant.
RawRecognitionThe raw recognition enum as PAPI decodes it:
RawStreakThe raw streak enum as PAPI decodes it: Enum<{ Attended: u32; Absent: u32 }>.
ReadAirdropDrawOptionsOptions for readAirdropDraw.
ReadClaimEligibilityOptionsOptions for readClaimEligibility.
ReadCommunicationIdentifierOptionsOptions for readCommunicationIdentifier.
ReadCreditCandidatesOptionsOptions for readCreditCandidates.
ReadCurrentGameOptionsOptions for readCurrentGame.
ReadGameAirdropEventIdsOptionsOptions for readGameAirdropEventIds.
ReadGameSignUpRequirementOptionsOptions for readGameSignUpRequirement.
ReadGroupMembersOptionsOptions for readGroupMembers.
ReadLiteSignUpRequirementOptionsOptions for readLiteSignUpRequirement.
ReadPlayerIndicesOptionsOptions for readPlayerIndices.
ReadPrizeStatusOptionsOptions for readPrizeStatus.
ReadRegistrationEligibilityOptionsOptions for readRegistrationEligibility.
ReadScoreContextOptionsOptions for readScoreContext.
ReadSignUpFundsOptionsOptions for readSignUpFunds.
RegisterChainThe Score.register call, typed structurally so the package needs no
RegisterPersonhoodOptionsOptions for registerPersonhoodTx.
RegistrationEligibilityA participant’s standing against the registration guards, at one pinned
RegistrationEligibilityChainThe two reads readRegistrationEligibility folds. Matched by hand
ReportChainStructural, so a test double satisfies it. Matched by hand against the paseo
ReportOptionsOptions for reportTx.
RingLocationWhere a ring lives: a chain, and a junction path addressing the ring on it.
RingVRFProofA ring VRF proof and the values the chain needs to verify it.
RosterChainStructural, so a test double satisfies it. Matched by hand against the paseo
ScoreContextChainThe published context every score proof must be minted in.
SignUpChainThe sign-up call, plus the reads that decide what it may carry. Composed with
SignUpFundsThe parts of what a sign-up costs, in the smallest unit of the native token.
SignUpWithAccountOptionsOptions for signUpWithAccountTx.
SignUpWithLiteInviteOptionsOptions for signUpWithLiteInviteTx.
VrfTranscript—
VrfTranscriptItemMerlin append_message(label, value), as the host’s signVrf takes it.
WatchAtOptions every watch takes: only the best block, so a change shows before finality.
WatchedBlockThe block a watched value was read at, which is a best block, not a finalized one.
WatchedValueA PAPI watchValue observable, narrowed to the one method a watch calls.
WatchPlayerOptionsOptions for watchPlayer and watchParticipant.

Type Aliases

NameSummary
AirdropOutcomeWhether a registrant won. Unchecked exists so “we did not ask” cannot be
AirdropPhaseThe phase a product renders. Gone is not a chain status but the row’s absence
AirdropRegistrantWhich identity entered a draw. Not the player’s choice on the game path: the
AirdropStatusTagThe chain’s own Status, kept alongside AirdropPhase because the
AirdropVrfVariantWhich variant the chain demands of this player. Read it, never choose it.
AsPersonInfoWhich person origin the transaction should run under.
ClaimBlockerWhy a prize cannot be claimed. Several can hold at once, so
ClaimOutcomeWhether a submitted claim reached the chain, re-read rather than watched. A
ContextSuffixThe RFC-0024 context-suffix selector: a plain index, or 32 raw bytes. The same
CreateRingVRFProofProduce a ring VRF proof over message.
CreditCandidatesChainRosterChain plus the game, which readCreditCandidates reads at the same block.
CurrentGameResult—
GamePhaseThe phase a game is in, named as the chain’s GameState variant. Their payloads
LiteAliasInfoWhich lite-person origin the transaction should run under.
LiteSignUpBlockerWhy the free lite sign-up (Game.sign_up_with_account_lite_invite) cannot go
PersonhoodContextName—
PersonhoodResultThe outcome of a personhood read.
PersonhoodStateA person’s membership standing, derived from one pinned snapshot.
PlayerKey—
PlayerRegistrationWhether the players named in ReadCurrentGameOptions.players are in the
PrizeStatusThe outcome of a prize-status read.
PrizeStatusChainBoth halves of the chain surface, since this read spans Game and Airdrop.
RawRegistrationEntryThe raw RegistrationEntry enum, the key Winners is addressed by.
RawReportVoteA vote as the pallet Report enum takes it.
ReadPersonhoodStateOptionsWhat to read, and how: a username or an account, and never both.
ReportVoteThe judgement of one co-player, who either attended as a person or did not.
ScoreContextThe chain’s score context, and whether a host can mint proofs in it.
SignUpBlockerWhy a sign-up, or the draw entry inside it, cannot go ahead. A list rather than
SignUpFundsChainWhat readSignUpFunds reads. Matched by hand against the paseo descriptors
UsernameCredibilityA consumer’s standing as the resources pallet records it.
WatchErrorHandler—

Variables

NameSummary
AIRDROP_VRF_TRANSCRIPT_LABELVRF_TRANSCRIPT_LABEL, which is also the domain item’s prefix.
GAME_AIRDROP_EVENT_ID_BASEGame::airdrop_event_id_base() — 27 bytes, the ten trailing spaces included as
MAX_GAME_AIRDROPSGame’s MAX_GAME_AIRDROPS: a game schedules at most this many draws.
PEOPLE_AIRDROPS_EVENT_ID_BASEindiv_pallet_people_airdrops::EVENT_ID_BASE — 24 bytes, four trailing spaces
PERSONHOOD_CONTEXT_INDEXThe context suffix indices the personhood product owns, mirroring
PERSONHOOD_PRODUCT_NAMEpersonhood::PRODUCT_NAME — the DotNS name (TLD excluded) the personhood
REGISTER_MESSAGE_PREFIXThe pallet’s domain prefix for the proof of ownership in Score.register.

Classes

class AsPersonError

Building an origin-modifying transaction extension — AsPerson or its lite-personhood peer PeopleLiteAuth — failed.

Raised when the chain does not declare the extension, declares a pipeline version this package cannot encode, or when a value does not survive a round trip through the chain’s own codec.

Unlike IndividualityDecodeError this one is thrown, not returned: it happens inside PolkadotSigner.signTx, where the only channel available is the exception PAPI already surfaces on the transaction’s error path.

Never interpolate a proof, a context or an alias into the message. Those are pseudonymous identity, and an error string is the least controlled place they can end up. An extension identifier or a version number is fine.

Extends: ProductIndividualityError

Constructors

constructor
new AsPersonError(message: string, options?: ErrorOptions): AsPersonError

class IndividualityDecodeError

A raw storage value did not match the shape the descriptor promised — an unknown streak or recognition variant, or a malformed grace ratio.

Messages must be fixed strings. Never interpolate a decoded value into one: the values here describe a person’s chain state, and an error message is the least controlled place they can end up. The variant that failed is identifiable from the message text alone.

Extends: ProductIndividualityError

Constructors

constructor
new IndividualityDecodeError(message: string, options?: ErrorOptions): IndividualityDecodeError

class ProductIndividualityError

Base class for errors raised by @parity/product-sdk-individuality.

Implements the cross-package SdkError marker so isSdkError(e) also recognizes it.

Extends: Error

Implements: SdkError

Constructors

constructor
new ProductIndividualityError(message: string, options?: ErrorOptions): ProductIndividualityError

Properties

isSdkError
propertyreadonlytrue

Discriminant present on all SDK errors.

source
propertyreadonly"individuality"

The package that raised the error, e.g. "host", "signer", "contracts".

Functions

airdropPhase()

airdropPhase(status: AirdropStatusTag): AirdropPhase

airdropVrfDomain()

domain_for_event: label bytes then the event id. Exported as the one part worth checking against a chain-side value.

airdropVrfDomain(eventId: string | Uint8Array<ArrayBufferLike>): Uint8Array

airdropVrfTranscript()

The transcript for one draw.

airdropVrfTranscript(options: { eventId: string | Uint8Array<ArrayBufferLike>; publicKey: Uint8Array }): VrfTranscript

Throws

  • ProductIndividualityError on a malformed event id or a wrong-width key.

buildLiteAliasBindTx()

Build the unsigned V5 general extrinsic that binds a lite person’s alias to account: PeopleLite.set_alias_account(account, valid_at_block) under PeopleLiteAuth::AsLiteAliasWithProof, encoded entirely client-side — no host createTransaction, no signer.

valid_at_block is the chain’s current best block; the chain accepts the call for its setup tolerance window (~600 blocks) after that. The proof is requested over the implication message this builder computes, and its context travels inside the proof — whichever call mints it decides, which for the lite ring must be the chain’s Score.score_context (see the module doc for the read that checks this before any of this work is done).

buildLiteAliasBindTx(chain: LiteAliasBindChain, options: BuildLiteAliasBindTxOptions): Promise<LiteAliasBindTx>

Returns

the finished extrinsic bytes and the proof’s ring coordinates.

Throws

  • when the chain’s metadata declares a pipeline or a PeopleLiteAuth field list this package cannot encode (devnet predates the revision field), when a slot has no known general-transaction value, or when the proof request fails or resolves malformed.
  • when account is not a valid address, or the chain serves no readable metadata or a malformed genesis hash.

canClaimFullUsername()

Whether this account can still claim a bare name.

This is the chain’s own precondition, not an approximation of it: the claim extrinsic rejects a record that already carries a full username. Exact because the decoder throws on an empty name, so null means full_username.is_none().

canClaimFullUsername(record: ConsumerUsernames): boolean

claimPrizeTx()

Build the Game.claim_airdrop call, unsigned. Pays::No on success, so only a rejected claim costs a fee.

claimPrizeTx(chain: ClaimChain<Tx>, options: { airdropIndex: number; beneficiary: string; gameIndex: number }): Tx

confirmClaim()

Did a submitted claim take effect? Re-reads the row rather than watching, so it answers after a reload. Absence means it landed — unless the draw has left Claiming, where the lifecycle may have swept the row instead.

confirmClaim(chain: AirdropChain & ClaimChain<unknown>, options: ConfirmClaimOptions): Promise<Result<ClaimOutcome, ProductIndividualityError>>

contextSuffixBytes()

Expand a ContextSuffix to the 32 bytes the context hash consumes, mirroring ProductContextSuffix::bytes() in individuality/support.

contextSuffixBytes(suffix: DerivationIndex): Uint8Array

Throws

  • ProductIndividualityError on an index outside u32, or Raw bytes that are not exactly 32.

creditHash()

The credit one attestation awards, as lowercase hex: blake2b-256("polkadot-pop-game" ++ game_index ++ round ++ attester ++ attestee).

game_index is a little-endian u32, round a u8, and each player a SCALE AccountOrPerson. An account hashes as its raw bytes, so its SS58 prefix does not matter.

creditHash(options: { attestee: PlayerKey; attester: PlayerKey; gameIndex: number; round: number }): string

Throws

  • ProductIndividualityError when a number is out of range or a player does not encode.

decodeAbsenceGracePolicy()

Decode the grace policy from its strict 0x + four-hex-digit serialization.

Any other encoding — missing prefix, wrong length, non-hex digit — throws. The value is validated rather than trusted because a SizedHex<2> arriving malformed means the descriptor and the chain disagree.

decodeAbsenceGracePolicy(value: string): AbsenceGracePolicy

decodeConsumerInfo()

undefined in means the account has no record, which is an answer, not a failure.

decodeConsumerInfo(value: RawConsumerInfo | undefined): ConsumerUsernames | null

deriveClaimEligibility()

Decide whether one prize can be claimed. Never throws.

deriveClaimEligibility(inputs: ClaimInputs): ClaimEligibility

derivePersonhoodState()

Derive a person’s membership standing from one pinned snapshot.

Never throws: an inconsistent record degrades to Suspended rather than failing the caller’s render.

derivePersonhoodState(snapshot: PersonhoodInputs): PersonhoodState

displayUsername()

The host computes this same rule over the same record at session-pairing time and exposes the answer as account.getUserId().primaryUsername. For the signed-in user the two should agree; if they do not, the session snapshot is older than the chain.

displayUsername(record: ConsumerUsernames): string

fromPapi()

fromPapi(client: Client, api: Api): PapiIndividualityChain<Api, Client>

gameAirdropEventId()

Mirrors Game::airdrop_event_id, a plain impl method, so only its base reaches metadata and the pinned vectors below keep this honest.

gameAirdropEventId(options: { airdropIndex: number; base: string | Uint8Array<ArrayBufferLike>; gameIndex: number }): string

Throws

  • ProductIndividualityError on a malformed base, or an index wider than its chain type (u32 game, u8 airdrop).

gameAirdropEventIds()

Every draw id of one game, in airdrop-index order. airdropsScheduled only exists while that game is current, so a past game’s count must have been captured — probing cannot tell a cleaned-up draw from one never scheduled.

gameAirdropEventIds(options: { airdropsScheduled: number; base: string | Uint8Array<ArrayBufferLike>; gameIndex: number }): string[]

gameTimeline()

A line-for-line mirror of the runtime’s GameTimes trait, including saturating_sub clamping at zero — reachable for a play time earlier than the phases before it.

registrationStarts = play - shuffle - postShuffleMargin - registration registrationEnds = play - shuffle - postShuffleMargin shuffleDeadline = play - postShuffleMargin reportingEnds = play + reporting playerProcessEnds = play + reporting + playerProcess

Only correct for a game that does not exist yet — a created game stores its own.

gameTimeline(gamePlayTime: number, durations: GamePhaseDurations): GameTimeline

groupSeats()

All maxGroupSize seats of the group the player at playerIndex sits in, ascending by index.

A seat whose index reaches past playerCount is unoccupied. Filtering those out leaves the member list the pallet itself computes.

groupSeats(playerIndex: number, playerCount: number, maxGroupSize: number): GroupSeat[]

litePeopleRing()

The people-lite ring on the chain with genesis genesisHash.

litePeopleRing(genesisHash: `0x${string}`): RingLocation

lookupUsername()

Read the usernames registered for an account, from Resources.Consumers.

Returns a Result, per the SDK-wide error model: ok carries the answer, err carries a ProductIndividualityError. An account with no consumer record is not a failure. It resolves to ok(null), because the chain was asked and answered.

The account is the input the SDK already hands callers: rootAddress from a paired session keys this map.

Not an authorization oracle. This is a client-side read in a client-side library, and a backend that trusts “the SDK said this name is theirs” is trivially spoofed.

lookupUsername(chain: ConsumersChain, options: LookupUsernameOptions): Promise<Result<ConsumerUsernames | null, ProductIndividualityError>>

mintAccountAirdropVrfs()

mintAccountAirdropVrfs(signer: AirdropVrfSigner, options: MintAccountAirdropVrfsOptions): Promise<Result<AccountVrfSignature[], ProductIndividualityError>>

missesInWindow()

Misses the window currently holds: the games inside it that were absences.

Mirrors the runtime’s misses_in_window(window) on the history exactly as stored. The window is clamped to the one-byte history width, so a wider policy counts eight games and no more.

missesInWindow(history: number, window: number): number

numberOfGroups()

The groups a roster of playerCount splits into, 0 when there is no roster.

numberOfGroups(playerCount: number, maxGroupSize: number): number

offboardTx()

Build Game.offboard, unsigned.

Only valid between games, or during registration for a player who has not signed up for that game. Offboarding a Recognized player suspends their personhood for good: playing as a person again takes a new personal id with a new key.

offboardTx(chain: ReportChain<Tx>): Tx

parsePeopleAirdropsEventId()

The draw index inside a PeopleAirdrops event id, or null if it is not one. Airdrop.Events holds both schedulers, so a foreign id is data, not a caller bug.

parsePeopleAirdropsEventId(eventId: string): bigint | null

peopleAirdropsEventId()

Derive a PeopleAirdrops draw’s event id, mirroring PeopleAirdrops::draw_event_id. The u64 index takes a bigint or a safe-integer number: anything above MAX_SAFE_INTEGER would round before reaching the encoder and address a draw nobody scheduled, so it throws.

peopleAirdropsEventId(drawIndex: number | bigint): string

peopleRing()

The people ring on the chain with genesis genesisHash. The host resolves the Members pallet by name, so no PalletInstance junction is needed.

peopleRing(genesisHash: `0x${string}`): RingLocation

personhoodContext()

The personhood product’s context for name on the network issuing .<tld> names: productContext("peopl.<tld>", Index(PERSONHOOD_CONTEXT_INDEX[name])).

The TLD belongs to the network ("paseo" on the paseo networks, "test" on previewnet until truapi 0.13.0 renames it to "testnet"), so the same context name on two networks is two different values, which is why it is a parameter and never a default.

personhoodContext(tld: string, name: "score" | "resources" | "peopleLiteAuth" | "dotnsGateway" | "peopleAirdrops"): Uint8Array

Parameters

  • tld: a single lower-case DotNS label, without the leading dot.

Throws

  • ProductIndividualityError on a tld the runtime cannot represent, or a composite one: "peopl" + ".te.st" and "peopl.te" + ".st" would collide.

productContext()

The 32-byte proof context of { productId, suffix }, mirroring indiv_support::context::build_product_context.

This is the value that must equal contextualAlias.context in every createAccountProof / getAccountAlias response for that product account, and the value of the on-chain context constants (Score.score_context and friends) on a runtime that derives them the product way.

productContext(productId: string, suffix: DerivationIndex): Uint8Array

Parameters

  • productId: the full DotNS id, TLD included ("dim2.dot", "peopl.test"). Never assemble it from a hardcoded TLD: the network decides the TLD, so take it from configuration or from the chain.

Throws

  • ProductIndividualityError via contextSuffixBytes.

readAirdropDraw()

A draw that is not in storage is not a failure, it is phase: "Gone" — the steady state for every past draw. Not evidence the draw existed either: an id that was never scheduled answers identically.

readAirdropDraw(chain: AirdropChain, options: ReadAirdropDrawOptions): Promise<Result<AirdropDraw, ProductIndividualityError>>

readClaimEligibility()

Check whether one prize can be claimed, from one pinned finalized block. The six gates span the draw, the score record and the asset list, so reading them apart is exactly the inconsistency pinning prevents.

readClaimEligibility(chain: AirdropChain & ClaimChain<unknown>, options: ReadClaimEligibilityOptions): Promise<Result<ClaimEligibilityResult, ProductIndividualityError>>

readCommunicationIdentifier()

The key an account is reached on during the game, at one pinned finalized block.

readCommunicationIdentifier(chain: RosterChain, options: ReadCommunicationIdentifierOptions): Promise<Result<CommunicationIdentifierResult, ProductIndividualityError>>

readCreditCandidates()

Every credit the attestee could earn in the running game, one per co-player per round, with the game and the roster read at one pinned finalized block.

Deriving is what names the attester behind each credit, and it is the only way to see the credits that have not been awarded yet. Match the hashes against the claims @parity/product-sdk-nfts reads to tell the two apart. The roster is drained when the game ends, so cache the result if it has to outlive the game.

readCreditCandidates(chain: CreditCandidatesChain, options: ReadCreditCandidatesOptions): Promise<Result<CreditCandidatesResult, ProductIndividualityError>>

readCurrentGame()

No game running is not a failure, it is BetweenGames — the chain’s normal state, since one game exists at a time and each is killed when it ends.

This function has multiple overloads.

Overload 1

readCurrentGame(chain: GameChain & GamePlayersChain, options: ReadCurrentGameOptions & { players: readonly AirdropRegistrant[] }): Promise<Result<CurrentGameResult, ProductIndividualityError>>

No game running is not a failure, it is BetweenGames — the chain’s normal state, since one game exists at a time and each is killed when it ends.

Overload 2

readCurrentGame(chain: GameChain, options?: Omit<ReadCurrentGameOptions, "players">): Promise<Result<CurrentGameResult, ProductIndividualityError>>

No game running is not a failure, it is BetweenGames — the chain’s normal state, since one game exists at a time and each is killed when it ends.

readDrawRegistration()

Whether an identity entered a draw, which readAirdropDraw cannot say: an absent Winners entry before the draw means “not drawn yet”, not “did not enter”.

A prefix scan, hence a separate call — the cost grows with the participant count, so this is for “you are in tonight’s draw”, not for every status poll. The personhood path could point-read it, but is gated on the PeopleAirdrops blockers.

readDrawRegistration(chain: AirdropChain, options: { eventId: string; registrant: AirdropRegistrant; signal?: AbortSignal }): Promise<Result<DrawRegistration, ProductIndividualityError>>

readGameAirdropEventIds()

Every event id of one game’s draws, with the base read from the chain rather than assumed. That is the point of it: a hardcoded copy would go on deriving ids for draws that do not exist if the base ever moved.

readGameAirdropEventIds(chain: AirdropChain, options: ReadGameAirdropEventIdsOptions): Promise<Result<string[], ProductIndividualityError>>

readGameSignUpRequirement()

What this player may do about the running game, at one pinned block. Between games is not a failure, it is a NoGameRunning blocker on the success channel.

readGameSignUpRequirement(chain: GameChain & SignUpChain<unknown>, options: ReadGameSignUpRequirementOptions): Promise<Result<GameSignUpRequirement, ProductIndividualityError>>

readGroupMembers()

The members of one group in one round, at one pinned finalized block.

An occupied seat with no player behind it means the counts and the indices come from different shuffles, or the indices are already being drained, and arrives on the err channel.

readGroupMembers(chain: RosterChain, options: ReadGroupMembersOptions): Promise<Result<GroupMembersResult, ProductIndividualityError>>

readLiteSignUpRequirement()

What this account may do about the free lite sign-up, at one pinned block: the account sign-up read plus the lite gates, with the blockers merged.

canSignUp answers for sign_up_with_account_lite_invite specifically — every lite blocker stops the sign-up itself, so it is the account read’s answer AND’ed with “no lite blocker”. The draw-entry split (canEnterDraws, the draw-only blockers) carries over from readGameSignUpRequirement unchanged: the draws ride on the sign-up here exactly as they do there.

An AliasNotBound answer is not a dead end — it says the bind leg (PeopleLite.set_alias_account under withLiteAlias(AliasWithProof)) has not run yet. AnotherAccountInvited and AccountIsALitePerson are dead ends for this account; AliasBoundElsewhere is recoverable, but only through a call this package cannot make. signup-types.ts has the detail per arm.

Game.LiteInvites is consulted only when a binding in the score context exists: the invite pin is keyed by the alias, and without the binding the alias is unknown here.

This function has multiple overloads.

Overload 1

readLiteSignUpRequirement(chain: GameChain & SignUpChain<unknown> & ScoreContextChain & NetworkSuffixChain & LiteSignUpChain<unknown>, options: ReadLiteSignUpRequirementOptions): Promise<Result<LiteSignUpRequirement, ProductIndividualityError>>

What this account may do about the free lite sign-up, at one pinned block: the account sign-up read plus the lite gates, with the blockers merged.

canSignUp answers for sign_up_with_account_lite_invite specifically — every lite blocker stops the sign-up itself, so it is the account read’s answer AND’ed with “no lite blocker”. The draw-entry split (canEnterDraws, the draw-only blockers) carries over from readGameSignUpRequirement unchanged: the draws ride on the sign-up here exactly as they do there.

An AliasNotBound answer is not a dead end — it says the bind leg (PeopleLite.set_alias_account under withLiteAlias(AliasWithProof)) has not run yet. AnotherAccountInvited and AccountIsALitePerson are dead ends for this account; AliasBoundElsewhere is recoverable, but only through a call this package cannot make. signup-types.ts has the detail per arm.

Game.LiteInvites is consulted only when a binding in the score context exists: the invite pin is keyed by the alias, and without the binding the alias is unknown here.

Overload 2

readLiteSignUpRequirement(chain: GameChain & SignUpChain<unknown> & ScoreContextChain & LegacySuffixChain & LiteSignUpChain<unknown>, options: ReadLiteSignUpRequirementOptions): Promise<Result<LiteSignUpRequirement, ProductIndividualityError>>

What this account may do about the free lite sign-up, at one pinned block: the account sign-up read plus the lite gates, with the blockers merged.

canSignUp answers for sign_up_with_account_lite_invite specifically — every lite blocker stops the sign-up itself, so it is the account read’s answer AND’ed with “no lite blocker”. The draw-entry split (canEnterDraws, the draw-only blockers) carries over from readGameSignUpRequirement unchanged: the draws ride on the sign-up here exactly as they do there.

An AliasNotBound answer is not a dead end — it says the bind leg (PeopleLite.set_alias_account under withLiteAlias(AliasWithProof)) has not run yet. AnotherAccountInvited and AccountIsALitePerson are dead ends for this account; AliasBoundElsewhere is recoverable, but only through a call this package cannot make. signup-types.ts has the detail per arm.

Game.LiteInvites is consulted only when a binding in the score context exists: the invite pin is keyed by the alias, and without the binding the alias is unknown here.

Overload 3

readLiteSignUpRequirement(chain: GameChain & SignUpChain<unknown> & ScoreContextChain & LiteSignUpChain<unknown>, options: ReadLiteSignUpRequirementOptions & { tld: string }): Promise<Result<LiteSignUpRequirement, ProductIndividualityError>>

What this account may do about the free lite sign-up, at one pinned block: the account sign-up read plus the lite gates, with the blockers merged.

canSignUp answers for sign_up_with_account_lite_invite specifically — every lite blocker stops the sign-up itself, so it is the account read’s answer AND’ed with “no lite blocker”. The draw-entry split (canEnterDraws, the draw-only blockers) carries over from readGameSignUpRequirement unchanged: the draws ride on the sign-up here exactly as they do there.

An AliasNotBound answer is not a dead end — it says the bind leg (PeopleLite.set_alias_account under withLiteAlias(AliasWithProof)) has not run yet. AnotherAccountInvited and AccountIsALitePerson are dead ends for this account; AliasBoundElsewhere is recoverable, but only through a call this package cannot make. signup-types.ts has the detail per arm.

Game.LiteInvites is consulted only when a binding in the score context exists: the invite pin is keyed by the alias, and without the binding the alias is unknown here.

readPersonhoodState()

Read a person’s personhood state from one pinned finalized block.

Takes a DotNS username or an account address. Every resolved answer carries both the derived state and the PersonhoodMetrics it came from, so a caller rendering progress does not have to switch on the state to find a score.

Returns a Result, per the SDK-wide error model: ok carries the answer, err carries a ProductIndividualityError. Everything that can go wrong arrives on the err channel, not only decode failures. That includes an unreachable node, an aborted signal, and the pinned block leaving the follower’s window mid-read, each normalized into the package’s error type with the original cause attached.

A username nobody owns is not a failure. It resolves to ok({ tag: "UsernameUnowned", ... }), because the chain was asked and answered. An account input never lands there: nothing was looked up, so an account with no records resolves to NotEnrolled instead.

Not an authorization oracle. This is a client-side read in a client-side library, and a backend that trusts “the SDK said Member” is trivially spoofed.

readPersonhoodState(chain: IndividualityChain, options: ReadPersonhoodStateOptions): Promise<Result<PersonhoodResult, ProductIndividualityError>>

readPlayerIndices()

The index a player holds in each round, at one pinned finalized block.

readPlayerIndices(chain: RosterChain, options: ReadPlayerIndicesOptions): Promise<Result<PlayerIndicesResult, ProductIndividualityError>>

readPrizeStatus()

Not an authorization oracle. The chain re-checks eligibility on claim, and a backend trusting a Won here is trivially spoofed.

Game.airdrop_event_id_base escapes the pinned block — PAPI serves constants from the client’s runtime — so it can only disagree across an upgrade mid-read.

readPrizeStatus(chain: PrizeStatusChain, options: ReadPrizeStatusOptions = {}): Promise<Result<PrizeStatus, ProductIndividualityError>>

readRegistrationEligibility()

Read Score.Participants and Score.PersonhoodThreshold at one pinned block and fold them into RegistrationEligibility.

Not an authorization oracle. The chain re-checks every guard at dispatch, and the threshold can move between this read and the transaction landing.

readRegistrationEligibility(chain: RegistrationEligibilityChain, options: ReadRegistrationEligibilityOptions): Promise<Result<RegistrationEligibility, ProductIndividualityError>>

readScoreContext()

Read Score.score_context and check it is the product derivation of peopl.<tld>/Index(0) — the only kind of context a stock host can mint.

A chain’s suffix source is fixed by its type, so one with none is a compile error rather than a runtime disappointment.

const score = await readScoreContext(chain, { tld: "paseo" }); if (score.ok && score.value.tag === "ProductDerived") { // mint proofs in { productId: score.value.productId, suffix: Index(0) } }

This function has multiple overloads.

Overload 1

readScoreContext(chain: ScoreContextChain & NetworkSuffixChain, options?: ReadScoreContextOptions): Promise<Result<ScoreContext, ProductIndividualityError>>

Read Score.score_context and check it is the product derivation of peopl.<tld>/Index(0) — the only kind of context a stock host can mint.

A chain’s suffix source is fixed by its type, so one with none is a compile error rather than a runtime disappointment.

const score = await readScoreContext(chain, { tld: "paseo" }); if (score.ok && score.value.tag === "ProductDerived") { // mint proofs in { productId: score.value.productId, suffix: Index(0) } }

Overload 2

readScoreContext(chain: ScoreContextChain & LegacySuffixChain, options?: ReadScoreContextOptions): Promise<Result<ScoreContext, ProductIndividualityError>>

Read Score.score_context and check it is the product derivation of peopl.<tld>/Index(0) — the only kind of context a stock host can mint.

A chain’s suffix source is fixed by its type, so one with none is a compile error rather than a runtime disappointment.

const score = await readScoreContext(chain, { tld: "paseo" }); if (score.ok && score.value.tag === "ProductDerived") { // mint proofs in { productId: score.value.productId, suffix: Index(0) } }

Overload 3

readScoreContext(chain: ScoreContextChain, options: ReadScoreContextOptions & { tld: string }): Promise<Result<ScoreContext, ProductIndividualityError>>

Read Score.score_context and check it is the product derivation of peopl.<tld>/Index(0) — the only kind of context a stock host can mint.

A chain’s suffix source is fixed by its type, so one with none is a compile error rather than a runtime disappointment.

const score = await readScoreContext(chain, { tld: "paseo" }); if (score.ok && score.value.tag === "ProductDerived") { // mint proofs in { productId: score.value.productId, suffix: Index(0) } }

readSignUpFunds()

The deposit, the free balance and the fee of a sign-up.

The deposit and the balance come from one pinned finalized block, the fee from wherever PAPI estimates it, see SignUpFunds.estimatedFee.

readSignUpFunds(chain: SignUpFundsChain, options: ReadSignUpFundsOptions): Promise<Result<SignUpFunds, ProductIndividualityError>>

readyToRegister()

Whether Score.register with a key would pass its guards now: the participant exists, is NotRecognized, and has the score or the sticky reached_personhood flag.

Suspended participants are not ready in this sense — they resume with register(None), a different call shape this package does not build — and neither are already-recognized ones.

Exported separately from the read, so it can run against a participant the caller already holds.

readyToRegister(participant: PersonhoodParticipant | null, personhoodThreshold: number): boolean

registerMessage()

"pop register using" ++ account — the 50 bytes the full member key signs.

The pallet builds the same bytes with account.using_encoded(|b| [PREFIX, b].concat()), and AccountId32 encodes as its bare 32 bytes, so this is a raw concatenation with no SCALE framing.

registerMessage(account: Uint8Array<ArrayBufferLike> | SS58String): Uint8Array

Parameters

  • account: the registering account (the transaction signer), as an SS58 address or its raw 32-byte public key.

Throws

  • ProductIndividualityError when the account does not decode or is not 32 bytes.

registerPersonhoodTx()

Build Score.register(Some((member_key, proof_of_ownership))), unsigned. Pays::No on success. Submission stays with @parity/product-sdk-tx, and the fee-free origin with import("./as-score-participant-signer.js").withScoreParticipant.

Preconditions on chain, or the dispatch fails: Score.Participants has the signer with reached_personhood || score >= PersonhoodThreshold and recognition == NotRecognized — check with readRegistrationEligibility. InvalidProofOfOwnership means the message or key is wrong; KeyAlreadyInUse that this member key already is a person.

registerPersonhoodTx(chain: RegisterChain<Tx>, options: RegisterPersonhoodOptions): Tx

Throws

  • ProductIndividualityError on a wrong-width key or signature. Checked here because the chain’s own failure rejects the call with nothing to inspect, after the fee-free allowance was already spent on it.

reportTx()

Build Game.report, unsigned.

Only valid while the game is in Reporting. Each Person vote awards the attestee a claim credit on the spot, and the call fails with Game.CreditCapacityExhausted before recording anything when there is no room for them. Pays::No on success.

reportTx(chain: ReportChain<Tx>, options: ReportOptions): Tx

Throws

  • ProductIndividualityError on a vote that is neither Person nor NotPerson.

ringCollectionId()

A personhood ring’s collection identifier: the human-readable name, space-padded to the 32-byte CollectionId the Members pallet keys on. Lite and full personhood differ only in this junction.

ringCollectionId(name: "people" | "people-lite"): Uint8Array

runScoreContextRead()

Throws; readScoreContext owns the Result boundary. Exported so a composing read can run it against a block it already pinned, like prize-status.ts runs runDrawRead, rather than pinning a second.

runScoreContextRead(chain: AnyScoreContextChain, options: ReadScoreContextOptions = {}, pinned?: FinalizedSnapshot): Promise<ScoreContext>

signUpWithAccountTx()

Build Game.sign_up_with_account, unsigned. Pays::No on success, though a new or archived player still pays a deposit.

No Alias argument: a recognized player needs one that cannot be produced, and an argument that always fails on chain is worse than none.

A returning player owes no deposit and can sign under withScoreParticipant to skip the fee as well, which is how a zero-balance account signs up again. A new or archived player owes the deposit, so sign plainly.

signUpWithAccountTx(chain: SignUpChain<Tx>, options: SignUpWithAccountOptions): Tx

Throws

  • ProductIndividualityError on a wrong-width key or signature, or an airdrop count that disagrees with airdropsScheduled. Checked because the chain’s own failure rejects the sign-up with nothing to inspect.

signUpWithLiteInviteTx()

Build Game.sign_up_with_account_lite_invite, unsigned. Pays::No, no deposit, valid on a zero balance — but only submittable under withLiteAlias({ tag: "AliasWithAccount" }) by the bound account, with RestrictOrigins true (which that signer sets).

The same width and count guards as signUpWithAccountTx: they protect the same call arguments, and the chain’s own rejection names nothing local.

signUpWithLiteInviteTx(chain: LiteSignUpChain<Tx>, options: SignUpWithLiteInviteOptions): Tx

Throws

  • ProductIndividualityError on a wrong-width key or signature, or an airdrop count that disagrees with airdropsScheduled.

statusTag()

Validate a raw Status variant name. Exported so a read that only needs the variant, not the whole event, still fails loudly on an unknown one.

The domain tags match the chain’s variant names exactly, so this narrows rather than translates.

statusTag(type: string): AirdropStatusTag

toAirdropEvent()

toAirdropEvent(eventId: string, raw: RawActiveEvent): AirdropEvent

Parameters

  • eventId: the key the row was read under, rather than raw.id; the two agreeing is asserted below, not assumed.

Throws

  • IndividualityDecodeError on an unknown status variant, an out-of-range timestamp, or an id that disagrees with the key.

toCurrentGame()

Map the raw running game, selecting the deadline that belongs to its phase.

toCurrentGame(raw: RawGameInfo): CurrentGame

Throws

  • IndividualityDecodeError on a GameState variant this package does not know.

toGamePhaseDurations()

Map the raw phase durations, from either source.

toGamePhaseDurations(raw: RawPhaseDurations): GamePhaseDurations

toGameSchedulePreview()

Map one upcoming schedule, deriving its timeline from the given durations.

The durations must come from the same block as the schedule, or the projection describes a game under rules that were never in force together.

toGameSchedulePreview(raw: RawGameSchedule, durations: GamePhaseDurations): GameSchedulePreview

toPersonhoodParticipant()

Map a raw PAPI participant to the domain shape the derivation consumes.

The recognition payload (a revision id) is discarded, the game-economy fields are dropped, and a missing last_attended_game becomes null rather than undefined so the domain type has one absent value, not two.

toPersonhoodParticipant(raw: RawParticipant): PersonhoodParticipant

toRawRegistrationEntry()

A domain registrant as the Winners key wants it.

toRawRegistrationEntry(registrant: AirdropRegistrant): RawRegistrationEntry

usernameBase()

The letters part of a lite username, which is what a claim would offer.

A lite username is letters, one dot, then digits, so the dot is always there and there is only one. A full username has no dot and is returned unchanged.

A suggestion, not an entitlement. An account may hold a reservation for a different name, and the reservation is what the chain honours.

usernameBase(username: string): string

watchCurrentGame()

Game.Game, which is null between games.

watchCurrentGame(chain: CurrentGameWatchChain, onValue: (game: CurrentGame | null, block: WatchedBlock) => void, onError: WatchErrorHandler): () => void

watchParticipant()

Score.Participants, which is null for a player who has never been scored.

watchParticipant(chain: ParticipantWatchChain, options: WatchPlayerOptions, onValue: (participant: PersonhoodParticipant | null, block: WatchedBlock) => void, onError: WatchErrorHandler): () => void

watchPlayer()

Game.Players, which is null for a player who never signed up or was archived.

watchPlayer(chain: PlayerWatchChain, options: WatchPlayerOptions, onValue: (record: PlayerRecord | null, block: WatchedBlock) => void, onError: WatchErrorHandler): () => void

withAsPerson()

Wrap a signer so its transactions run under a person origin.

signBytes and publicKey pass through untouched. PAPI stamps publicKey into the extrinsic and uses it to fetch the nonce, so it has to stay the inner signer’s.

withAsPerson(signer: PolkadotSigner, info: AsPersonInfo): PolkadotSigner

Parameters

  • signer: the signer to wrap, e.g. from AccountsProvider.getProductAccountSigner.
  • info: which person origin to use, and where the proof comes from.

Returns

a PolkadotSigner usable anywhere the original was.

withLiteAlias()

Wrap a signer so its transactions run under a lite-person origin.

signBytes and publicKey pass through untouched. PAPI stamps publicKey into the extrinsic and uses it to fetch the nonce, so it has to stay the inner signer’s.

withLiteAlias(signer: PolkadotSigner, info: LiteAliasInfo): PolkadotSigner

Parameters

  • signer: the signer to wrap, e.g. from AccountsProvider.getProductAccountSigner.
  • info: which lite-person origin to use, and where the proof comes from.

Returns

a PolkadotSigner usable anywhere the original was.

withScoreParticipant()

Wrap a signer so its transactions run as the score participant, fee-free.

signBytes and publicKey pass through untouched. PAPI stamps publicKey into the extrinsic and uses it to fetch the nonce, so it has to stay the inner signer’s — which is also what keeps the participant the chain resolves (Participants[Account(signer)]) the account this signer signs as.

withScoreParticipant(signer: PolkadotSigner): PolkadotSigner

Parameters

  • signer: the signer to wrap, e.g. from AccountsProvider.getProductAccountSigner.

Returns

a PolkadotSigner usable anywhere the original was.

Interfaces

interface AbsenceGracePolicy

The absence-grace policy currently in force, decoded from Score.AbsenceGraceRatio.

window is a count of recent games; allowedMisses is how many of them may be absences before the next one suspends. A window of 0 means no grace at all.

Properties

allowedMisses
propertynumber
window
propertynumber

interface AccountVrfSignature

One AirdropVrfs::Account entry, shaped as the host’s signVrf returns it.

Properties

preOutput
propertyUint8Array

32 bytes.

proof
propertyUint8Array

64 bytes, the DLEQ proof.

interface AirdropAssetId

The prize asset, as an XCM location. Opaque on purpose — this package does not model XCM; it is the key an Assets.Metadata read takes.

Properties

interior
propertyunknown
parents
propertynumber

interface AirdropChain

Structural, so a test double satisfies it. See IndividualityChain in read.ts for the conventions and where the fidelity guard lives.

Matched by hand against the paseo descriptors on 2026-08-20:

Game.airdrop_event_id_base: PlainDescriptor<SizedHex<27>> Airdrop.Events: StorageDescriptor<[Key: SizedHex<32>], ActiveEvent, true, never> Airdrop.Winners: StorageDescriptor<[SizedHex<32>, RegistrationEntry], SizedHex<32>, true, never> Airdrop.EventEntropy: StorageDescriptor<[Key: SizedHex<32>], SizedHex<32>, true, never>

Extends: PinnedChain

Properties

individuality
property{ constants: { Game: { airdrop_event_id_base: unknown } }; query: { Airdrop: { EventEntropy: { getValue: unknown }; Events: { getValue: unknown }; Registrations: { getEntries: unknown }; SupportedAssets: { getValue: unknown }; Winners: { getValue: unknown } } } }

interface AirdropDraw

One draw at one pinned block. event is null exactly when phase is "Gone", but the outcome survives that: Winners is cleared in its own lifecycle state, so a win can outlive the event row or be swept before it.

Properties

at
propertyFinalizedSnapshot

The finalized block every read in this row was pinned to.

entropy
propertystring | null

The draw’s entropy seed, present from DrawWinners onwards and null before it. Only useful for verifying a draw independently; a product rendering a result does not need it.

event
propertyAirdropEvent | null
eventId
propertystring
outcome
propertyAirdropOutcome
phase
propertyAirdropPhase

interface AirdropEvent

The counters are null where the Status variant does not carry them — not zero: a Finalizing draw did have participants, the chain stopped reporting it.

FieldAbsent in
totalParticipantsScheduled, Finalizing
effectiveWinnersScheduled, Registering
claimedScheduled, Registering, AwaitingEntropy, DrawWinners

Properties

claimed
propertynumber | null
drawTime
propertynumber

Unix seconds: registration closes and the draw is performed.

effectiveWinners
propertynumber | null
endTime
propertynumber

Unix seconds: claiming closes and clean-up starts.

eventId
propertystring

The 32-byte event id, 0x-prefixed, as the draw is addressed by.

phase
propertyAirdropPhase
prize
propertyAirdropPrize
registrationStarts
propertynumber

Unix timestamp in seconds, when registration opens.

All three timestamps are u64 seconds on chain, not block numbers and not milliseconds. Multiply by 1000 before handing one to Date.

source
propertystring | null

The account funding this event, for source-funded draws. null for pre-funded ones, whose released funds stay in the pallet’s pot.

status
propertyAirdropStatusTag
totalParticipants
propertynumber | null

interface AirdropPrize

The prize a draw pays out, from AirdropPrize on chain.

Properties

assetAmount
propertybigint

Total amount paid across all winners, in the prize asset’s smallest unit.

assetId
propertyAirdropAssetId

Not the chain’s native token. Prizes are paid in a foreign asset, so formatting assetAmount with the chain’s tokenDecimals is wrong. Read Assets.Metadata for this id and use its decimals.

maxWinners
propertynumber

Hard cap on winners, whatever the participant count.

winnerCapPermill
propertynumber

The share of participants that may win, as a Permill — parts per million, not a count and not a percentage. 10_000 is one percent. Named for the unit because rendering it as a count is the mistake the plain chain name (winner_cap) invites.

interface AirdropVrfSigner

An sr25519 VRF over one draw’s transcript.

Wire this to AccountsProvider.signVrf(account, label, items). Neither host call satisfies it directly, since both take the account first, so the adapter closes over it and unwraps the Result. The module doc has one.

Structural, so the package keeps no dependency on @parity/product-sdk-host.

Methods

signVrf
signVrf(transcriptLabel: Uint8Array, items: VrfTranscriptItem[]): Promise<AccountVrfSignature>

interface BuildLiteAliasBindTxOptions

Options for buildLiteAliasBindTx.

Properties

account
propertystring

The account to bind, as an SS58 address. A plain call parameter: the chain ties it to nothing but the proof’s alias, which is what lets the personhood product bind another product’s account. LiteInvites later pins it as the one account this lite person may ever invite, so show a person which account they are binding before building this.

createProof
propertyCreateRingVRFProof

Mints the lite ring-VRF proof over the message this builder computes. Wire it to createRingVRFProof with the lite key handle, the RingLocation from litePeopleRing, and the ProductProofContext that readScoreContext reported — never choose the message yourself.

signal
propertyoptionalAbortSignal

interface CapturedGame

A game identified by the caller rather than read from the chain.

Properties

airdropsScheduled
propertynumber

airdrops_scheduled as it was while the game ran. Capture it then: it is unreadable afterwards, and it is the count that actually got scheduled rather than what the schedule asked for.

index
propertynumber

interface ClaimChain

The Game.claim_airdrop call, plus the Score.Participants read the check needs. Composed with AirdropChain, which supplies the draw.

Extends: PinnedChain

Properties

individuality
property{ constants: { Game: { airdrop_event_id_base: unknown } }; query: { Score: { Participants: { getValue: unknown } } }; tx: { Game: { claim_airdrop: unknown } } }

interface ClaimEligibility

Whether a specific prize can be claimed, and what stops it if not.

Properties

blockers
propertyClaimBlocker[]

Empty exactly when claimable is true.

claimable
propertyboolean
ticket
propertystring | null

The winning ticket, when there is one. Worth keeping: it is the only local evidence that distinguishes “claimed” from “never won” once the chain has removed the Winners row.

window
propertyClaimWindow | null

The draw’s deadlines whenever the draw exists, independent of whether this caller can claim, so a product can show the window to someone who did not win. null only when the event row is gone. Read claimable for whether there is anything to do before it.

interface ClaimEligibilityResult

The result of checking a claim against the chain.

Extends: ClaimEligibility

Properties

airdropIndex
propertynumber
at
propertyFinalizedSnapshot
eventId
propertystring
gameIndex
propertynumber

interface ClaimInputs

Everything the predicate needs, all from one pinned block.

Properties

draw
propertyAirdropDraw

The draw, as readAirdropDraw or readPrizeStatus returned it.

gameIndex
propertynumber

The game the prize belongs to, which the chain compares attendance against.

now
propertynumber

Unix seconds, against the draw’s end_time. An input rather than the clock so a caller can pass the block’s own time: a device clock minutes fast will call a live window closed.

participant
propertyPersonhoodParticipant | null

null when Score.Participants holds no record for the claimant.

prizeAssetEnabled
propertyboolean | null

Whether the prize asset is still enabled for airdrops, from Airdrop.SupportedAssets. false blocks the claim on chain, so leaving it out would let a claimable: true cost the player a fee.

null means nothing to check: the draw’s event row is gone and carries no asset id. Not the same as disabled, and reporting it as such would name a cause that is not true on top of the DrawNotClaiming that already fires.

interface ClaimTarget

Everything a claim addresses.

Properties

airdropIndex
propertynumber
gameIndex
propertynumber
registrant
propertyAirdropRegistrant

Who is claiming. Decides both the Score.Participants key and the Winners key, and must match the identity that entered the draw — a player who signed up with an alias cannot claim as an account.

interface ClaimWindow

When a claim stops being possible. Two deadlines apply and only one is a clock — the other has no timestamp at all.

Properties

closesOnNextAttendance
propertyboolean

Always true on the game path, and the reason a countdown alone misleads: attending the next game moves last_attended_game and closes the claim, usually well before endTime. The runtime contemplates relaxing == to >=, which would make this false.

endTime
propertynumber

Unix seconds. The draw’s end_time.

interface CommunicationIdentifierResult

Properties

at
propertyFinalizedSnapshot
identifier
propertyUint8Array<ArrayBufferLike> | null

The 65 bytes the account registered at sign-up, or null when it has none. The chain never interprets them, and deriving them stays with the product.

interface ConfirmClaimOptions

Options for confirmClaim.

Extends: ClaimTarget

Properties

signal
propertyoptionalAbortSignal

interface ConsumersChain

The chain surface this read needs, structural rather than a pinned descriptor.

Anything exposing this one entry satisfies it: a real ChainClient from getChainAPI, a future People Lite deployment, or a hand-rolled test double. Deliberately narrower than IndividualityChain in read.ts, so a double for either read does not have to implement the other’s entries.

Written with method shorthand on purpose: the parameter bivariance that gives is what lets the real PAPI signature satisfy the loosened key type below.

Fidelity is checked at compile time from the umbrella package, in packages/sdk/src/individuality/contract.test.ts, for the reason recorded there: inside this package the same assertion is vacuous.

Properties

individuality
property{ query: { Resources: { Consumers: { getValue: unknown } } } }

interface ConsumerUsernames

The usernames registered for one account, decoded.

Properties

credibility
propertyUsernameCredibility
fullUsername
propertystring | null
liteUsername
propertystring

Always present, for example example.07.

interface CreditCandidate

One credit the attestee could earn this game: a co-player of one round, and the hash.

Properties

attester
propertyPlayerKey

Exactly as the chain keys the co-player, which is the form the hash is built from.

attesterIndex
propertynumber
hash
propertystring

The credit, as creditHash derives it.

round
propertynumber

interface CreditCandidatesResult

Properties

at
propertyFinalizedSnapshot
candidates
propertyCreditCandidate[]

Ascending by round, then by attester index. Empty when the attestee holds no seat.

gameIndex
propertynumber | null

The game the candidates belong to, or null when no game has a roster at this block.

interface CurrentGame

The game that is running now.

Properties

airdropsScheduled
propertynumber

Draws actually scheduled, carrying airdrop indices 0..airdropsScheduled.

Derive event ids from this, not the schedule’s count. Scheduling stops at the first failure, so a game can end up with fewer draws than it asked for.

gamePlayTime
propertynumber
index
propertynumber

The game index, which is also the game_index a prize claim takes.

Games are numbered from 1: the counter is incremented when a game is created, so index 0 never names one.

maxGroupSize
propertynumber
nextDeadline
propertynumber | null

The boundary this phase runs to, null for PlayerProcess and Cancelling, which end on work rather than time. Taken from the boundary matching phase, never inferred from the clock: transitions run in an offchain worker’s own time, so a boundary can be past while its phase is current.

pendingAttendance
propertynumber

Registered players whose attendance is not settled yet. Reaches zero when every player has been resolved, which can end the reporting phase early.

phase
propertyGamePhase
playerCount
propertynumber | null

Players in the roster, which the group arithmetic of the roster reads needs.

Known from the end of the shuffle until PlayerProcess clears the indices, and null outside that window, which is also when the roster reads are valid.

registrationEnds
propertynumber

Unix seconds. Stored on the game, not re-derived.

reportingEnds
propertynumber
rounds
propertynumber
shuffleDeadline
propertynumber

interface CurrentGameWatchChain

Structural, so a test double satisfies it.

Properties

individuality
property{ query: { Game: { Game: { watchValue: unknown } } } }

interface DrawRegistration

One draw’s registration for one identity.

Properties

at
propertyFinalizedSnapshot
entriesScanned
propertynumber

Entries the scan walked. Reported because it is the cost of the call, and nothing bounds it below the draw’s participant count.

eventId
propertystring
slot
propertystring | null

The entropy slot the registration is stored under, or null when this identity has none. The slot is also the draw ticket.

interface EncodedCallSource

The one call-encoding method the builder needs; PAPI transactions have it.

Methods

getEncodedData
getEncodedData(): Promise<Uint8Array<ArrayBufferLike>>

interface FeeEstimable

A built transaction whose fee can be estimated, as every PAPI transaction can.

Methods

getEstimatedFees
getEstimatedFees(from: string, options: { customSignedExtensions: Record<string, { value: unknown }>; nonce: number }): Promise<bigint>

interface FinalizedBlockSource

The one raw-client method the pinned reads use. Structural, so PolkadotClient fits.

Methods

getFinalizedBlock
getFinalizedBlock(): Promise<{ hash: string; number: number }>

interface FinalizedSnapshot

The finalized block every read in a result was pinned to.

Properties

blockHash
propertystring
blockNumber
propertynumber

interface GameChain

Structural, so a test double satisfies it. Separate from AirdropChain because a caller reading the game needs neither it nor the personhood entries; PrizeStatusChain is the intersection.

Matched by hand against the paseo descriptors on 2026-08-20:

Game.GameIndex: StorageDescriptor<[], number, false, never> Game.Game: StorageDescriptor<[], GameInfo, true, never> Game.GameSchedules: StorageDescriptor<[], Array<GameSchedule>, false, never> Game.StoredPhaseDurations: StorageDescriptor<[], PhaseDurationValues, true, never> Game.DefaultPhaseDurations: PlainDescriptor<PhaseDurationValues>

Extends: PinnedChain

Properties

individuality
property{ constants: { Game: { DefaultPhaseDurations: unknown } }; query: { Game: { Game: { getValue: unknown }; GameIndex: { getValue: unknown }; GameSchedules: { getValue: unknown }; StoredPhaseDurations: { getValue: unknown } } } }

interface GamePhaseDurations

The phase durations in force, from Game.StoredPhaseDurations when governance has set one and Game.DefaultPhaseDurations otherwise. All in seconds.

Properties

playerProcess
propertynumber
postShuffleMargin
propertynumber

Slack between the shuffle deadline and the play time.

registration
propertynumber
reporting
propertynumber
shuffle
propertynumber

interface GamePlayersChain

The registration entry, needed only when ReadCurrentGameOptions.players is given. Kept out of GameChain so a caller that never asks about a player, and every existing test double, keeps satisfying the narrower type.

Game.Players: StorageDescriptor<[Key: AccountOrPerson], { registered: boolean }, true, never>

Properties

individuality
property{ query: { Game: { Players: { getValue: (key: PlayerKey, options: ReadAt) => Promise<{ registered: boolean } | undefined> } } } }

interface GameScheduledAirdrop

One prize draw a schedule will set up, with its timing relative to play time.

Properties

claimWindow
propertynumber

Seconds the claim window stays open after the draw.

drawOffset
propertynumber

Seconds after the play time at which winners are drawn.

prize
propertyAirdropPrize

interface GameSchedulePreview

A game not created yet. The chain keeps Game.GameSchedules chronological — schedule_games rejects anything overlapping or preceding the last one, and remove_scheduled_game binary-searches it — so the first entry is the next game.

Properties

airdrops
propertyGameScheduledAirdrop[]

The draws this schedule asks for — an upper bound, since scheduling can fail per draw. For showing a prize before the game exists, never for deriving event ids.

gamePlayTime
propertynumber

Unix seconds. The only time the chain stores for a scheduled game.

maxGroupSize
propertynumber
rounds
propertynumber
timeline
propertyGameTimeline

Boundaries derived from the durations at the same block — a projection. Governance can move them before this game is created, shifting everything here except gamePlayTime. Once it exists, read its stored boundaries.

interface GameSignUpRequirement

What the chain will accept from this player, at one pinned block. Index and draw count must come from the same block: an id built from one game’s index and another’s count addresses a draw that does not exist.

Properties

airdropsScheduled
propertynumber

Game.airdrops_scheduled. The airdrops list must have exactly this many entries.

at
propertyFinalizedSnapshot
blockers
propertySignUpBlocker[]

Empty exactly when both canSignUp and canEnterDraws hold.

canEnterDraws
propertyboolean

Never true when canSignUp is false: the draws ride on the sign-up.

canSignUp
propertyboolean

Whether the chain would accept a sign-up, with or without draw entry. Not whether this package can build one: an Alias registrant needs sign_up_with_alias, which cannot be assembled, and still reads true.

eventIds
propertystring[]

Ids for airdrop indices 0 to airdropsScheduled - 1, in supply order.

gameIndex
propertynumber | null

null between games. Not the lastGameIndex a late claim uses.

phase
propertyGamePhase | null
registrationEnds
propertynumber | null

Unix seconds. null between games.

variant
propertyAirdropVrfVariant | null

null between games, where recognition is known but there is nothing to enter.

interface GameTimeline

A game’s phase boundaries, Unix seconds. Mirrors the runtime’s GameTimes trait (pallets/game/src/types.rs:525), and is only ever a projection, for a game that does not exist yet.

Properties

gamePlayTime
propertynumber
playerProcessEnds
propertynumber

End of the whole game. The chain schedules nothing else before it.

registrationEnds
propertynumber
registrationStarts
propertynumber

Earliest the game may open for sign-ups.

reportingEnds
propertynumber
shuffleDeadline
propertynumber

Miss this and the game is cancelled rather than played.

interface GroupMember

One occupied seat, resolved to the player the chain keys it by.

Properties

index
propertynumber
player
propertyPlayerKey

interface GroupMembersResult

Properties

at
propertyFinalizedSnapshot
members
propertyGroupMember[]

Every occupied seat, the player at ownIndex included, ascending by index.

interface GroupSeat

One position of a group, with whether a player was shuffled into it.

Properties

index
propertynumber
occupied
propertyboolean

interface IndividualityChain

The chain surface this read needs — deliberately structural, not a pinned descriptor.

Anything exposing these six entries satisfies it: a real ChainClient<{ individuality: … }> from getChainAPI, a future People Lite deployment, or a hand-rolled test double. The same approach as PeopleUsernameQueryApi in @parity/product-sdk’s identity/dotns.ts, and for the same reason — the SDK should not pin a genesis hash to read a username.

Written with method shorthand on purpose: the parameter bivariance that gives is what lets the real PAPI signatures satisfy the loosened key types below.

Fidelity is checked at compile time, from the umbrella package. packages/sdk/src/individuality/contract.test.ts asserts that a real getChainAPI client still satisfies this type, so a descriptor regeneration that changes an entry fails pnpm typecheck.

The guard has to live there rather than here, which is worth recording because it is not obvious. Inside this package the same assertion is vacuous: it passes even against a contract demanding a pallet the chain does not have, because the descriptor types do not fully resolve through this package’s dependency graph. From packages/sdk, which depends on both chain-client and this package, the identical assertion correctly rejects a bogus contract. Both halves were verified before choosing the placement.

The entries were also matched by hand on 2026-08-17 against descriptors/chains/paseo-individuality/generated/dist/paseo_individuality.d.ts:

UsernameOwnerOf: StorageDescriptor<[Key: Uint8Array], SS58String, true, never> Participants: key AnonymousEnum<{ Account: SS58String; Person: SizedHex<32> }> PersonhoodThreshold: StorageDescriptor<[], number, false, never> AbsenceGraceRatio: StorageDescriptor<[], SizedHex<2>, false, never> AccountToAlias: value { revision, ring, ca: { alias, context } } LitePeople: value { ring_vrf_key, method } (presence is the signal)

A descriptor regeneration that changes any of them now fails pnpm typecheck rather than passing silently.

Properties

individuality
property{ query: { People: { AccountToAlias: { getValue: unknown } }; PeopleLite: { AccountToAlias: { getValue: unknown }; LitePeople: { getValue: unknown } }; Resources: { UsernameOwnerOf: { getValue: unknown } }; Score: { AbsenceGraceRatio: { getValue: unknown }; Participants: { getValue: unknown }; PersonhoodThreshold: { getValue: unknown } } } }
raw
property{ individuality: { getFinalizedBlock: unknown } }

interface LegacySuffixChain

The network suffix before #20. Previewnet only, and gone on its next upgrade.

Score.Suffix: PlainDescriptor<Uint8Array>

Properties

individuality
property{ constants: { Score: { Suffix: unknown } } }

interface LiteAliasBindChain

What building the bind leg needs from a chain: the call codec, the current best block for valid_at_block, and the three values the proof implicitly signs — metadata (the extension pipeline), the runtime version and the genesis hash. Matched by hand against the previewnet descriptors on 2026-08-31.

Properties

individuality
property{ apis: { Metadata: { metadata_at_version: unknown } }; constants: { System: { Version: unknown } }; query: { System: { Number: { getValue: unknown } } }; tx: { PeopleLite: { set_alias_account: unknown } } }
raw
property{ individuality: { getChainSpecData: unknown } }

interface LiteAliasBindTx

What buildLiteAliasBindTx returns.

Properties

ringIndex
propertynumber

Which ring the proof was minted against, for logging.

ringRevision
propertynumber

That ring’s revision at minting time, for logging.

transaction
propertyUint8Array

The finished extrinsic. Submit it raw — client.submit, or anything that broadcasts bytes; there is nothing left to sign.

validAtBlock
propertynumber

The valid_at_block the call carries: the best block at build time.

interface LiteSignUpChain

The lite sign-up call, plus the reads that decide whether it can dispatch. Composed with GameChain and SignUpChain, which supply the game and the account-path reads. Matched by hand against the paseo and previewnet descriptors on 2026-09-02 (devnet predates the surface):

PeopleLite.AccountToAlias: StorageDescriptor<[Key: SS58String], { revision, ring, ca }, true, never> PeopleLite.LitePeople: StorageDescriptor<[Key: SS58String], LitePersonInfo, true, never> Game.LiteInvites: StorageDescriptor<[Key: SizedHex<32>], SS58String, true, never> Members.Members: StorageDescriptor<[SizedHex<32>, SizedHex<32>], MemberStatus, true, never> Members.Root: StorageDescriptor<[SizedHex<32>, number], { root, revision, intermediate }, true, never> Game.StmtAccountToAlias: StorageDescriptor<[Key: SS58String], SizedHex<32>, true, never>

Properties

individuality
property{ query: { Game: { LiteInvites: { getValue: unknown }; StmtAccountToAlias: { getValue: unknown } }; Members: { Members: { getValue: unknown }; Root: { getValue: unknown } }; PeopleLite: { AccountToAlias: { getValue: unknown }; LitePeople: { getValue: unknown } } }; tx: { Game: { sign_up_with_account_lite_invite: unknown } } }

interface LiteSignUpRequirement

GameSignUpRequirement with the wider blocker union: what the chain will accept from this account as a lite sign-up, at one pinned block. canSignUp and canEnterDraws answer for Game.sign_up_with_account_lite_invite — the account read’s answers AND’ed with “no lite blocker”, since every lite arm stops the whole extrinsic.

Extends: Omit<GameSignUpRequirement, "blockers">

Properties

blockers
propertyLiteSignUpBlocker[]

Empty exactly when both canSignUp and canEnterDraws hold.

interface LookupUsernameOptions

Options for lookupUsername.

Extends: ConsumersReadAt

Properties

account
propertystring

The account to read, SS58 encoded. This is the storage key.

interface MintAccountAirdropVrfsOptions

Options for mintAccountAirdropVrfs.

Properties

eventIds
propertystring[]

In airdrop-index order: entry i is checked against airdrop index i.

publicKey
propertyUint8Array

The signing account’s sr25519 key, 32 bytes.

signal
propertyoptionalAbortSignal

Checked between draws only. AirdropVrfSigner takes no signal, so a signature already being prompted for cannot be cancelled, unlike the reads.

interface NetworkSuffixChain

The network suffix since individuality-community #20. Root can move it between blocks, so it is read at a pinned one. The pallet is testnet-only upstream, so production has neither this nor LegacySuffixChain and the caller says.

NetworkSuffix.NetworkSuffix: StorageDescriptor<[], Uint8Array, false, never>

Extends: PinnedChain

Properties

individuality
property{ query: { NetworkSuffix: { NetworkSuffix: { getValue: unknown } } } }

interface PapiIndividualityChain

What fromPapi returns, with the typed API preserved.

Properties

individuality
propertyApi
raw
property{ individuality: Client }

interface ParticipantWatchChain

Properties

individuality
property{ query: { Score: { Participants: { watchValue: (key: PlayerKey, options: WatchAt) => WatchedValue<RawParticipant | undefined> } } } }

interface PersonhoodInputs

Everything PersonhoodState is derived from, resolved for one account at one block.

Named inputs rather than a snapshot on purpose: FinalizedSnapshot is the block this was read at, and two exported types called Snapshot meaning different things is a trap.

Properties

isLitePerson
propertyboolean
participant
propertyPersonhoodParticipant | null
personhoodThreshold
propertynumber

Score.PersonhoodThreshold. This is a u8 on chain, but PAPI types both u8 and u32 as number, so a width mistake here typechecks and passes tests. Verified against the metadata blob on 2026-08-16.

policy
propertyAbsenceGracePolicy

interface PersonhoodMetrics

The numbers behind a resolved state, carried alongside it.

The state union answers “what is this person’s standing”; these answer “by how much”, which a progress bar needs in every state rather than only in the two whose variants happen to carry payload. All five come from the same pinned snapshot as the state, so no extra read pays for them.

misses here is not Caution.misses. This is what the window holds now. Caution.misses is a projection — what it would hold after one more absence — because that is what the grace policy is evaluated against. A UI showing “you have missed 2 of the last 8” wants this one.

score and misses are null when the account has no participant record: there is no score to report and no attendance history to count. The threshold and the policy are unkeyed storage values, so they are always present.

Properties

allowedMisses
propertynumber

Score.AbsenceGraceRatio: how many of window may be absences.

misses
propertynumber | null

Absences inside the current window, or null with no record.

personhoodThreshold
propertynumber

Score.PersonhoodThreshold, the score at which personhood is reached.

score
propertynumber | null
window
propertynumber

Score.AbsenceGraceRatio: how many recent games the policy looks at.

interface PersonhoodParticipant

A participant’s game record, as read from Score.Participants and decoded.

attendanceHistory is a rolling byte: bit 0 is the most recent game, 1 means attended and 0 means absent.

Properties

attendanceHistory
propertynumber
hasEverReachedPersonhood
propertyboolean

Stays true once personhood was reached, after the score falls back below the threshold.

lastAttendedGame
propertynumber | null
reachedPersonhood
propertyboolean
recognition
property"Suspended" | "ExternallyRecognized" | "NotRecognized" | "Recognized"
score
propertynumber
streak
property{ count: number; tag: "Attended" | "Absent" }

interface PlayerIndicesResult

Properties

at
propertyFinalizedSnapshot
indices
propertynumber[] | null

One index per round, or null when the player holds no seat in the roster.

interface PlayerRecord

A player record in Game.Players, present from the first sign-up until archival.

Properties

registered
propertyboolean

Signed up for the current game.

interface PlayerWatchChain

Properties

individuality
property{ query: { Game: { Players: { watchValue: (key: PlayerKey, options: WatchAt) => WatchedValue<{ registered: boolean } | undefined> } } } }

interface RawAccountAlias

AccountToAlias, narrowed to the contextual alias the read keys on.

Properties

ca
property{ alias: string }

interface RawActiveEvent

The raw Airdrop.Events value, narrowed to what the domain reads.

Extra fields on the actual value are accepted — this is a structural type, not an exhaustive record of the storage entry.

Properties

id
propertystring
info
propertyRawAirdropEventInfo
source
propertyoptionalstring
status
propertyRawAirdropStatus

interface RawAirdropEventInfo

The raw EventInfo. Every timestamp is a u64 of Unix seconds.

Properties

draw_time
propertybigint
end_time
propertybigint
prize
propertyRawAirdropPrize
registration_starts
propertybigint

interface RawAirdropPrize

The raw AirdropPrize, narrowed to the fields the domain carries.

Properties

asset_amount
propertybigint
asset_id
propertyAirdropAssetId
max_winners
propertynumber
winner_cap
propertynumber

interface RawAirdropStatus

The raw Status enum. The payload is loose on purpose: enumerating eight variants’ field sets would duplicate the descriptor and catch nothing the availability rules above miss.

Properties

type
propertystring
value
propertyoptional{ claimed?: number; effective_winners?: number; total_participants?: number }

interface RawConsumerInfo

The raw Resources.Consumers value, narrowed to the fields we read.

The chain also sends identifier_key, an opaque communication key with no bearing on names. Extra fields on the actual value are accepted; this is a structural type, not an exhaustive record of the storage entry.

Properties

credibility
property{ type: string; value?: { alias: string; demoted: boolean; last_update: bigint } }

PAPI’s encoding of the pallet’s Credibility enum: variant name in type, payload in value. Either Lite, which has no payload, or Person.

full_username
propertyoptionalUint8Array<ArrayBufferLike>
lite_username
propertyUint8Array

interface RawGameAirdrop

One raw GameAirdrop from a schedule.

Properties

claim_window
propertynumber
draw_offset
propertynumber
prize
propertyRawAirdropPrize

interface RawGameInfo

The raw Game.Game value, narrowed to the fields the domain carries.

Properties

airdrops_scheduled
propertynumber
game_date
propertynumber
index
propertynumber
max_group_size
propertynumber
pending_attendance
propertynumber
registration_ends
propertynumber
report_ends
propertynumber
rounds
propertynumber
shuffle_deadline
propertynumber
state
propertyRawGameState

interface RawGameSchedule

One raw GameSchedule from the Game.GameSchedules list.

Properties

airdrops
propertyRawGameAirdrop[]
game_play_time
propertynumber
max_group_size
propertynumber
rounds
propertynumber

interface RawGameState

The raw GameState enum. Only the player count is read from its payload.

Properties

type
propertystring
value
propertyoptionalunknown

interface RawLiteAliasBinding

PeopleLite.AccountToAlias, the alias binding the signed leg dispatches on. ca.context is read as well as ca.alias: a binding in any context other than the chain’s score context does not satisfy the game’s origin check.

Properties

ca
property{ alias: string; context: string }

The contextual alias itself, both halves as 0x hex.

revision
propertynumber

Ring revision the binding was proven at.

ring
propertynumber

Ring the alias belongs to.

interface RawLiteRingMembership

One Members.Members entry, narrowed to the discriminant. Only Included means the key sits in a built ring and a proof against it will verify.

Properties

type
propertystring

interface RawParticipant

The raw Score.Participants value, narrowed to the fields the domain reads.

The chain also sends credit and cashed_out. Both are deliberately absent: they are game-economy fields with no bearing on membership. Extra fields on the actual value are accepted — this is a structural type, not an exhaustive record of the storage entry.

Properties

attendance_history
propertynumber
has_ever_reached_personhood
propertyboolean
last_attended_game
propertyoptionalnumber
reached_personhood
propertyboolean
recognition
propertyRawRecognition
score
propertynumber
streak
propertyRawStreak

interface RawPhaseDurations

The raw PhaseDurationValues, from storage or from the runtime constant.

Properties

player_process
propertynumber
post_shuffle_margin
propertynumber
registration
propertynumber
reporting
propertynumber
shuffle
propertynumber

interface RawRecognition

The raw recognition enum as PAPI decodes it: Enum<{ ExternallyRecognized; NotRecognized; Suspended: bigint; Recognized: bigint }>.

The payload is a revision id on two of the four variants and absent on the other two. The domain does not carry it.

Properties

type
propertystring
value
propertyoptionalbigint

interface RawStreak

The raw streak enum as PAPI decodes it: Enum<{ Attended: u32; Absent: u32 }>.

Properties

type
propertystring
value
propertynumber

interface ReadAirdropDrawOptions

Options for readAirdropDraw.

Properties

eventId
propertystring

The 32-byte event id, 0x-prefixed. Derive it with gameAirdropEventId or peopleAirdropsEventId — no storage entry lists it.

registrant
propertyoptionalAirdropRegistrant

Whose outcome to look up. Omit it to read the draw itself without asking about anyone, which returns outcome: { tag: "Unchecked" } rather than a false that would read as “did not win”.

signal
propertyoptionalAbortSignal

Forwarded into every underlying pull, so an aborted caller stops the whole batch. No deadline is applied here — that belongs to the caller.

interface ReadClaimEligibilityOptions

Options for readClaimEligibility.

Extends: ClaimTarget

Properties

now
propertyoptionalnumber

Unix seconds; defaults to the device clock. See ClaimInputs.now.

signal
propertyoptionalAbortSignal

interface ReadCommunicationIdentifierOptions

Options for readCommunicationIdentifier.

Properties

account
propertystring

SS58. Only accounts register one, an alias never does.

signal
propertyoptionalAbortSignal

interface ReadCreditCandidatesOptions

Options for readCreditCandidates.

Properties

attestee
propertyPlayerKey
signal
propertyoptionalAbortSignal

interface ReadCurrentGameOptions

Options for readCurrentGame.

Properties

players
propertyoptionalreadonly AirdropRegistrant[]

Whose registration to read, at the same block as the game. One person is keyed twice on chain — by account and, once recognized, by alias — so pass every key the caller holds; any hit answers Registered. Requires a chain that also satisfies GamePlayersChain.

signal
propertyoptionalAbortSignal

Forwarded into every underlying pull, so an aborted caller stops the whole batch. No deadline is applied here — that belongs to the caller.

interface ReadGameAirdropEventIdsOptions

Options for readGameAirdropEventIds.

Properties

airdropsScheduled
propertynumber

Game.Game.airdrops_scheduled, readable only while the game is current — capture it then, because a past game’s count is unrecoverable. Probing ids upward cannot tell a cleaned-up draw from one never scheduled.

gameIndex
propertynumber

The game the draws belong to.

interface ReadGameSignUpRequirementOptions

Options for readGameSignUpRequirement.

Properties

keyType
propertyoptional"sr25519" | "ed25519" | "ecdsa"

Only "sr25519" can mint Account VRFs, and no chain read reveals the scheme. Pass it for a NotSr25519 blocker, omit it and the check is yours.

now
propertyoptionalnumber

Unix seconds; defaults to the device clock.

registrant
propertyAirdropRegistrant

Keys both reads, and must be the identity that will sign.

signal
propertyoptionalAbortSignal

interface ReadGroupMembersOptions

Options for readGroupMembers.

Properties

maxGroupSize
propertynumber
ownIndex
propertynumber

The index of the player whose group to read, in that round.

playerCount
propertynumber

From CurrentGame.playerCount.

round
propertynumber
signal
propertyoptionalAbortSignal

interface ReadLiteSignUpRequirementOptions

Options for readLiteSignUpRequirement.

Properties

account
propertystring

The account the sign-up will be signed by and dispatched for — usually the caller’s playing product account. Keys the alias-binding read here and the registration reads of the account path.

keyType
propertyoptional"sr25519" | "ed25519" | "ecdsa"

Forwarded to the account read’s draw-entry check.

liteMemberKey
propertyoptionalUint8Array<ArrayBufferLike>

The 32-byte lite member key (RFC-0022 index 1, from the host’s registerRingVrfKey against the lite people ring). Pass it for a NotLiteMember blocker when the key is not an Included ring member; omit it and the membership check is yours.

now
propertyoptionalnumber

Unix seconds; defaults to the device clock.

signal
propertyoptionalAbortSignal
tld
propertyoptionalstring

Required when the chain publishes no suffix, and wins when it does.

interface ReadPlayerIndicesOptions

Options for readPlayerIndices.

Properties

player
propertyPlayerKey
signal
propertyoptionalAbortSignal

interface ReadPrizeStatusOptions

Options for readPrizeStatus.

Properties

game
propertyoptionalCapturedGame

A game the caller already knows, for claiming after it ended. Supplying it skips the game read — four fewer reads, so game on the result is null even if this index is the running one.

registrant
propertyoptionalAirdropRegistrant

Whose outcome to report. Omit to read the draws without asking about anyone, which leaves every outcome Unchecked.

signal
propertyoptionalAbortSignal

interface ReadRegistrationEligibilityOptions

Options for readRegistrationEligibility.

Properties

registrant
property{ accountAddress: string; tag: "Account" }

The account that would sign register; the pallet reads no other key.

signal
propertyoptionalAbortSignal

interface ReadScoreContextOptions

Options for readScoreContext.

Properties

signal
propertyoptionalAbortSignal
tld
propertyoptionalstring

Required when the chain publishes no suffix, and wins when it does.

interface ReadSignUpFundsOptions

Options for readSignUpFunds.

Properties

account
propertystring

SS58. The account that will sign and hold the deposit.

signal
propertyoptionalAbortSignal
tx
propertyoptionalFeeEstimable

The sign-up transaction as built, for example by signUpWithAccountTx. Omit it and estimatedFee is null. Placeholder VRFs of the right width cost the same as real ones, so the funds can be checked before any is minted.

interface RegisterChain

The Score.register call, typed structurally so the package needs no descriptor dependency. Matched by hand against the previewnet descriptors on 2026-08-31:

Score.register: TxDescriptor<{ key?: [SizedHex<32>, SizedHex<64>] }>

Properties

individuality
property{ tx: { Score: { register: unknown } } }

interface RegisterPersonhoodOptions

Options for registerPersonhoodTx.

Properties

memberKey
propertyUint8Array

The full member key, 32 bytes: registerRingVrfKey(Index(0), peopleRing) from the personhood product’s host session. Opaque here — this package never mints it.

proofOfOwnership
propertyUint8Array

A plain Bandersnatch signature by that key over registerMessage(account), 64 bytes: ringVrfSign from the same session. account must be the account that will sign the transaction, or the chain answers InvalidProofOfOwnership.

interface RegistrationEligibility

A participant’s standing against the registration guards, at one pinned block.

Properties

at
propertyFinalizedSnapshot
participant
propertyPersonhoodParticipant | null

null for an account Score has never seen.

personhoodThreshold
propertynumber

Score.PersonhoodThreshold at the same block. A u8, but u32 on devnet.

readyToRegister
propertyboolean

readyToRegister over the two fields above.

interface RegistrationEligibilityChain

The two reads readRegistrationEligibility folds. Matched by hand against the previewnet descriptors on 2026-08-31:

Score.Participants: StorageDescriptor<[Key: AccountOrPerson], Participant, true, never> Score.PersonhoodThreshold: StorageDescriptor<[], number, false, never>

PersonhoodThreshold is a storage item, not a constant: the runtime recalculates it from a population-tiered schedule at the start of each report session, so it can move under a participant mid-season — which is why both reads are pinned to one block.

Extends: PinnedChain

Properties

individuality
property{ query: { Score: { Participants: { getValue: (key: PlayerKey, options: ReadAt) => Promise<RawParticipant | undefined> }; PersonhoodThreshold: { getValue: unknown } } } }

interface ReportChain

Structural, so a test double satisfies it. Matched by hand against the paseo descriptors on 2026-09-25:

Game.report: TxDescriptor<{ full_report: Array<Array<Enum<{ Person, NotPerson }>>> }> Game.offboard: TxDescriptor<undefined>

Properties

individuality
property{ tx: { Game: { offboard: unknown; report: unknown } } }

interface ReportOptions

Options for reportTx.

Properties

fullReport
propertyreadonly readonly ReportVote[][]

One entry per round of the game, exactly rounds of them. Each holds a vote per co-player in the group of the reporter that round, in group order, which is ascending player index, with the reporter left out. A round that does not match the real group fails with Game.InvalidReport.

interface RingLocation

Where a ring lives: a chain, and a junction path addressing the ring on it.

Structurally compatible with the host’s RingLocation, and declared here rather than imported so this package needs no dependency on @parity/product-sdk-host. Same approach as RingVRFProof.

Properties

chainId
property`0x${string}`

Genesis hash of the chain hosting the ring.

junctions
property{ tag: "PalletInstance"; value: number } | { tag: "CollectionId"; value: `0x${string}` }[]

Path addressing the ring within the chain.

interface RingVRFProof

A ring VRF proof and the values the chain needs to verify it.

Structurally compatible with the host’s RingVRFProof, and declared here rather than imported so this package needs no dependency on @parity/product-sdk-host. Same approach as IndividualityChain, and the umbrella package asserts the two stay compatible at compile time.

Properties

contextualAlias
property{ alias: Uint8Array; context: Uint8Array }

The alias the proof commits to, and the 32-byte context it is bound to.

proof
propertyUint8Array

Raw ring VRF proof bytes.

ringIndex
propertynumber

Index of the ring the proof was generated against.

ringRevision
propertynumber

Revision of that ring at generation time.

interface RosterChain

Structural, so a test double satisfies it. Matched by hand against the paseo descriptors on 2026-09-25:

Game.PlayerToIndex: StorageDescriptor<[Key: AccountOrPerson], Array<number>, true, never> Game.IndexToPlayer: StorageDescriptor<[Key: [number, number]], AccountOrPerson, true, never> Game.CommunicationIdentifiers: StorageDescriptor<[Key: SS58String], SizedHex<65>, true, never>

Extends: PinnedChain

Properties

individuality
property{ query: { Game: { CommunicationIdentifiers: { getValue: unknown }; IndexToPlayer: { getValues: (keys: [[number, number]][], options: ReadAt) => Promise<PlayerKey | undefined[]> }; PlayerToIndex: { getValue: (key: PlayerKey, options: ReadAt) => Promise<number[] | undefined> } } } }

interface ScoreContextChain

The published context every score proof must be minted in.

Separate from the suffix contracts because merging them needs optional members, which constrain nothing structurally and blind the umbrella guard.

Matched by hand against the previewnet descriptors on 2026-08-31:

Score.score_context: PlainDescriptor<SizedHex<32>>

Properties

individuality
property{ constants: { Score: { score_context: unknown } } }

interface SignUpChain

The sign-up call, plus the reads that decide what it may carry. Composed with GameChain, which supplies the game. Matched by hand against the paseo descriptors on 2026-08-21.

Extends: PinnedChain

Properties

individuality
property{ constants: { Game: { airdrop_event_id_base: unknown } }; query: { Game: { Players: { getValue: (key: PlayerKey, options: ReadAt) => Promise<{ registered: boolean } | undefined> } }; Score: { Participants: { getValue: (key: PlayerKey, options: ReadAt) => Promise<RawParticipant | undefined> } } }; tx: { Game: { sign_up_with_account: unknown } } }

interface SignUpFunds

The parts of what a sign-up costs, in the smallest unit of the native token.

How much headroom to demand on top is product policy, so no total is given.

Properties

at
propertyFinalizedSnapshot
decimals
propertynumber | null

null when the chain spec does not publish it.

deposit
propertybigint

Held from a new or archived player at sign-up. A returning player owes none, and an existing deposit keeps the amount it was created with.

estimatedFee
propertybigint | null

Charged up front and refunded on success, so the account needs it to start with. Nothing under withScoreParticipant. PAPI estimates it at the latest finalized block, which can be newer than at.

free
propertybigint

The raw free balance, which is more than a sign-up can spend.

The fee cannot come out of frozen funds, and neither the fee nor the deposit may take the account below the existential deposit. So a check that free covers deposit + estimatedFee can pass while the sign-up fails.

symbol
propertystring | null

interface SignUpWithAccountOptions

Options for signUpWithAccountTx.

Properties

airdrops
propertyoptionalAccountVrfSignature[]

Omit to enter no draw. Length must equal airdropsScheduled.

airdropsScheduled
propertyoptionalnumber

From GameSignUpRequirement, checked against airdrops when both are given. A mismatch fails the whole sign-up on chain with the deposit taken, and is reachable by re-reading the requirement between minting and building.

identifierKey
propertyUint8Array

CommunicationIdentifier, exactly 65 bytes. Stored against the account and never interpreted by the chain; it is how co-players reach each other.

interface SignUpWithLiteInviteOptions

Options for signUpWithLiteInviteTx.

Properties

account
propertystring

The account to sign up — a call argument here, unlike the account sign-up where the signer implies it. It must also be the account that signs the transaction: the extension resolves the alias from the signer, and LiteInvites is checked against this argument.

airdrops
propertyoptionalAccountVrfSignature[]

Omit to enter no draw. Length must equal airdropsScheduled.

airdropsScheduled
propertyoptionalnumber

From LiteSignUpRequirement, checked against airdrops when both are given — the same guard as the account sign-up, for the same reason.

identifierKey
propertyUint8Array

CommunicationIdentifier, exactly 65 bytes. Rewritten on every sign-up, so pass the key whose private half the playing product holds now.

interface VrfTranscript

Properties

items
propertyVrfTranscriptItem[]

domain then signer. The order is part of the message.

label
propertyUint8Array

interface VrfTranscriptItem

Merlin append_message(label, value), as the host’s signVrf takes it.

Properties

label
propertyUint8Array
value
propertyUint8Array

interface WatchAt

Options every watch takes: only the best block, so a change shows before finality.

Properties

at
property"best"

interface WatchedBlock

The block a watched value was read at, which is a best block, not a finalized one.

Properties

blockHash
propertystring
blockNumber
propertynumber

interface WatchedValue

A PAPI watchValue observable, narrowed to the one method a watch calls.

Methods

subscribe
subscribe(observer: { error: (error: unknown) => void; next: (emission: { block: { hash: string; number: number }; value: Value }) => void }): { unsubscribe: unknown }

interface WatchPlayerOptions

Options for watchPlayer and watchParticipant.

Properties

player
propertyPlayerKey

Type Aliases

type AirdropOutcome

Whether a registrant won. Unchecked exists so “we did not ask” cannot be mistaken for “did not win” — a false there would be a claim the read never made.

type AirdropOutcome = { tag: "Unchecked" } | { tag: "NotWon" } | { tag: "Won"; ticket: string }

type AirdropPhase

The phase a product renders. Gone is not a chain status but the row’s absence — the steady state for every past draw. It is not proof a draw happened: an id that was never scheduled answers identically, and the chain cannot tell them apart.

type AirdropPhase = "Upcoming" | "Registering" | "Drawing" | "Claiming" | "Settling" | "Gone"

type AirdropRegistrant

Which identity entered a draw. Not the player’s choice on the game path: the chain picks Alias for a recognized person and Account for everyone else.

type AirdropRegistrant = { accountAddress: string; tag: "Account" } | { alias: string; tag: "Alias" }

type AirdropStatusTag

The chain’s own Status, kept alongside AirdropPhase because the collapse is lossy: a product renders one spinner for AwaitingEntropy and DrawWinners, but someone debugging a stalled draw needs to know which.

type AirdropStatusTag = "Scheduled" | "Registering" | "AwaitingEntropy" | "DrawWinners" | "Claiming" | "ClearingRegistrations" | "ClearingWinners" | "Finalizing"

type AirdropVrfVariant

Which variant the chain demands of this player. Read it, never choose it.

type AirdropVrfVariant = "Account" | "Alias"

type AsPersonInfo

Which person origin the transaction should run under.

Only the alias variants are here. AsPersonalIdentityWithProof needs a raw sr25519 signature over the implication hash, which no host call currently produces, and AsPersonalIdentityWithAccount has no known consumer.

type AsPersonInfo = { tag: "AliasWithAccount" } | { createProof: CreateRingVRFProof; tag: "AliasWithProof" } | { createProof: CreateRingVRFProof; tag: "AliasWithAccountRevised" }

type ClaimBlocker

Why a prize cannot be claimed. Several can hold at once, so ClaimEligibility carries a list rather than the first one found — a UI that says “not recognized” while the window has also closed sends the player to fix the wrong thing.

type ClaimBlocker = { tag: "NotAParticipant" } | { tag: "NotRecognized" } | { tag: "Suspended" } | { lastAttendedGame: number | null; tag: "DidNotAttendThisGame" } | { phase: AirdropPhase; tag: "DrawNotClaiming" } | { endTime: number; tag: "ClaimWindowClosed" } | { tag: "PrizeAssetDisabled" } | { tag: "NoPrize" } | { tag: "OutcomeUnchecked" }

type ClaimOutcome

Whether a submitted claim reached the chain, re-read rather than watched. A successful claim removes the Winners row, so the absence of a ticket that was there before is the confirmation — recoverable after a reload, which a subscription is not.

type ClaimOutcome = { at: FinalizedSnapshot; tag: "Claimed" } | { at: FinalizedSnapshot; tag: "Pending"; ticket: string } | { at: FinalizedSnapshot; phase: AirdropPhase; tag: "Unknown" }

type ContextSuffix

The RFC-0024 context-suffix selector: a plain index, or 32 raw bytes. The same selector RFC-0022 uses for a product account, under a name that reads right at a proof-context call site.

type ContextSuffix = DerivationIndex

type CreateRingVRFProof

Produce a ring VRF proof over message.

Wire this to SignerManager.createRingVRFProof(keyHandle, context, location, message), or to any other call that returns a proof for the context the chain expects.

The message is computed by the wrapping signer and must not be chosen by the caller. It is blake2-256 of the call implication, which depends on the nonce, the era, the tip and every other extension after the one being filled. A proof over anything else fails on chain as a bad proof.

The context is taken from the returned proof, not from the request, so whichever call mints the proof decides it.

type CreateRingVRFProof = (message: Uint8Array) => Promise<RingVRFProof>

type CreditCandidatesChain

RosterChain plus the game, which readCreditCandidates reads at the same block.

type CreditCandidatesChain = RosterChain & { individuality: { query: { Game: { Game: { getValue: unknown } } } } }

type CurrentGameResult

type CurrentGameResult = { at: FinalizedSnapshot; durations: GamePhaseDurations; game: CurrentGame; registration: PlayerRegistration; tag: "Running"; upcoming: GameSchedulePreview[] } | { at: FinalizedSnapshot; durations: GamePhaseDurations; lastGameIndex: number | null; tag: "BetweenGames"; upcoming: GameSchedulePreview[] }

type GamePhase

The phase a game is in, named as the chain’s GameState variant. Their payloads are not decoded — offchain-worker cursors and sub-step markers, not anything a product renders; pendingAttendance is the progress signal that is. The one exception is the player count, see CurrentGame.playerCount.

type GamePhase = "Registration" | "Shuffle" | "Reporting" | "PlayerProcess" | "Cancelling"

type LiteAliasInfo

Which lite-person origin the transaction should run under.

AsLitePerson, the fourth variant on chain, is deliberately absent: it authenticates the canonical lite account itself, which stays in host custody, so no product-side signer can ever be that origin.

type LiteAliasInfo = { tag: "AliasWithAccount" } | { createProof: CreateRingVRFProof; tag: "AliasWithProof" } | { createProof: CreateRingVRFProof; tag: "AliasWithAccountRevised" }

type LiteSignUpBlocker

Why the free lite sign-up (Game.sign_up_with_account_lite_invite) cannot go ahead: every account-path blocker, plus the lite-only gates.

A parallel union rather than new arms on SignUpBlocker, on purpose: widening that union would break every existing exhaustive consumer of the account read the moment this package is upgraded, for a path they never call. readGameSignUpRequirement keeps returning the narrow union; readLiteSignUpRequirement returns this one, and a consumer of both narrows once.

Unlike the account read’s draw-only arms, every lite arm blocks the sign-up itself. AnotherAccountInvited and AccountIsALitePerson are permanent for the account they name; ContextNotProductDerived is about the environment, not the account.

type LiteSignUpBlocker = SignUpBlocker | { tag: "AliasNotBound" } | { tag: "AliasBoundElsewhere" } | { invited: string; tag: "AnotherAccountInvited" } | { tag: "AccountIsALitePerson" } | { tag: "NotLiteMember" } | { tag: "ContextNotProductDerived" } | { tag: "AlreadyPlaying" } | { tag: "AccountIsAStatementAccount" } | { tag: "StaleAlias" }

type PersonhoodContextName

type PersonhoodContextName = keyof typeof PERSONHOOD_CONTEXT_INDEX

type PersonhoodResult

The outcome of a personhood read.

UsernameUnowned is a first-class success value: the chain was queried and answered that nobody owns that username. It is not an error channel.

type PersonhoodResult = { at: FinalizedSnapshot; tag: "UsernameUnowned" } | { accountAddress: string; alias: string | null; at: FinalizedSnapshot; metrics: PersonhoodMetrics; participant: PersonhoodParticipant | null; state: PersonhoodState; tag: "Resolved" }

type PersonhoodState

A person’s membership standing, derived from one pinned snapshot.

Ordered here roughly by progression, not by precedence. The derivation rules are the authority on precedence — in particular a participant record always beats Lite personhood, and external recognition is permanent.

type PersonhoodState = { tag: "NotEnrolled" } | { tag: "Lite" } | { gamesRemaining: number; personhoodThreshold: number; score: number; tag: "Candidate" } | { tag: "MembershipReady" } | { activeWeeks: number; lastAttendedGame: number | null; tag: "Member" } | { allowedMisses: number; lastAttendedGame: number | null; misses: number; tag: "Caution"; window: number } | { tag: "Suspended" }

type PlayerKey

type PlayerKey = { type: "Account"; value: string } | { type: "Person"; value: string }

type PlayerRegistration

Whether the players named in ReadCurrentGameOptions.players are in the running game. One identity is keyed twice on chain (account and alias), so the question is asked per key and answered once: any hit is Registered.

Unknown exists so a failed key read cannot be mistaken for “not registered” — a stale account miss must not hide a person-side registration. Unchecked exists so “we did not ask” cannot be mistaken for either.

type PlayerRegistration = { tag: "Registered" } | { tag: "NotRegistered" } | { tag: "Unknown" } | { tag: "Unchecked" }

type PrizeStatus

The outcome of a prize-status read.

type PrizeStatus = { at: FinalizedSnapshot; lastGameIndex: number | null; tag: "NoGame"; upcoming: GameSchedulePreview[] } | { at: FinalizedSnapshot; drawCountFrom: "chain" | "caller"; draws: AirdropDraw[]; game: CurrentGame | null; gameIndex: number; tag: "Draws" }

type PrizeStatusChain

Both halves of the chain surface, since this read spans Game and Airdrop.

type PrizeStatusChain = AirdropChain & GameChain

type RawRegistrationEntry

The raw RegistrationEntry enum, the key Winners is addressed by.

type RawRegistrationEntry = { type: "Alias"; value: { alias: string } } | { type: "Account"; value: { account_id: string } }

type RawReportVote

A vote as the pallet Report enum takes it.

type RawReportVote = { type: "Person"; value: undefined } | { type: "NotPerson"; value: undefined }

type ReadPersonhoodStateOptions

What to read, and how: a username or an account, and never both.

Two inputs rather than one because a profile or results screen usually holds an account, not a name, and making it look the name up first would be a read this function then throws away.

The rule is enforced at runtime, not by this type. The union below rejects an object literal that names both fields as strings, and rejects an empty one. It does not reject { username: maybeName, account: maybeAccount } with both typed string | undefined, which is the shape a caller writes when the values come from state: TypeScript checks such a literal property by property against the union and lets it through. selectInput is what actually holds the rule, and an ambiguous call is an err result rather than a silent choice.

type ReadPersonhoodStateOptions = { signal?: AbortSignal } & { account?: never; username: string } | { account: string; username?: never }

type ReportVote

The judgement of one co-player, who either attended as a person or did not.

type ReportVote = "Person" | "NotPerson"

type ScoreContext

The chain’s score context, and whether a host can mint proofs in it.

NotProductDerived is an answer, not a failure — it is the state nextv2 is in — so it travels on the ok channel, like UsernameUnowned does. Every proof-building flow must treat it as a hard stop.

A chain that will not say what its suffix is has no variant here; it is rejected at compile time.

type ScoreContext = unknown

type SignUpBlocker

Why a sign-up, or the draw entry inside it, cannot go ahead. A list rather than the first hit: a player told “registration has closed” who is also already registered fixes the wrong thing.

Several of these stop only the draws. GameSignUpRequirement is what separates the two, not this type.

A tag must name a condition that is true on its own, or it sends the player to fix the wrong thing.

type SignUpBlocker = { tag: "NoGameRunning" } | { phase: GamePhase; tag: "NotInRegistration" } | { registrationEnds: number; tag: "RegistrationEnded" } | { tag: "AlreadyRegistered" } | { tag: "AliasVrfsUnavailable" } | { tag: "AccountVrfsNeedAnAccount" } | { tag: "NoDrawsScheduled" } | { keyType: string; tag: "NotSr25519" }

type SignUpFundsChain

What readSignUpFunds reads. Matched by hand against the paseo descriptors on 2026-09-25:

Game.PlayDepositAmount: StorageDescriptor<[], bigint, false, never> System.Account: StorageDescriptor<[Key: SS58String], AccountInfo, false, never>
type SignUpFundsChain = PinnedChain & { individuality: { query: { Game: { PlayDepositAmount: { getValue: unknown } }; System: { Account: { getValue: unknown } } } }; raw: { individuality: { getChainSpecData: unknown } } }

type UsernameCredibility

A consumer’s standing as the resources pallet records it.

alias is the person alias the pallet stores against the credibility, which is not the same value as a contextual alias from People.AccountToAlias.

type UsernameCredibility = { tag: "Lite" } | { alias: string; demoted: boolean; lastUpdate: number; tag: "Person" }

type WatchErrorHandler

type WatchErrorHandler = (error: ProductIndividualityError) => void

Variables

AIRDROP_VRF_TRANSCRIPT_LABEL

VRF_TRANSCRIPT_LABEL, which is also the domain item’s prefix.

let AIRDROP_VRF_TRANSCRIPT_LABEL: "pop:airdrop" = "pop:airdrop"

GAME_AIRDROP_EVENT_ID_BASE

Game::airdrop_event_id_base() — 27 bytes, the ten trailing spaces included as part of the value. The pinned expectation; production reads the chain’s copy.

let GAME_AIRDROP_EVENT_ID_BASE: "pop:game:airdrop: " = "pop:game:airdrop: "

MAX_GAME_AIRDROPS

Game’s MAX_GAME_AIRDROPS: a game schedules at most this many draws.

let MAX_GAME_AIRDROPS: 16 = 16

PEOPLE_AIRDROPS_EVENT_ID_BASE

indiv_pallet_people_airdrops::EVENT_ID_BASE — 24 bytes, four trailing spaces included. Hardcoded because it never reaches metadata, unlike Game’s; if it ever gains an extra_constants entry, read that and delete this.

let PEOPLE_AIRDROPS_EVENT_ID_BASE: "pop:people-airdrops: " = "pop:people-airdrops: "

PERSONHOOD_CONTEXT_INDEX

The context suffix indices the personhood product owns, mirroring personhood in individuality/support/src/context.rs.

Only score, peopleLiteAuth and peopleAirdrops are published as runtime constants; resources and dotnsGateway exist solely as this derivation, so pinning the published three pins the derivation that produces the other two.

let PERSONHOOD_CONTEXT_INDEX: { readonly dotnsGateway: 3; readonly peopleAirdrops: 4; readonly peopleLiteAuth: 2; readonly resources: 1; readonly score: 0 } = ...

PERSONHOOD_PRODUCT_NAME

personhood::PRODUCT_NAME — the DotNS name (TLD excluded) the personhood product’s contexts derive from, shared by every network.

let PERSONHOOD_PRODUCT_NAME: "peopl" = "peopl"

REGISTER_MESSAGE_PREFIX

The pallet’s domain prefix for the proof of ownership in Score.register. 18 bytes of UTF-8, concatenated raw — no separator, no length prefix.

let REGISTER_MESSAGE_PREFIX: "pop register using" = "pop register using"
Last updated on