@cellar-door/eas
v0.1.0
Published
EAS (Ethereum Attestation Service) adapter for EXIT Protocol — anchor departure markers as on-chain attestations
Maintainers
Readme
@cellar-door/eas 𓉸
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
⚠️ Pre-release software. No formal security audit has been performed. Use at your own risk. Report vulnerabilities to [email protected].
What This Does
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.
Install
npm install @cellar-door/easQuick Start
import { 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}`);
}Three-Tier Schema System
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 |
Usage
// 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'Schema Registration
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
Off-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.
API
anchorExit(marker, options) → AnchorResult
Anchor an EXIT marker as an EAS attestation (on-chain or off-chain).
verifyAnchor(uid, options) → VerifyResult
Verify an on-chain EXIT attestation by UID. Auto-detects schema mode (full/minimal/commitment).
verifyOffchainAnchor(attestation) → VerifyResult
Verify an off-chain EXIT attestation. Checks EIP-712 signature and decodes schema data.
revokeAnchor(uid, options) → RevokeResult
Revoke an on-chain EXIT attestation.
registerExitSchema(options) → RegisterSchemaResult
Register the EXIT schema on a chain (one-time per mode).
setExitSchemaUid(chain, uid, mode?)
Configure a known schema UID without re-registering.
didToAddress(did) → string
Convert a DID to an Ethereum address. Supports did:ethr, did:pkh, and did:key.
Supported Chains
| 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 Support
| 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 |
Security Considerations
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.
GDPR Compliance
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.
Additional Documentation
| 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 |
Ecosystem
| 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 |
License
Apache-2.0
