← Pentagon Identity API docs

For every project that touches wallets, balance, or Points

Wallets & Points — the model, the rename, and what impacts you

One reference for how a user's wallets and Points work, the current naming, and whether the ongoing custody upgrade affects your integration. Short version: for most projects there is no code impact.

TL;DR
• Names: AA / AA2PG Balance · NPCPoints · PEN$PC · in-app self-custody wallet → PGAI Wallet · imported external wallets → Connected (monitor-only).
API/DB field names are unchangedaa_wallet_address, penai_address, mm_address, npc_points stay exactly as they are.
• The custodial key storage is being upgraded to per-wallet AWS-KMS envelope encryption with per-user, audited access. The one real change: a service no longer gets blanket access to every user's wallet — you act on a user's custodial wallet only by piggybacking on that user's authenticated login.

The three things a user can have

PGAI WalletConnected walletPG Balance
API fieldpenai_addressmm_addressaa_wallet_address
CustodyUser (self-custody, holds the seed)External, monitor-onlyPentagon (custodial)
After PGAI upgradeThe user's primary EOAWatch-only — we display it, never sign with itCustodial Points / $PC account
Who can spendThe userNobody via us (view only)Pentagon backend, on the user's behalf

Plain-language primer (safe to share with users): pentagon.games/pentagon-chain/pgai-wallet

Points / NPC / $PC

Points = NPC = $PC × 1000, and they live only on the PG Balance (never on the PGAI Wallet or a connected wallet). The balance is computed live from on-chain at read time — /user/walletinfo returns npc_points = on-chain $PC × 1000 (NPC_POINTS_PER_PC = 1000). There is no cached balance to keep in sync.

Impact: none. Reading a user's balance / Points is unchanged.

What the custody upgrade changes

Custodial wallet keys are moving to a per-wallet KMS envelope: each wallet's key is individually encrypted, unlockable only through an IAM-scoped, audited path — there is no shared master key. During the rollout, each migrated PG Balance also rotates to a fresh address (its balance is swept over 1:1; the previous address is retained as Legacy).

Two things to be aware of:
• A migrated user's aa_wallet_address value can change (the field name does not). Don't cache the address indefinitely; treat the old one as Legacy.
• To sign/spend from a user's custodial wallet you now piggyback on that user's login (an authenticated, per-user grant) rather than a service-wide key. No integration gets access to all users' wallets.

Worked example: a spend, and the "middle layer" AA2 adds

This is the part that surprises people, so here it is concretely — using the AR game spend.

Old model — broadly, an app could cause a custodial spend that went straight to a target contract. That's why it felt like "any app could use the wallets."
New model (AA2) — three parties, one integration point, and a deliberate split of duties:
PartyRoleCan it move the money?
The app (e.g. AR)Initiates — it holds the user's login (JWT) and calls the custody API with a unique idempotency key. No keys, and it does not name the target.No — it can only ask
Custody (pg-identity backend)Aims & signs — inside the user's authenticated session, it signs the transaction from the user's wallet to a fixed target.Yes — the only party that can
The contract teamProvides the surface the signed tx calls.No — it just receives

Live example: the AR app calls POST /user/npc/spend_ar with the user's JWT + an idempotency_key; custody signs GamePayHub.payPC(2, keccak256(idempotency_key)) from the user's wallet, value = the full spend. The app never sees a key and never names the contract.

Why the app can't just do it itself: it has no key (custody holds it), and — the important part — under AA2 the caller cannot name the target contract. If it could, any app holding a user's session could point that user's custodial funds anywhere. Fixing the target inside custody is the security upgrade, not a bottleneck. (Hashing the idempotency key can live in the app or in custody — it's a convention, not a privilege.)

Impact & how to up-rev — find your row

What your project doesImpactHow to up-rev
Reads a user's balance / PointsNoneNothing — same endpoint, same ×1000 math
Reads a user's address(es)Low — field names unchanged; aa_wallet_address value can change on migrationDon't cache the AA address forever; treat old as Legacy
Shows "AA wallet" / "NPC" labelsCosmeticRename to "PG Balance" / "Points"; don't call the custodial account a "wallet"
Lets a user connect MetaMask/RabbyBehavior — external EOAs are monitor-only (PGAI is the EOA)Treat connected wallets as view-only; a wallet already linked elsewhere returns wallet_already_linked (anti-reuse, by design)
Signs/spends from a user's custodial wallet, or expected access to all user walletsChangesPiggyback on the user's login → enqueue to the signer service. No service-wide wallet access.

Nomenclature map

You may seeCanonical nowNote
AA · AA2 · internal/platform wallet · "Pentagon account"PG Balancecustodial; not ERC-4337
NPC · NPC CreditsPoints1 $PC = 1000 Points
PEN · PEN chain$PC · Pentagon Chain (3344)token written $PC
PenXRPentagon AI (PGAI)same app, updated
penAIapp_address · "secondary address"PGAI Wallet (penai_address)self-custody EOA
PG connected wallet (imported)Connected wallet (monitor-only)mm_address / external
API/DB field names never change — only the user-facing labels and (for a migrated PG Balance) the address value. If your integration only reads fields, you are almost certainly unaffected.

Questions, or a case not covered here → the pg-identity / wallet team. Keep this the single source of truth for the wallet & points model.