Anchor EXIT departure markers as on-chain attestations via EAS (Ethereum Attestation Service).
𓉸 Passage Protocol · exit-door · entry-door · mcp · langchain · vercel · eliza · eas · erc-8004 · sign · python
EXIT markers are verifiable departure records for AI agents. This package anchors them on-chain as EAS attestations — non-transferable, permanent, queryable records on Base L2 (or any EVM chain where EAS is deployed).
EAS attestations are inherently soul-bound — they cannot be transferred, sold, or traded. No SBT wrapper needed.
npm install @cellar-door/easimport { anchorExit, verifyAnchor, registerExitSchema, setExitSchemaUid } from '@cellar-door/eas';
import { Wallet, JsonRpcProvider } from 'ethers';
const provider = new JsonRpcProvider('https://mainnet.base.org');
const signer = new Wallet(process.env.PRIVATE_KEY!, provider);
// One-time: register the EXIT schema on Base
const { schemaUid } = await registerExitSchema({ chain: 'base', signer });
// Or configure a known schema UID
setExitSchemaUid('base', '0x...');
// Anchor an EXIT marker on-chain
const result = await anchorExit(marker, {
chain: 'base',
signer,
vcUri: 'ipfs://bafybeig...',
});
console.log(`Anchored: ${result.uid}`);
// Verify an anchored attestation
const verification = await verifyAnchor(result.uid, { chain: 'base', provider });
if (verification.valid && !verification.revoked) {
console.log(`Valid EXIT by ${verification.attestation.attester}`);
}Choose the right level of on-chain data exposure for your use case:
| Mode | Schema | On-chain Data | Use Case |
|---|---|---|---|
full |
All fields | exitId, subjectDid, recipient, origin, timestamp, exitType, status, selfAttested, lineageHash, vcUri | Maximum queryability, public attestations |
minimal |
Hash + DID + URI | exitHash, subjectDid, vcUri | Reduced data, keeps DID for lookups |
commitment (default) |
Hash + URI only | exitHash, vcUri | True GDPR-safe — no personal data on-chain |
// Commitment mode (default) — GDPR-safe, no personal data on-chain
await anchorExit(marker, { chain: 'base', signer });
// Minimal mode — commitment hash + DID + VC URI
await anchorExit(marker, { chain: 'base', signer, schemaMode: 'minimal' });
// Full mode — all fields on-chain for maximum queryability
await anchorExit(marker, { chain: 'base', signer, schemaMode: 'full' });
// Backwards compat: minimal: true still works
await anchorExit(marker, { chain: 'base', signer, minimal: true }); // → schemaMode: 'minimal'Each mode has its own schema UID (content-addressed). Register once per chain per mode:
await registerExitSchema({ chain: 'base', signer }); // full
await registerExitSchema({ chain: 'base', signer, mode: 'minimal' }); // minimal
await registerExitSchema({ chain: 'base', signer, mode: 'commitment' }); // commitmentOff-chain attestations are signed EIP-712 data that can be stored anywhere.
// Create off-chain attestation
const result = await anchorExit(marker, {
chain: 'base',
signer,
mode: 'offchain',
schemaMode: 'commitment',
});
// Verify off-chain attestation
import { verifyOffchainAnchor } from '@cellar-door/eas';
const verification = verifyOffchainAnchor(result.offchainAttestation);Deduplication: Off-chain attestations include a deterministic nonce in the refUID field (derived from keccak256(markerId + chain + timestamp)). Consumers should check refUID uniqueness to detect duplicates.
Anchor an EXIT marker as an EAS attestation (on-chain or off-chain).
Verify an on-chain EXIT attestation by UID. Auto-detects schema mode (full/minimal/commitment).
Verify an off-chain EXIT attestation. Checks EIP-712 signature and decodes schema data.
Revoke an on-chain EXIT attestation.
Register the EXIT schema on a chain (one-time per mode).
Configure a known schema UID without re-registering.
Convert a DID to an Ethereum address. Supports did:ethr, did:pkh, and did:key.
| Chain | Cost/attestation | EAS Version |
|---|---|---|
| Base (default) | ~$0.002 | v1.0.1 (native) |
| Optimism | ~$0.002 | v1.0.1 (native) |
| Arbitrum | ~$0.01 | v0.26 |
| Ethereum | ~$5-30 | v0.26 |
| Sepolia (testnet) | Free | v0.26 |
| DID Method | Example | Mapping |
|---|---|---|
did:ethr |
did:ethr:0x1234... |
Direct address extraction |
did:ethr (network) |
did:ethr:base:0x1234... |
Direct address extraction |
did:pkh |
did:pkh:eip155:8453:0x1234... |
Direct address extraction |
did:key |
did:key:z6Mk... |
keccak256-derived address |
Attestations are permissionless. Anyone can create an attestation against EXIT schemas. Consumers MUST verify the attester address against a trusted set before accepting attestation data. See TRUST_MODEL.md for details and code examples.
For EU deployments, use schemaMode: 'commitment' to avoid storing personal data on-chain. See GDPR_GUIDE.md for the full deployment guide, crypto-shredding pattern, and DPIA requirements.
| Document | Description |
|---|---|
| TRUST_MODEL.md | Permissionless attestation model & attester verification |
| DID_METHODS.md | DID method address mapping, synthetic addresses, key rotation |
| GDPR_GUIDE.md | EU deployment guide, commitment mode, crypto-shredding |
| Package | Language | Description |
|---|---|---|
| cellar-door-exit | TypeScript | Core protocol (reference impl) |
| cellar-door-exit | Python | Core protocol |
| cellar-door-entry | TypeScript | Arrival/entry markers |
| @cellar-door/langchain | TypeScript | LangChain integration |
| cellar-door-langchain | Python | LangChain integration |
| @cellar-door/vercel-ai-sdk | TypeScript | Vercel AI SDK |
| @cellar-door/mcp-server | TypeScript | MCP server |
| @cellar-door/eliza | TypeScript | ElizaOS plugin |
| @cellar-door/eas | TypeScript | EAS attestation anchoring ← you are here |
| @cellar-door/erc-8004 | TypeScript | ERC-8004 identity/reputation |
| @cellar-door/sign-protocol | TypeScript | Sign Protocol attestation |
Apache-2.0