Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
4275191
feat: add delegation-based caveat enforcer actions
cursoragent Aug 6, 2025
32ca7cb
feat: move caveat enforcer client to main export
cursoragent Aug 6, 2025
5bc38de
refactor: modify existing actions to accept delegation instead of cre…
cursoragent Aug 6, 2025
9828c52
refactor: simplify actions to only accept delegation and use environm…
cursoragent Aug 6, 2025
309219d
refactor: replace custom error types with standard Error constructor
cursoragent Aug 6, 2025
0f08e24
refactor: consolidate parameter types into single CaveatEnforcerParam…
cursoragent Aug 6, 2025
fa47fa7
test: update caveatUtils.test.ts to use new delegation interface
cursoragent Aug 6, 2025
f34de6c
refactor: remove client exports from actions index (moved to main exp…
cursoragent Aug 7, 2025
1fbd944
refactor: add caveatEnforcerActions back to actions export
cursoragent Aug 7, 2025
06f21cb
refactor: use destructuring in findMatchingCaveat function
cursoragent Aug 7, 2025
5b2a354
style: remove extra whitespace in getCaveatAvailableAmount.ts
cursoragent Aug 7, 2025
5c2e0a5
Fix tests
jeffsmale90 Aug 7, 2025
5a1ee52
use getDelegationHashoffchain function instead of delegation-core has…
jeffsmale90 Aug 7, 2025
89628de
Fix package exports, straggling tests, and import order.
jeffsmale90 Aug 7, 2025
b61ee8c
Improve internals of getCaveatAvailableAmount actions. Improve valida…
jeffsmale90 Aug 7, 2025
23ba21c
Improve action tests, remove client tests.
jeffsmale90 Aug 7, 2025
246694e
Move caveatEnforcerClient into it's own file
jeffsmale90 Aug 8, 2025
0b03514
Fix jsdoc comments in getCaveatAvailableAmount.ts
jeffsmale90 Aug 8, 2025
8a7843a
Remove duplicate createCaveatEnforcerClient and type
jeffsmale90 Aug 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 93 additions & 93 deletions packages/delegation-toolkit/src/actions/getCaveatAvailableAmount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,16 @@ import * as ERC20StreamingEnforcer from '../DelegationFramework/ERC20StreamingEn
import * as MultiTokenPeriodEnforcer from '../DelegationFramework/MultiTokenPeriodEnforcer';
import * as NativeTokenPeriodTransferEnforcer from '../DelegationFramework/NativeTokenPeriodTransferEnforcer';
import * as NativeTokenStreamingEnforcer from '../DelegationFramework/NativeTokenStreamingEnforcer';
import type { DeleGatorEnvironment } from '../types';
import { hashDelegation } from '../delegation';
import type { DeleGatorEnvironment, Delegation } from '../types';

/**
* Shared base params for all enforcer actions
* Parameters for all caveat enforcer actions.
*/
export type BaseCaveatParams = {
delegationHash: Hex;
delegationManager?: Address;
enforcerAddress?: Address;
terms: Hex;
export type CaveatEnforcerParams = {
Comment thread
jeffsmale90 marked this conversation as resolved.
delegation: Delegation;
};

/**
* Parameters for ERC20 period transfer enforcer.
*/
export type ERC20PeriodTransferParams = BaseCaveatParams;

/**
* Parameters for ERC20 streaming enforcer.
*/
export type ERC20StreamingParams = BaseCaveatParams;

/**
* Parameters for MultiTokenPeriodEnforcer.
*/
export type MultiTokenPeriodParams = {
args: Hex;
} & BaseCaveatParams;

/**
* Parameters for native token period transfer enforcer.
*/
export type NativeTokenPeriodTransferParams = BaseCaveatParams;

/**
* Parameters for native token streaming enforcer.
*/
export type NativeTokenStreamingParams = BaseCaveatParams;

/**
* Return type for period-based transfer enforcers
*/
Expand All @@ -60,46 +31,65 @@ export type StreamingResult = {
availableAmount: bigint;
};





Comment thread
jeffsmale90 marked this conversation as resolved.
Outdated
/**
* Resolves the delegation manager address from parameters or environment.
* Finds a caveat that matches the specified enforcer address
* @param delegation - The delegation to search
* @param enforcerAddress - The enforcer address to match
* @returns The matching caveat
* @throws Error if no matching caveat is found
* @throws Error if multiple matching caveats are found
*/
function findMatchingCaveat(
delegation: Delegation,
enforcerAddress: Address,
): { terms: Hex; args: Hex } {
const matchingCaveats = delegation.caveats.filter(
(caveat) => caveat.enforcer.toLowerCase() === enforcerAddress.toLowerCase(),
);

if (matchingCaveats.length === 0) {
throw new Error(`No caveat found with enforcer matching ${enforcerAddress}`);
}

if (matchingCaveats.length > 1) {
throw new Error(`Multiple caveats found with enforcer matching ${enforcerAddress}`);
}

return {
terms: matchingCaveats[0].terms,
args: matchingCaveats[0].args,
};
Comment thread
jeffsmale90 marked this conversation as resolved.
}

/**
* Gets the delegation manager address from environment.
*
* @param params - The parameters object.
* @param params.delegationManager - The delegation manager address.
* @param environment - The delegator environment.
* @returns The resolved delegation manager address.
* @returns The delegation manager address.
*/
function resolveDelegationManager(
params: { delegationManager?: Address },
environment: DeleGatorEnvironment,
): Address {
const delegationManager =
params.delegationManager ?? environment.DelegationManager;

if (!delegationManager) {
function getDelegationManager(environment: DeleGatorEnvironment): Address {
if (!environment.DelegationManager) {
throw new Error('Delegation manager address not found');
}

return delegationManager;
return environment.DelegationManager;
}

/**
* Resolves the enforcer address from parameters or environment.
* Gets the enforcer address from environment.
*
* @param enforcerName - The name of the enforcer.
* @param params - The parameters object.
* @param params.enforcerAddress - The enforcer address.
* @param environment - The delegator environment.
* @returns The resolved enforcer address.
* @returns The enforcer address.
*/
function resolveEnforcerAddress(
function getEnforcerAddress(
enforcerName: keyof DeleGatorEnvironment['caveatEnforcers'],
params: { enforcerAddress?: Address },
environment: DeleGatorEnvironment,
): Address {
if (params.enforcerAddress) {
return params.enforcerAddress;
}

const enforcerAddress = environment.caveatEnforcers[enforcerName];
if (!enforcerAddress) {
throw new Error(`${enforcerName} not found in environment`);
Expand All @@ -119,21 +109,23 @@ function resolveEnforcerAddress(
export async function getErc20PeriodTransferEnforcerAvailableAmount(
client: PublicClient,
environment: DeleGatorEnvironment,
params: ERC20PeriodTransferParams,
params: CaveatEnforcerParams,
): Promise<PeriodTransferResult> {
const delegationManager = resolveDelegationManager(params, environment);
const enforcerAddress = resolveEnforcerAddress(
const delegationManager = getDelegationManager(environment);
const enforcerAddress = getEnforcerAddress(
'ERC20PeriodTransferEnforcer',
params,
environment,
);

const delegationHash = hashDelegation(params.delegation);
const { terms } = findMatchingCaveat(params.delegation, enforcerAddress);

return ERC20PeriodTransferEnforcer.read.getAvailableAmount({
client,
contractAddress: enforcerAddress,
delegationHash: params.delegationHash,
delegationHash,
delegationManager,
terms: params.terms,
terms,
});
}

Expand All @@ -148,21 +140,23 @@ export async function getErc20PeriodTransferEnforcerAvailableAmount(
export async function getErc20StreamingEnforcerAvailableAmount(
client: PublicClient,
environment: DeleGatorEnvironment,
params: ERC20StreamingParams,
params: CaveatEnforcerParams,
): Promise<StreamingResult> {
const delegationManager = resolveDelegationManager(params, environment);
const enforcerAddress = resolveEnforcerAddress(
const delegationManager = getDelegationManager(environment);
const enforcerAddress = getEnforcerAddress(
'ERC20StreamingEnforcer',
params,
environment,
);

const delegationHash = hashDelegation(params.delegation);
const { terms } = findMatchingCaveat(params.delegation, enforcerAddress);

return ERC20StreamingEnforcer.read.getAvailableAmount({
client,
contractAddress: enforcerAddress,
delegationManager,
delegationHash: params.delegationHash,
terms: params.terms,
delegationHash,
terms,
});
}

Expand All @@ -177,22 +171,24 @@ export async function getErc20StreamingEnforcerAvailableAmount(
export async function getMultiTokenPeriodEnforcerAvailableAmount(
client: PublicClient,
environment: DeleGatorEnvironment,
params: MultiTokenPeriodParams,
params: CaveatEnforcerParams,
): Promise<PeriodTransferResult> {
const delegationManager = resolveDelegationManager(params, environment);
const enforcerAddress = resolveEnforcerAddress(
const delegationManager = getDelegationManager(environment);
const enforcerAddress = getEnforcerAddress(
'MultiTokenPeriodEnforcer',
params,
environment,
);

const delegationHash = hashDelegation(params.delegation);
const { terms, args } = findMatchingCaveat(params.delegation, enforcerAddress);

return MultiTokenPeriodEnforcer.read.getAvailableAmount({
client,
contractAddress: enforcerAddress,
delegationHash: params.delegationHash,
delegationHash,
delegationManager,
terms: params.terms,
args: params.args,
terms,
args,
});
}

Expand All @@ -207,21 +203,23 @@ export async function getMultiTokenPeriodEnforcerAvailableAmount(
export async function getNativeTokenPeriodTransferEnforcerAvailableAmount(
client: PublicClient,
environment: DeleGatorEnvironment,
params: NativeTokenPeriodTransferParams,
params: CaveatEnforcerParams,
): Promise<PeriodTransferResult> {
const delegationManager = resolveDelegationManager(params, environment);
const enforcerAddress = resolveEnforcerAddress(
const delegationManager = getDelegationManager(environment);
const enforcerAddress = getEnforcerAddress(
'NativeTokenPeriodTransferEnforcer',
params,
environment,
);

const delegationHash = hashDelegation(params.delegation);
const { terms } = findMatchingCaveat(params.delegation, enforcerAddress);

return NativeTokenPeriodTransferEnforcer.read.getAvailableAmount({
client,
contractAddress: enforcerAddress,
delegationHash: params.delegationHash,
delegationHash,
delegationManager,
terms: params.terms,
terms,
});
}

Expand All @@ -236,21 +234,23 @@ export async function getNativeTokenPeriodTransferEnforcerAvailableAmount(
export async function getNativeTokenStreamingEnforcerAvailableAmount(
client: PublicClient,
environment: DeleGatorEnvironment,
params: NativeTokenStreamingParams,
params: CaveatEnforcerParams,
): Promise<StreamingResult> {
const delegationManager = resolveDelegationManager(params, environment);
const enforcerAddress = resolveEnforcerAddress(
const delegationManager = getDelegationManager(environment);
const enforcerAddress = getEnforcerAddress(
'NativeTokenStreamingEnforcer',
params,
environment,
);

const delegationHash = hashDelegation(params.delegation);
const { terms } = findMatchingCaveat(params.delegation, enforcerAddress);

return NativeTokenStreamingEnforcer.read.getAvailableAmount({
client,
contractAddress: enforcerAddress,
delegationManager,
delegationHash: params.delegationHash,
terms: params.terms,
delegationHash,
terms,
});
}

Expand All @@ -271,7 +271,7 @@ export const caveatEnforcerActions =
* @returns Promise resolving to the period transfer result.
*/
getErc20PeriodTransferEnforcerAvailableAmount: async (
params: ERC20PeriodTransferParams,
params: CaveatEnforcerParams,
): Promise<PeriodTransferResult> => {
return getErc20PeriodTransferEnforcerAvailableAmount(
client,
Expand All @@ -287,7 +287,7 @@ export const caveatEnforcerActions =
* @returns Promise resolving to the streaming result.
*/
getErc20StreamingEnforcerAvailableAmount: async (
params: ERC20StreamingParams,
params: CaveatEnforcerParams,
): Promise<StreamingResult> => {
return getErc20StreamingEnforcerAvailableAmount(
client,
Expand All @@ -303,7 +303,7 @@ export const caveatEnforcerActions =
* @returns Promise resolving to the period transfer result.
*/
getMultiTokenPeriodEnforcerAvailableAmount: async (
params: MultiTokenPeriodParams,
params: CaveatEnforcerParams,
): Promise<PeriodTransferResult> => {
return getMultiTokenPeriodEnforcerAvailableAmount(
client,
Expand All @@ -319,7 +319,7 @@ export const caveatEnforcerActions =
* @returns Promise resolving to the period transfer result.
*/
getNativeTokenPeriodTransferEnforcerAvailableAmount: async (
params: NativeTokenPeriodTransferParams,
params: CaveatEnforcerParams,
): Promise<PeriodTransferResult> => {
return getNativeTokenPeriodTransferEnforcerAvailableAmount(
client,
Expand All @@ -335,7 +335,7 @@ export const caveatEnforcerActions =
* @returns Promise resolving to the streaming result.
*/
getNativeTokenStreamingEnforcerAvailableAmount: async (
params: NativeTokenStreamingParams,
params: CaveatEnforcerParams,
): Promise<StreamingResult> => {
return getNativeTokenStreamingEnforcerAvailableAmount(
client,
Expand Down
11 changes: 3 additions & 8 deletions packages/delegation-toolkit/src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,14 @@ export {
getMultiTokenPeriodEnforcerAvailableAmount,
getNativeTokenPeriodTransferEnforcerAvailableAmount,
getNativeTokenStreamingEnforcerAvailableAmount,
// Client extension exports
createCaveatEnforcerClient,
// Action builder
caveatEnforcerActions,
type CaveatEnforcerClient,
// Parameter types
type ERC20PeriodTransferParams,
type ERC20StreamingParams,
type MultiTokenPeriodParams,
type NativeTokenPeriodTransferParams,
type NativeTokenStreamingParams,
type CaveatEnforcerParams,
// Result types
type PeriodTransferResult,
type StreamingResult,

Comment thread
jeffsmale90 marked this conversation as resolved.
Outdated
} from './getCaveatAvailableAmount';

export { isValid7702Implementation } from './isValid7702Implementation';
6 changes: 6 additions & 0 deletions packages/delegation-toolkit/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,9 @@ export { redeemDelegations } from './write';
export * as contracts from './contracts';

export * as actions from './actions';

// Export the caveat enforcer client
export {
createCaveatEnforcerClient,
type CaveatEnforcerClient,
} from './actions';
Loading
Loading