Session control
Session control
An agent you hired never holds your funds. It holds a key that names what it may call, caps what it may spend, and dies on a date you set — registered in a public Keystore that anybody, including you, can read without asking us.
Point it at an address.
Every session key Hallmark grants is registered in Altana’s public Keystore, and the Keystore answers to anyone. Paste a wallet address above, or connect yours, and this page will read its keys straight off BNB Testnet — no account, no API key, no trust in us.
These buttons run the real scope check — the same function an agent's execution path runs before it touches the relay — against the real policy for the category you pick. Nothing reaches a chain and nothing is mocked. A refusal here is the value a live agent would receive, word for word.
What a refusal looks like further down the stack
The check below runs locally, before anything is sent. If a call gets past it, the relay applies the same policy again and refuses by name: an over-cap spend comes back as ExceededSpendLimit and an off-allowlist call as UnauthorizedCall, each naming the key hash, the target and the calldata, raised at wallet_prepareCalls before a bundle exists at all.
So there is no transaction, no gas, and no status code to read — the refusal is a typed error, which is better evidence than a number. @hallmark/altana currently classifies those two as reverted rather than refused; that is a known misclassification in the package and is documented there.
Nothing attempted yet.
Press one of the buttons above. The interesting ones are the red ones: a session key that cannot be made to refuse has not demonstrated anything.
Runs checkScope() from @hallmark/altana over buildPolicy()’s output. The reasons — call-not-allowed, spend-cap, session-expired — are the SDK’s own, not copy written for this page. The relay’s equivalents, one layer down, are UnauthorizedCall and ExceededSpendLimit.
If verification needed our cooperation it would not be verification. Paste this into a terminal.
# Every session key 0x0000000000000000000000000000000000000000 has registered, from a public node.
cast call 0x6b8361C29d05D498b1a12B54A37310f94171E94A \
"getKeys(address)(bytes32[])" 0x0000000000000000000000000000000000000000 \
--rpc-url https://bsc-testnet-rpc.publicnode.com
# Whether one of them is still authorised, right now.
cast call 0x6b8361C29d05D498b1a12B54A37310f94171E94A \
"isValidKey(address,bytes32)(bool)" 0x0000000000000000000000000000000000000000 <keyId> \
--rpc-url https://bsc-testnet-rpc.publicnode.comKeystore contract on BNB Testnet: 0x6b8361C29d05D498b1a12B54A37310f94171E94A
Three transactions on BNB testnet. In between them an agent supplied real collateral to Venus using a key that could do that and nothing else — then the key stopped existing.
A scoped key registered in the public Altana Keystore against 0x330e…8531. The user keeps the admin key; the agent gets this one.
0x8e5c0023…87b856b4Venus mint() — supplied 0.001 tBNB as collateral. Signed by the session key, not by the wallet owner — the agent moved value under a policy that let it supply collateral and nothing else.
0xbb50ff72…bc78fd76One transaction, effective immediately. Anyone can confirm it without asking us — the Keystore is public and the read below took no credentials.
0xc5572b8f…fdf3d2f6isValidKey(0x330eb8…8531, 0x209a9c04…) = false — revokedKeystore 0x6b83…E94A on BNB testnet. The key no longer appears in getKeys() for that wallet at all, which is what revocation looks like from the outside. On BNB Smart Chain this lifecycle has not been run — the escrow and the probe live on testnet, and we do not imply otherwise.