Skip to content

feat: add CaveatType enum and integrate into core caveat builder#179

Merged
mj-kiwi merged 11 commits intomainfrom
feat/add-caveat-type-enum
Mar 5, 2026
Merged

feat: add CaveatType enum and integrate into core caveat builder#179
mj-kiwi merged 11 commits intomainfrom
feat/add-caveat-type-enum

Conversation

@mj-kiwi
Copy link
Contributor

@mj-kiwi mj-kiwi commented Mar 5, 2026

📝 Description

Added comprehensive CaveatType enum to the Smart Accounts Kit and fully integrated it into the core caveat builder system. This provides developers with a type-safe, enum-based approach to specifying caveat types throughout the codebase, complementing the existing string literal support.

🔄 What Changed?

Core Changes:

  • Created CaveatType enum in constants.ts with 32 caveat type members:

    • Transfer & Balance caveats: Erc20TransferAmount, Erc20BalanceChange, NativeTokenTransferAmount, NativeBalanceChange, etc.
    • Time-based caveats: Timestamp, BlockNumber, LimitedCalls
    • Access control caveats: AllowedMethods, AllowedTargets, AllowedCalldata, Deployed
    • Advanced caveats: ExactCalldata, ExactExecution, MultiTokenPeriod, OwnershipTransfer, and more
  • Exported CaveatType from main package index (src/index.ts) for public API access

  • Enhanced type system in coreCaveatBuilder.ts:

    • Refactored CoreCaveatMap into _CoreCaveatMap (base type) and CoreCaveatMap (extended type)
    • Added mapped type that aliases CaveatType enum values to their corresponding builder functions
    • Ensures type safety and compile-time validation for caveat type references
  • Added comprehensive test coverage:

    • New "caveat builders using CaveatType enum" test suite with 17 tests
    • Validates all primary caveat types work correctly with the enum form
    • Ensures enum-based and string literal-based approaches produce identical results
    • All 37 tests passing (20 original string literal + 17 new enum tests)

🚀 Why?

  • Type Safety: Developers get IDE autocomplete and compile-time type checking instead of relying on string literals
  • Developer Experience: Enum values are discoverable through IDE IntelliSense
  • Consistency: Aligns with the existing ScopeType and Implementation enums in the codebase
  • Maintainability: Provides a single source of truth for caveat type definitions
  • Backward Compatible: String literal approach still works, enabling gradual migration
  • Comprehensive Coverage: Test suite validates both enum and string literal forms work identically

🧪 How to Test?

  • Automated tests added/updated
    • Run: npx vitest run test/caveatBuilder/createCaveatBuilder.test.ts
    • Result: 37 tests passing (20 original + 17 new enum-based tests)
    • Validates both CaveatType.AllowedMethods and 'allowedMethods' produce identical outputs
  • All existing tests pass (verified with vitest)
  • Type checking passes with TypeScript

⚠️ Breaking Changes

  • No breaking changes
    • String literal approach remains fully functional
    • New enum is purely additive to the existing API

📋 Checklist

  • Code follows the project's coding standards
  • Type system improvements with mapped types ensure type safety
  • Tests added/updated (17 new tests for CaveatType enum coverage)
  • Public API exports updated (CaveatType added to index.ts)
  • All existing tests pass
  • CI checks pass

🔗 Related Issues

Related to PR #170 (String Literal Support for addCaveat)

📚 Additional Notes

The CaveatType enum is now the recommended approach for specifying caveat types in production code. It provides the same functionality as string literals but with full type safety and IDE support. The implementation maintains backward compatibility with the string literal approach, allowing for gradual migration in existing codebases.

Key enum members:

  • Transfer controls: Erc20TransferAmount, NativeTokenTransferAmount, Erc20PeriodTransfer, NativeTokenPeriodTransfer
  • Balance enforcement: Erc20BalanceChange, NativeBalanceChange, Erc721BalanceChange, Erc1155BalanceChange
  • Time constraints: Timestamp, BlockNumber, LimitedCalls
  • Access control: AllowedMethods, AllowedTargets, AllowedCalldata, Deployed, Redeemer
  • Exact execution: ExactCalldata, ExactExecution, ExactCalldataBatch, ExactExecutionBatch

Note

Low Risk
Mostly additive API and TypeScript typing changes; runtime caveat building logic is unchanged, with the main risk being potential type-level breaking changes for consumers relying on previous CoreCaveatBuilder key types.

Overview
Adds a public CaveatType enum (exported from src/index.ts) to provide a type-safe alternative to string literals when selecting caveat/enforcer types.

Updates coreCaveatBuilder’s type map to accept both the existing string keys and CaveatType enum values (via a mapped type alias), and expands the createCaveatBuilder test suite to assert .addCaveat(CaveatType.*) produces the same caveat output as string-based usage.

Written by Cursor Bugbot for commit 5327b00. This will update automatically on new commits. Configure here.

@mj-kiwi mj-kiwi marked this pull request as ready for review March 5, 2026 00:42
@mj-kiwi mj-kiwi requested a review from a team as a code owner March 5, 2026 00:42
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Copy link
Collaborator

@jeffsmale90 jeffsmale90 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked this with the createDelegation interface and it all works really well! Such a nice simple solution.

I think some test coverage and this should be g2g.

ownershipTransfer: typeof ownershipTransferBuilder;
};

type CaveatMapLookup<Key extends keyof _CoreCaveatMap> = _CoreCaveatMap[Key];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks so nice and simple! Do we need this intermediary CaveatMapLookup though?

I think we can just

type CoreCaveatMap = _CoreCaveatMap & {
  [K in CaveatType as `${K}`]: _CoreCaveatMap[`${K}`];
};

I think we should rename _CoreCaveatMap to something more meaningful - maybe your CaveatMapLookup is a good name for it!

jeffsmale90
jeffsmale90 previously approved these changes Mar 5, 2026
Copy link
Collaborator

@jeffsmale90 jeffsmale90 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! A possible type rename, but otherwise looks awesome.

Copy link
Collaborator

@jeffsmale90 jeffsmale90 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love it!

@mj-kiwi mj-kiwi merged commit fab0b5f into main Mar 5, 2026
17 checks passed
@mj-kiwi mj-kiwi deleted the feat/add-caveat-type-enum branch March 5, 2026 08:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants