UNPKG

@metamask/delegation-toolkit

Version:

The Delegation Toolkit built on top of Viem - a library for interacting with DeleGator Smart Accounts

1 lines 129 kB
{"version":3,"sources":["../src/caveatBuilder/caveatBuilder.ts","../src/caveatBuilder/types.ts","../src/caveatBuilder/allowedCalldataBuilder.ts","../src/caveatBuilder/allowedMethodsBuilder.ts","../src/caveatBuilder/allowedTargetsBuilder.ts","../src/caveatBuilder/argsEqualityCheckBuilder.ts","../src/caveatBuilder/blockNumberBuilder.ts","../src/caveatBuilder/deployedBuilder.ts","../src/caveatBuilder/erc1155BalanceChangeBuilder.ts","../src/caveatBuilder/erc20BalanceChangeBuilder.ts","../src/caveatBuilder/erc20PeriodTransferBuilder.ts","../src/caveatBuilder/erc20StreamingBuilder.ts","../src/caveatBuilder/erc20TransferAmountBuilder.ts","../src/caveatBuilder/erc721BalanceChangeBuilder.ts","../src/caveatBuilder/erc721TransferBuilder.ts","../src/caveatBuilder/exactCalldataBatchBuilder.ts","../src/caveatBuilder/exactCalldataBuilder.ts","../src/caveatBuilder/exactExecutionBatchBuilder.ts","../src/caveatBuilder/exactExecutionBuilder.ts","../src/caveatBuilder/idBuilder.ts","../src/caveatBuilder/limitedCallsBuilder.ts","../src/caveatBuilder/multiTokenPeriodBuilder.ts","../src/caveatBuilder/nativeBalanceChangeBuilder.ts","../src/caveatBuilder/nativeTokenPaymentBuilder.ts","../src/caveatBuilder/nativeTokenPeriodTransferBuilder.ts","../src/caveatBuilder/nativeTokenStreamingBuilder.ts","../src/caveatBuilder/nativeTokenTransferAmountBuilder.ts","../src/caveatBuilder/nonceBuilder.ts","../src/caveatBuilder/ownershipTransferBuilder.ts","../src/caveatBuilder/redeemerBuilder.ts","../src/caveatBuilder/specificActionERC20TransferBatchBuilder.ts","../src/caveatBuilder/timestampBuilder.ts","../src/caveatBuilder/valueLteBuilder.ts","../src/caveatBuilder/coreCaveatBuilder.ts","../src/caveatBuilder/scope/erc20PeriodicScope.ts","../src/caveatBuilder/scope/erc20StreamingScope.ts","../src/caveatBuilder/scope/erc20TransferScope.ts","../src/utils.ts","../src/caveatBuilder/scope/erc721Scope.ts","../src/caveatBuilder/scope/functionCallScope.ts","../src/caveatBuilder/scope/nativeTokenPeriodicScope.ts","../src/caveatBuilder/scope/nativeTokenStreamingScope.ts","../src/caveatBuilder/scope/nativeTokenTransferScope.ts","../src/caveatBuilder/scope/ownershipScope.ts","../src/caveatBuilder/scope/index.ts","../src/caveatBuilder/resolveCaveats.ts","../src/caveats.ts","../src/delegation.ts"],"sourcesContent":["import type { Caveat, DeleGatorEnvironment } from '../types';\n\ntype CaveatWithOptionalArgs = Omit<Caveat, 'args'> & {\n args?: Caveat['args'];\n};\n\nconst INSECURE_UNRESTRICTED_DELEGATION_ERROR_MESSAGE =\n 'No caveats found. If you definitely want to create an empty caveat collection, set `allowInsecureUnrestrictedDelegation` to `true`.';\n\ntype CaveatBuilderMap = {\n [key: string]: (\n environment: DeleGatorEnvironment,\n ...args: [...any]\n ) => Caveat;\n};\n\nexport type CaveatBuilderConfig = {\n allowInsecureUnrestrictedDelegation?: boolean;\n};\n\n/**\n * A builder class for creating and managing caveats.\n * @template TCaveatBuilderMap - The type map of available caveat builder functions.\n */\nexport class CaveatBuilder<\n TCaveatBuilderMap extends CaveatBuilderMap = Record<string, never>,\n> {\n #results: Caveat[] = [];\n\n #hasBeenBuilt = false;\n\n #environment: DeleGatorEnvironment;\n\n #config: CaveatBuilderConfig;\n\n #enforcerBuilders: TCaveatBuilderMap;\n\n constructor(\n environment: DeleGatorEnvironment,\n config: CaveatBuilderConfig = {},\n enforcerBuilders: TCaveatBuilderMap = {} as TCaveatBuilderMap,\n builtCaveats: Caveat[] = [],\n ) {\n this.#environment = environment;\n this.#config = config;\n this.#enforcerBuilders = enforcerBuilders;\n this.#results = builtCaveats;\n }\n\n /**\n * Extends the CaveatBuilder with a new enforcer function.\n * @template TEnforcerName - The name of the enforcer.\n * @template TFunction - The type of the enforcer function.\n * @param name - The name of the enforcer.\n * @param fn - The enforcer function.\n * @returns The extended CaveatBuilder instance.\n */\n extend<\n TEnforcerName extends string,\n TFunction extends (\n environment: DeleGatorEnvironment,\n config: any,\n ) => Caveat,\n >(\n name: TEnforcerName,\n fn: TFunction,\n ): CaveatBuilder<TCaveatBuilderMap & Record<TEnforcerName, TFunction>> {\n return new CaveatBuilder<\n TCaveatBuilderMap & Record<TEnforcerName, TFunction>\n >(\n this.#environment,\n this.#config,\n { ...this.#enforcerBuilders, [name]: fn },\n this.#results,\n );\n }\n\n /**\n * Adds a caveat directly using a Caveat object.\n * @param caveat - The caveat to add.\n * @returns The CaveatBuilder instance for chaining.\n */\n addCaveat(caveat: CaveatWithOptionalArgs): CaveatBuilder<TCaveatBuilderMap>;\n\n /**\n * Adds a caveat using a named enforcer function.\n * @param name - The name of the enforcer function to use.\n * @param config - The configuration to pass to the enforcer function.\n * @returns The CaveatBuilder instance for chaining.\n */\n addCaveat<TEnforcerName extends keyof TCaveatBuilderMap>(\n name: TEnforcerName,\n config: Parameters<TCaveatBuilderMap[TEnforcerName]>[1],\n ): CaveatBuilder<TCaveatBuilderMap>;\n\n addCaveat<TEnforcerName extends keyof TCaveatBuilderMap>(\n nameOrCaveat: TEnforcerName | CaveatWithOptionalArgs,\n config?: Parameters<TCaveatBuilderMap[TEnforcerName]>[1],\n ): CaveatBuilder<TCaveatBuilderMap> {\n if (typeof nameOrCaveat === 'object') {\n const caveat = {\n args: '0x' as const,\n ...nameOrCaveat,\n };\n\n this.#results = [...this.#results, caveat];\n\n return this;\n }\n const name = nameOrCaveat;\n\n const func = this.#enforcerBuilders[name];\n if (typeof func === 'function') {\n const result = func(this.#environment, config);\n\n this.#results = [...this.#results, result];\n\n return this;\n }\n throw new Error(`Function \"${String(name)}\" does not exist.`);\n }\n\n /**\n * Returns the caveats that have been built using this CaveatBuilder.\n * @returns The array of built caveats.\n * @throws Error if the builder has already been built or if no caveats are found and empty caveats are not allowed.\n */\n build(): Caveat[] {\n if (this.#hasBeenBuilt) {\n throw new Error('This CaveatBuilder has already been built.');\n }\n\n if (\n this.#results.length === 0 &&\n !this.#config.allowInsecureUnrestrictedDelegation\n ) {\n throw new Error(INSECURE_UNRESTRICTED_DELEGATION_ERROR_MESSAGE);\n }\n\n this.#hasBeenBuilt = true;\n\n return this.#results;\n }\n}\n","import type { DeleGatorEnvironment } from 'src/types';\n\nexport enum BalanceChangeType {\n Increase = 0x0,\n Decrease = 0x1,\n}\n\nexport type UnitOfAuthorityBaseConfig = { environment: DeleGatorEnvironment };\n","import { type Hex, concat, isHex, toHex } from 'viem';\n\nimport type { DeleGatorEnvironment, Caveat } from '../types';\n\nexport const allowedCalldata = 'allowedCalldata';\n\nexport type AllowedCalldataBuilderConfig = {\n /**\n * The index in the calldata byte array (including the 4-byte method selector)\n * where the expected calldata starts.\n */\n startIndex: number;\n /**\n * The expected calldata as a hex string that must match at the specified index.\n */\n value: Hex;\n};\n\n/**\n * Builds a caveat struct for AllowedCalldataEnforcer that restricts calldata to a specific value at a given index.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object containing startIndex and value.\n * @returns The Caveat.\n * @throws Error if the value is not a valid hex string, if startIndex is negative, or if startIndex is not a whole number.\n */\nexport const allowedCalldataBuilder = (\n environment: DeleGatorEnvironment,\n config: AllowedCalldataBuilderConfig,\n): Caveat => {\n const { startIndex, value } = config;\n\n if (!isHex(value)) {\n throw new Error('Invalid value: must be a valid hex string');\n }\n\n if (startIndex < 0) {\n throw new Error('Invalid startIndex: must be zero or positive');\n }\n\n if (!Number.isInteger(startIndex)) {\n throw new Error('Invalid startIndex: must be a whole number');\n }\n\n const startIndexHex = toHex(startIndex, { size: 32 });\n\n const terms = concat([startIndexHex, value]);\n\n const {\n caveatEnforcers: { AllowedCalldataEnforcer },\n } = environment;\n\n if (!AllowedCalldataEnforcer) {\n throw new Error('AllowedCalldataEnforcer not found in environment');\n }\n\n return {\n enforcer: AllowedCalldataEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { isHex, concat, toFunctionSelector } from 'viem';\nimport type { AbiFunction, Hex } from 'viem';\n\nimport type { Caveat, DeleGatorEnvironment } from '../types';\n\nexport const allowedMethods = 'allowedMethods';\n\nexport type MethodSelector = Hex | string | AbiFunction;\n\n// length of function selector in chars, _including_ 0x prefix\nconst FUNCTION_SELECTOR_STRING_LENGTH = 10;\n\nexport type AllowedMethodsBuilderConfig = {\n /**\n * An array of method selectors that the delegate is allowed to call.\n * Can be 4-byte hex strings, ABI function signatures, or ABIFunction objects.\n */\n selectors: MethodSelector[];\n};\n\n/**\n * Builds a caveat struct for the AllowedMethodsEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object containing the allowed function selectors.\n * @returns The Caveat.\n * @throws Error if no selectors are provided or if any selector is invalid.\n */\nexport const allowedMethodsBuilder = (\n environment: DeleGatorEnvironment,\n config: AllowedMethodsBuilderConfig,\n): Caveat => {\n const { selectors } = config;\n\n if (selectors.length === 0) {\n throw new Error('Invalid selectors: must provide at least one selector');\n }\n\n const parsedSelectors = selectors.map(parseSelector);\n\n const terms = concat(parsedSelectors);\n\n const {\n caveatEnforcers: { AllowedMethodsEnforcer },\n } = environment;\n\n if (!AllowedMethodsEnforcer) {\n throw new Error('AllowedMethodsEnforcer not found in environment');\n }\n\n return {\n enforcer: AllowedMethodsEnforcer,\n terms,\n args: '0x',\n };\n};\n\n/**\n * Parses a method selector into a hex string.\n * @param selector - The method selector to parse.\n * @returns The parsed selector as a hex string.\n */\nfunction parseSelector(selector: MethodSelector) {\n if (isHex(selector)) {\n if (selector.length === FUNCTION_SELECTOR_STRING_LENGTH) {\n return selector;\n }\n throw new Error(\n 'Invalid selector: must be a 4 byte hex string, abi function signature, or AbiFunction',\n );\n }\n\n try {\n return toFunctionSelector(selector);\n } catch (rootError: any) {\n throw new Error(\n 'Invalid selector: must be a 4 byte hex string, abi function signature, or AbiFunction',\n { cause: rootError },\n );\n }\n}\n","import { concat, isAddress, type Address } from 'viem';\n\nimport type { Caveat, DeleGatorEnvironment } from '../types';\n\nexport const allowedTargets = 'allowedTargets';\n\nexport type AllowedTargetsBuilderConfig = {\n /**\n * An array of addresses that the delegate is allowed to call.\n * Each address must be a valid hex string.\n */\n targets: Address[];\n};\n\n/**\n * Builds a caveat struct for AllowedTargetsEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object containing the targets.\n * @returns The Caveat.\n * @throws Error if no targets are provided or if any of the addresses are invalid.\n */\nexport const allowedTargetsBuilder = (\n environment: DeleGatorEnvironment,\n config: AllowedTargetsBuilderConfig,\n): Caveat => {\n const { targets } = config;\n\n if (targets.length === 0) {\n throw new Error(\n 'Invalid targets: must provide at least one target address',\n );\n }\n\n // we check that the address is valid, but doesn't need to be checksummed\n const invalidAddresses = targets.filter(\n (target) => !isAddress(target, { strict: false }),\n );\n\n if (invalidAddresses.length > 0) {\n throw new Error('Invalid targets: must be valid addresses');\n }\n\n const terms = concat(targets);\n\n const {\n caveatEnforcers: { AllowedTargetsEnforcer },\n } = environment;\n\n if (!AllowedTargetsEnforcer) {\n throw new Error('AllowedTargetsEnforcer not found in environment');\n }\n\n return {\n enforcer: AllowedTargetsEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { type Hex, isHex } from 'viem';\n\nimport type { DeleGatorEnvironment, Caveat } from '../types';\n\nexport const argsEqualityCheck = 'argsEqualityCheck';\n\nexport type ArgsEqualityCheckBuilderConfig = {\n /**\n * The expected args as a hex string that must match exactly when redeeming the delegation.\n */\n args: Hex;\n};\n\n/**\n * Builds a caveat struct for the ArgsEqualityCheckEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object for the builder.\n * @returns The Caveat.\n * @throws Error if the config is invalid.\n */\nexport const argsEqualityCheckBuilder = (\n environment: DeleGatorEnvironment,\n config: ArgsEqualityCheckBuilderConfig,\n): Caveat => {\n const { args } = config;\n if (!isHex(args)) {\n throw new Error('Invalid config: args must be a valid hex string');\n }\n\n const {\n caveatEnforcers: { ArgsEqualityCheckEnforcer },\n } = environment;\n\n if (!ArgsEqualityCheckEnforcer) {\n throw new Error('ArgsEqualityCheckEnforcer not found in environment');\n }\n\n return {\n enforcer: ArgsEqualityCheckEnforcer,\n terms: args,\n args: '0x',\n };\n};\n","import { concat, toHex } from 'viem';\n\nimport type { DeleGatorEnvironment, Caveat } from '../types';\n\nexport const blockNumber = 'blockNumber';\n\nexport type BlockNumberBuilderConfig = {\n /**\n * The block number after which the delegation is valid.\n * Set to 0n to disable this threshold.\n */\n afterThreshold: bigint;\n /**\n * The block number before which the delegation is valid.\n * Set to 0n to disable this threshold.\n */\n beforeThreshold: bigint;\n};\n\n/**\n * Builds a caveat struct for the BlockNumberEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object for the BlockNumberEnforcer.\n * @returns The Caveat.\n * @throws Error if both thresholds are zero, if blockAfterThreshold is greater than or equal to blockBeforeThreshold, or if BlockNumberEnforcer is not available in the environment.\n */\nexport const blockNumberBuilder = (\n environment: DeleGatorEnvironment,\n config: BlockNumberBuilderConfig,\n): Caveat => {\n const { afterThreshold, beforeThreshold } = config;\n\n if (afterThreshold === 0n && beforeThreshold === 0n) {\n throw new Error(\n 'Invalid thresholds: At least one of afterThreshold or beforeThreshold must be specified',\n );\n }\n\n if (beforeThreshold !== 0n && afterThreshold >= beforeThreshold) {\n throw new Error(\n 'Invalid thresholds: afterThreshold must be less than beforeThreshold if both are specified',\n );\n }\n\n const terms = concat([\n toHex(afterThreshold, {\n size: 16,\n }),\n toHex(beforeThreshold, {\n size: 16,\n }),\n ]);\n\n const {\n caveatEnforcers: { BlockNumberEnforcer },\n } = environment;\n\n if (!BlockNumberEnforcer) {\n throw new Error('BlockNumberEnforcer not found in environment');\n }\n\n return {\n enforcer: BlockNumberEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { concat, isAddress, isHex, pad, type Address, type Hex } from 'viem';\n\nimport type { Caveat, DeleGatorEnvironment } from '../types';\n\nexport const deployed = 'deployed';\n\nexport type DeployedBuilderConfig = {\n /**\n * The contract address as a hex string.\n */\n contractAddress: Address;\n /**\n * The salt to use with the deployment, as a hex string.\n */\n salt: Hex;\n /**\n * The bytecode of the contract as a hex string.\n */\n bytecode: Hex;\n};\n\n/**\n * Builds a caveat struct for a DeployedEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration for the deployed builder.\n * @returns The Caveat.\n * @throws Error if the contract address, factory address, or bytecode is invalid.\n */\nexport const deployedBuilder = (\n environment: DeleGatorEnvironment,\n config: DeployedBuilderConfig,\n): Caveat => {\n const { contractAddress, salt, bytecode } = config;\n\n // we check that the addresses are valid, but don't need to be checksummed\n if (!isAddress(contractAddress, { strict: false })) {\n throw new Error(\n `Invalid contractAddress: must be a valid Ethereum address`,\n );\n }\n\n if (!isHex(salt)) {\n throw new Error('Invalid salt: must be a valid hexadecimal string');\n }\n\n if (!isHex(bytecode)) {\n throw new Error('Invalid bytecode: must be a valid hexadecimal string');\n }\n\n const terms = concat([contractAddress, pad(salt, { size: 32 }), bytecode]);\n\n const {\n caveatEnforcers: { DeployedEnforcer },\n } = environment;\n\n if (!DeployedEnforcer) {\n throw new Error('DeployedEnforcer not found in environment');\n }\n\n return {\n enforcer: DeployedEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { type Address, isAddress, encodePacked } from 'viem';\n\nimport type { DeleGatorEnvironment, Caveat } from '../types';\nimport { BalanceChangeType } from './types';\n\nexport const erc1155BalanceChange = 'erc1155BalanceChange';\n\nexport type Erc1155BalanceChangeBuilderConfig = {\n /**\n * The ERC-1155 contract address as a hex string.\n */\n tokenAddress: Address;\n /**\n * The recipient's address as a hex string.\n */\n recipient: Address;\n /**\n * The ID of the ERC-1155 token as a bigint.\n */\n tokenId: bigint;\n /**\n * The amount by which the balance must have changed as a bigint.\n */\n balance: bigint;\n /**\n * The balance change type for the ERC-1155 token.\n * Specifies whether the balance should have increased or decreased.\n * Valid parameters are BalanceChangeType.Increase and BalanceChangeType.Decrease.\n */\n changeType: BalanceChangeType;\n};\n\n/**\n * Builds a caveat struct for the ERC1155BalanceChangeEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object for the ERC1155 balance change.\n * @returns The Caveat.\n * @throws Error if the token address is invalid, the recipient address is invalid, or the amount is not a positive number.\n */\nexport const erc1155BalanceChangeBuilder = (\n environment: DeleGatorEnvironment,\n config: Erc1155BalanceChangeBuilderConfig,\n): Caveat => {\n const { tokenAddress, recipient, tokenId, balance, changeType } = config;\n\n if (!isAddress(tokenAddress, { strict: false })) {\n throw new Error('Invalid tokenAddress: must be a valid address');\n }\n\n if (!isAddress(recipient, { strict: false })) {\n throw new Error('Invalid recipient: must be a valid address');\n }\n\n if (balance <= 0n) {\n throw new Error('Invalid balance: must be a positive number');\n }\n\n if (tokenId < 0n) {\n throw new Error('Invalid tokenId: must be a non-negative number');\n }\n\n if (\n changeType !== BalanceChangeType.Increase &&\n changeType !== BalanceChangeType.Decrease\n ) {\n throw new Error('Invalid changeType: must be either Increase or Decrease');\n }\n\n const terms = encodePacked(\n ['uint8', 'address', 'address', 'uint256', 'uint256'],\n [changeType, tokenAddress, recipient, tokenId, balance],\n );\n\n const {\n caveatEnforcers: { ERC1155BalanceChangeEnforcer },\n } = environment;\n\n if (!ERC1155BalanceChangeEnforcer) {\n throw new Error('ERC1155BalanceChangeEnforcer not found in environment');\n }\n\n return {\n enforcer: ERC1155BalanceChangeEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { type Address, isAddress, encodePacked } from 'viem';\n\nimport type { DeleGatorEnvironment, Caveat } from '../types';\nimport { BalanceChangeType } from './types';\n\nexport const erc20BalanceChange = 'erc20BalanceChange';\n\nexport type Erc20BalanceChangeBuilderConfig = {\n /**\n * The ERC-20 contract address as a hex string.\n */\n tokenAddress: Address;\n /**\n * The recipient's address as a hex string.\n */\n recipient: Address;\n /**\n * The amount by which the balance must have changed as a bigint.\n */\n balance: bigint;\n /**\n * The balance change type for the ERC-20 token.\n * Specifies whether the balance should have increased or decreased.\n * Valid parameters are BalanceChangeType.Increase and BalanceChangeType.Decrease.\n */\n changeType: BalanceChangeType;\n};\n\n/**\n * Builds a caveat struct for the ERC20BalanceChangeEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object for the ERC20 balance change.\n * @returns The Caveat.\n * @throws Error if the token address is invalid, the amount is not a positive number, or the change type is invalid.\n */\nexport const erc20BalanceChangeBuilder = (\n environment: DeleGatorEnvironment,\n config: Erc20BalanceChangeBuilderConfig,\n): Caveat => {\n const { tokenAddress, recipient, balance, changeType } = config;\n\n if (!isAddress(tokenAddress, { strict: false })) {\n throw new Error('Invalid tokenAddress: must be a valid address');\n }\n\n if (balance <= 0n) {\n throw new Error('Invalid balance: must be a positive number');\n }\n\n if (\n changeType !== BalanceChangeType.Increase &&\n changeType !== BalanceChangeType.Decrease\n ) {\n throw new Error('Invalid changeType: must be either Increase or Decrease');\n }\n\n const terms = encodePacked(\n ['uint8', 'address', 'address', 'uint256'],\n [changeType, tokenAddress, recipient, balance],\n );\n\n const {\n caveatEnforcers: { ERC20BalanceChangeEnforcer },\n } = environment;\n\n if (!ERC20BalanceChangeEnforcer) {\n throw new Error('ERC20BalanceChangeEnforcer not found in environment');\n }\n\n return {\n enforcer: ERC20BalanceChangeEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { createERC20TokenPeriodTransferTerms } from '@metamask/delegation-core';\nimport type { Address } from 'viem';\n\nimport type { Caveat, DeleGatorEnvironment } from '../types';\n\nexport const erc20PeriodTransfer = 'erc20PeriodTransfer';\n\nexport type Erc20PeriodTransferBuilderConfig = {\n /**\n * The ERC-20 contract address as a hex string.\n */\n tokenAddress: Address;\n /**\n * The maximum amount of tokens that can be transferred per period.\n */\n periodAmount: bigint;\n /**\n * The duration of each period in seconds.\n */\n periodDuration: number;\n /**\n * The timestamp when the first period begins in seconds.\n */\n startDate: number;\n};\n\n/**\n * Builds a caveat struct for ERC20PeriodTransferEnforcer.\n * This enforcer validates that ERC20 token transfers do not exceed a specified amount\n * within a given time period. The transferable amount resets at the beginning of each period,\n * and any unused tokens are forfeited once the period ends.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration for the ERC20 period transfer builder.\n * @returns The Caveat.\n * @throws Error if the token address is invalid or if any of the numeric parameters are invalid.\n */\nexport const erc20PeriodTransferBuilder = (\n environment: DeleGatorEnvironment,\n config: Erc20PeriodTransferBuilderConfig,\n): Caveat => {\n const { tokenAddress, periodAmount, periodDuration, startDate } = config;\n\n const terms = createERC20TokenPeriodTransferTerms({\n tokenAddress,\n periodAmount,\n periodDuration,\n startDate,\n });\n\n const {\n caveatEnforcers: { ERC20PeriodTransferEnforcer },\n } = environment;\n\n if (!ERC20PeriodTransferEnforcer) {\n throw new Error('ERC20PeriodTransferEnforcer not found in environment');\n }\n\n return {\n enforcer: ERC20PeriodTransferEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { createERC20StreamingTerms } from '@metamask/delegation-core';\nimport { type Address } from 'viem';\n\nimport type { DeleGatorEnvironment, Caveat } from '../types';\n\nexport const erc20Streaming = 'erc20Streaming';\n\nexport type Erc20StreamingBuilderConfig = {\n /**\n * The ERC-20 contract address as a hex string.\n */\n tokenAddress: Address;\n /**\n * The initial amount available at start time as a bigint.\n */\n initialAmount: bigint;\n /**\n * Maximum total amount that can be unlocked as a bigint.\n */\n maxAmount: bigint;\n /**\n * Rate at which tokens accrue per second as a bigint.\n */\n amountPerSecond: bigint;\n /**\n * The start timestamp in seconds.\n */\n startTime: number;\n};\n\n/**\n * Builds a caveat for ERC20 token streaming with configurable parameters.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration for the ERC20 streaming builder.\n * @returns The Caveat.\n * @throws Error if the token address is invalid.\n * @throws Error if the initial amount is a negative number.\n * @throws Error if the max amount is not greater than 0.\n * @throws Error if the max amount is less than the initial amount.\n * @throws Error if the amount per second is not a positive number.\n * @throws Error if the start time is not a positive number.\n */\nexport const erc20StreamingBuilder = (\n environment: DeleGatorEnvironment,\n config: Erc20StreamingBuilderConfig,\n): Caveat => {\n const { tokenAddress, initialAmount, maxAmount, amountPerSecond, startTime } =\n config;\n\n const terms = createERC20StreamingTerms({\n tokenAddress,\n initialAmount,\n maxAmount,\n amountPerSecond,\n startTime,\n });\n\n const {\n caveatEnforcers: { ERC20StreamingEnforcer },\n } = environment;\n\n if (!ERC20StreamingEnforcer) {\n throw new Error('ERC20StreamingEnforcer not found in environment');\n }\n\n return {\n enforcer: ERC20StreamingEnforcer,\n terms,\n args: '0x',\n };\n};\n","import type { Address } from 'viem';\nimport { concat, isAddress, toHex } from 'viem';\n\nimport type { Caveat, DeleGatorEnvironment } from '../types';\n\nexport const erc20TransferAmount = 'erc20TransferAmount';\n\nexport type Erc20TransferAmountBuilderConfig = {\n /**\n * The ERC-20 contract address as a hex string.\n */\n tokenAddress: Address;\n /**\n * The maximum amount of tokens that can be transferred as a bigint.\n */\n maxAmount: bigint;\n};\n\n/**\n * Builds a caveat struct for ERC20TransferAmountEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration for the ERC20 transfer amount builder.\n * @returns The Caveat.\n * @throws Error if the token address is invalid or if the max amount is not a positive number.\n */\nexport const erc20TransferAmountBuilder = (\n environment: DeleGatorEnvironment,\n config: Erc20TransferAmountBuilderConfig,\n): Caveat => {\n const { tokenAddress, maxAmount } = config;\n\n if (!isAddress(tokenAddress, { strict: false })) {\n throw new Error('Invalid tokenAddress: must be a valid address');\n }\n\n if (maxAmount <= 0n) {\n throw new Error('Invalid maxAmount: must be a positive number');\n }\n\n const terms = concat([tokenAddress, toHex(maxAmount, { size: 32 })]);\n\n const {\n caveatEnforcers: { ERC20TransferAmountEnforcer },\n } = environment;\n\n if (!ERC20TransferAmountEnforcer) {\n throw new Error('ERC20TransferAmountEnforcer not found in environment');\n }\n\n return {\n enforcer: ERC20TransferAmountEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { type Address, isAddress, encodePacked } from 'viem';\n\nimport type { DeleGatorEnvironment, Caveat } from '../types';\nimport { BalanceChangeType } from './types';\n\nexport const erc721BalanceChange = 'erc721BalanceChange';\n\nexport type Erc721BalanceChangeBuilderConfig = {\n /**\n * The ERC-721 contract address as a hex string.\n */\n tokenAddress: Address;\n /**\n * The recipient's address as a hex string.\n */\n recipient: Address;\n /**\n * The amount by which the balance must have changed as a bigint.\n */\n amount: bigint;\n /**\n * The balance change type for the ERC-721 token.\n * Specifies whether the balance should have increased or decreased.\n * Valid parameters are BalanceChangeType.Increase and BalanceChangeType.Decrease.\n */\n changeType: BalanceChangeType;\n};\n\n/**\n * Builds a caveat struct for the ERC721BalanceChangeEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object for the ERC721 balance change.\n * @returns The Caveat.\n * @throws Error if the token address is invalid, the recipient address is invalid, or the amount is not a positive number.\n */\nexport const erc721BalanceChangeBuilder = (\n environment: DeleGatorEnvironment,\n config: Erc721BalanceChangeBuilderConfig,\n): Caveat => {\n const { tokenAddress, recipient, amount, changeType } = config;\n\n if (!isAddress(tokenAddress, { strict: false })) {\n throw new Error('Invalid tokenAddress: must be a valid address');\n }\n\n if (!isAddress(recipient, { strict: false })) {\n throw new Error('Invalid recipient: must be a valid address');\n }\n\n if (amount <= 0n) {\n throw new Error('Invalid balance: must be a positive number');\n }\n\n if (\n changeType !== BalanceChangeType.Increase &&\n changeType !== BalanceChangeType.Decrease\n ) {\n throw new Error('Invalid changeType: must be either Increase or Decrease');\n }\n\n const terms = encodePacked(\n ['uint8', 'address', 'address', 'uint256'],\n [changeType, tokenAddress, recipient, amount],\n );\n\n const {\n caveatEnforcers: { ERC721BalanceChangeEnforcer },\n } = environment;\n\n if (!ERC721BalanceChangeEnforcer) {\n throw new Error('ERC721BalanceChangeEnforcer not found in environment');\n }\n\n return {\n enforcer: ERC721BalanceChangeEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { type Address, isAddress, toHex, concat } from 'viem';\n\nimport type { DeleGatorEnvironment, Caveat } from '../types';\n\nexport const erc721Transfer = 'erc721Transfer';\n\nexport type Erc721TransferBuilderConfig = {\n /**\n * The ERC-721 contract address as a hex string.\n */\n tokenAddress: Address;\n /**\n * The token ID as a bigint.\n */\n tokenId: bigint;\n};\n\n/**\n * Builds a caveat struct for the ERC721TransferEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object for the ERC721 transfer builder.\n * @returns The Caveat representing the caveat for ERC721 transfer.\n * @throws Error if the permitted contract address is invalid.\n */\nexport const erc721TransferBuilder = (\n environment: DeleGatorEnvironment,\n config: Erc721TransferBuilderConfig,\n): Caveat => {\n const { tokenAddress, tokenId } = config;\n\n if (!isAddress(tokenAddress, { strict: false })) {\n throw new Error('Invalid tokenAddress: must be a valid address');\n }\n\n if (tokenId < 0n) {\n throw new Error('Invalid tokenId: must be a non-negative number');\n }\n\n const terms = concat([tokenAddress, toHex(tokenId, { size: 32 })]);\n\n const {\n caveatEnforcers: { ERC721TransferEnforcer },\n } = environment;\n\n if (!ERC721TransferEnforcer) {\n throw new Error('ERC721TransferEnforcer not found in environment');\n }\n\n return {\n enforcer: ERC721TransferEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { encodeAbiParameters, isAddress } from 'viem';\n\nimport type { ExecutionStruct } from '../executions';\nimport type { Caveat, DeleGatorEnvironment } from '../types';\n\nexport const exactCalldataBatch = 'exactCalldataBatch';\n\nexport type ExactCalldataBatchBuilderConfig = {\n /**\n * An array of executions that must be matched exactly in the batch.\n * Each execution specifies a target address, value, and calldata.\n */\n executions: ExecutionStruct[];\n};\n\n/**\n * Builds a caveat struct for ExactCalldataBatchEnforcer.\n * This enforcer ensures that the provided batch execution calldata matches exactly\n * the expected calldata for each execution.\n *\n * @param environment - The DeleGator environment.\n * @param config - Configuration object containing executions.\n * @returns The Caveat.\n * @throws Error if any of the executions have invalid parameters.\n */\nexport const exactCalldataBatchBuilder = (\n environment: DeleGatorEnvironment,\n config: ExactCalldataBatchBuilderConfig,\n): Caveat => {\n const { executions } = config;\n\n if (executions.length === 0) {\n throw new Error('Invalid executions: array cannot be empty');\n }\n\n // Validate each execution\n for (const execution of executions) {\n if (!isAddress(execution.target, { strict: false })) {\n throw new Error('Invalid target: must be a valid address');\n }\n\n if (execution.value < 0n) {\n throw new Error('Invalid value: must be a non-negative number');\n }\n\n if (!execution.callData.startsWith('0x')) {\n throw new Error(\n 'Invalid calldata: must be a hex string starting with 0x',\n );\n }\n }\n\n // Encode the executions using the approach implemented in ExecutionLib.sol encodeBatch()\n const terms = encodeAbiParameters(\n [\n {\n type: 'tuple[]',\n components: [\n { type: 'address', name: 'target' },\n { type: 'uint256', name: 'value' },\n { type: 'bytes', name: 'callData' },\n ],\n },\n ],\n [executions],\n );\n\n const {\n caveatEnforcers: { ExactCalldataBatchEnforcer },\n } = environment;\n\n if (!ExactCalldataBatchEnforcer) {\n throw new Error('ExactCalldataBatchEnforcer not found in environment');\n }\n\n return {\n enforcer: ExactCalldataBatchEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { createExactCalldataTerms } from '@metamask/delegation-core';\nimport type { Hex } from 'viem';\n\nimport type { Caveat, DeleGatorEnvironment } from '../types';\n\nexport const exactCalldata = 'exactCalldata';\n\nexport type ExactCalldataBuilderConfig = {\n /**\n * The exact calldata that must be matched as a hex string.\n */\n calldata: Hex;\n};\n\n/**\n * Builds a caveat struct for ExactCalldataEnforcer.\n * This enforcer ensures that the provided execution calldata matches exactly\n * the expected calldata.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration for the ExactCalldataBuilder.\n * @returns The Caveat.\n * @throws Error if any of the parameters are invalid.\n */\nexport const exactCalldataBuilder = (\n environment: DeleGatorEnvironment,\n config: ExactCalldataBuilderConfig,\n): Caveat => {\n const { calldata } = config;\n\n const terms = createExactCalldataTerms({ calldata });\n\n const {\n caveatEnforcers: { ExactCalldataEnforcer },\n } = environment;\n\n if (!ExactCalldataEnforcer) {\n throw new Error('ExactCalldataEnforcer not found in environment');\n }\n\n return {\n enforcer: ExactCalldataEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { encodeAbiParameters, isAddress } from 'viem';\n\nimport type { ExecutionStruct } from '../executions';\nimport type { Caveat, DeleGatorEnvironment } from '../types';\n\nexport const exactExecutionBatch = 'exactExecutionBatch';\n\nexport type ExactExecutionBatchBuilderConfig = {\n /**\n * An array of executions that must be matched exactly in the batch.\n * Each execution specifies a target address, value, and calldata.\n */\n executions: ExecutionStruct[];\n};\n\n/**\n * Builds a caveat struct for ExactExecutionBatchEnforcer.\n * This enforcer ensures that each execution in the batch matches exactly\n * with the expected execution (target, value, and calldata).\n *\n * @param environment - The DeleGator environment.\n * @param config - Configuration object containing executions.\n * @returns The Caveat.\n * @throws Error if any of the execution parameters are invalid.\n */\nexport const exactExecutionBatchBuilder = (\n environment: DeleGatorEnvironment,\n config: ExactExecutionBatchBuilderConfig,\n): Caveat => {\n const { executions } = config;\n\n if (executions.length === 0) {\n throw new Error('Invalid executions: array cannot be empty');\n }\n\n // Validate each execution\n for (const execution of executions) {\n if (!isAddress(execution.target, { strict: false })) {\n throw new Error('Invalid target: must be a valid address');\n }\n\n if (execution.value < 0n) {\n throw new Error('Invalid value: must be a non-negative number');\n }\n\n if (!execution.callData.startsWith('0x')) {\n throw new Error(\n 'Invalid calldata: must be a hex string starting with 0x',\n );\n }\n }\n\n // Encode the executions using the approach implemented in ExecutionLib.sol encodeBatch()\n const terms = encodeAbiParameters(\n [\n {\n type: 'tuple[]',\n components: [\n { type: 'address', name: 'target' },\n { type: 'uint256', name: 'value' },\n { type: 'bytes', name: 'callData' },\n ],\n },\n ],\n [executions],\n );\n\n const {\n caveatEnforcers: { ExactExecutionBatchEnforcer },\n } = environment;\n\n if (!ExactExecutionBatchEnforcer) {\n throw new Error('ExactExecutionBatchEnforcer not found in environment');\n }\n\n return {\n enforcer: ExactExecutionBatchEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { isAddress, concat, toHex } from 'viem';\n\nimport type { ExecutionStruct } from '../executions';\nimport type { Caveat, DeleGatorEnvironment } from '../types';\n\nexport const exactExecution = 'exactExecution';\n\nexport type ExactExecutionBuilderConfig = {\n /**\n * The execution that must be matched exactly.\n * Specifies the target address, value, and calldata.\n */\n execution: ExecutionStruct;\n};\n\n/**\n * Builds a caveat struct for ExactExecutionEnforcer.\n * This enforcer ensures that the provided execution matches exactly\n * with the expected execution (target, value, and calldata).\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object containing the execution.\n * @returns The Caveat.\n * @throws Error if any of the execution parameters are invalid.\n */\nexport const exactExecutionBuilder = (\n environment: DeleGatorEnvironment,\n config: ExactExecutionBuilderConfig,\n): Caveat => {\n const { execution } = config;\n\n if (!isAddress(execution.target, { strict: false })) {\n throw new Error('Invalid target: must be a valid address');\n }\n\n if (execution.value < 0n) {\n throw new Error('Invalid value: must be a non-negative number');\n }\n\n if (!execution.callData.startsWith('0x')) {\n throw new Error('Invalid calldata: must be a hex string starting with 0x');\n }\n\n const terms = concat([\n execution.target,\n toHex(execution.value, { size: 32 }),\n execution.callData,\n ]);\n\n const {\n caveatEnforcers: { ExactExecutionEnforcer },\n } = environment;\n\n if (!ExactExecutionEnforcer) {\n throw new Error('ExactExecutionEnforcer not found in environment');\n }\n\n return {\n enforcer: ExactExecutionEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { maxUint256, toHex } from 'viem';\n\nimport type { DeleGatorEnvironment, Caveat } from '../types';\n\nexport type IdBuilderConfig = {\n /**\n * An id for the delegation. Only one delegation may be redeemed with any given id.\n */\n id: bigint | number;\n};\n\nexport const id = 'id';\n\n/**\n * Builds a caveat struct for the IdEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object containing the id to use in the caveat.\n * @returns The Caveat.\n * @throws Error if the provided id is not a number, not an integer, or is not 32 bytes or fewer in length.\n */\nexport const idBuilder = (\n environment: DeleGatorEnvironment,\n config: IdBuilderConfig,\n): Caveat => {\n const { id: idValue } = config;\n\n let idBigInt: bigint;\n\n if (typeof idValue === 'number') {\n if (!Number.isInteger(idValue)) {\n throw new Error('Invalid id: must be an integer');\n }\n\n idBigInt = BigInt(idValue);\n } else if (typeof idValue === 'bigint') {\n idBigInt = idValue;\n } else {\n throw new Error('Invalid id: must be a bigint or number');\n }\n\n if (idBigInt < 0n) {\n throw new Error('Invalid id: must be a non-negative number');\n }\n\n if (idBigInt > maxUint256) {\n throw new Error('Invalid id: must be less than 2^256');\n }\n\n const terms = toHex(idBigInt, { size: 32 });\n\n const {\n caveatEnforcers: { IdEnforcer },\n } = environment;\n\n if (!IdEnforcer) {\n throw new Error('IdEnforcer not found in environment');\n }\n\n return {\n enforcer: IdEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { type Hex, toHex, pad } from 'viem';\n\nimport type { DeleGatorEnvironment, Caveat } from '../types';\n\nexport const limitedCalls = 'limitedCalls';\n\nexport type LimitedCallsBuilderConfig = {\n /**\n * The maximum number of times this delegation may be redeemed.\n */\n limit: number;\n};\n\n/**\n * Builds a caveat struct for the LimitedCallsEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object containing the limit.\n * @returns The Caveat.\n * @throws Error if the limit is not a positive integer.\n */\nexport const limitedCallsBuilder = (\n environment: DeleGatorEnvironment,\n config: LimitedCallsBuilderConfig,\n): Caveat => {\n const { limit } = config;\n\n if (!Number.isInteger(limit)) {\n throw new Error('Invalid limit: must be an integer');\n }\n\n if (limit <= 0) {\n throw new Error('Invalid limit: must be a positive integer');\n }\n\n const terms: Hex = pad(toHex(limit), { size: 32 });\n\n const {\n caveatEnforcers: { LimitedCallsEnforcer },\n } = environment;\n\n if (!LimitedCallsEnforcer) {\n throw new Error('LimitedCallsEnforcer not found in environment');\n }\n\n return {\n enforcer: LimitedCallsEnforcer,\n terms,\n args: '0x',\n };\n};\n","import type { Hex } from 'viem';\nimport { concat, isAddress, pad, toHex } from 'viem';\n\nimport type { DeleGatorEnvironment, Caveat } from '../types';\n\nexport type TokenPeriodConfig = {\n /**\n * The token contract address as a hex string.\n */\n token: Hex;\n /**\n * The maximum amount of tokens that can be transferred per period.\n */\n periodAmount: bigint;\n /**\n * The duration of each period in seconds.\n */\n periodDuration: number;\n /**\n * The timestamp when the first period begins in seconds.\n */\n startDate: number;\n};\n\nexport type MultiTokenPeriodBuilderConfig = TokenPeriodConfig[];\n\nexport const multiTokenPeriod = 'multiTokenPeriod';\n\n/**\n * Creates a caveat for the MultiTokenPeriodEnforcer.\n * This enforcer allows setting periodic transfer limits for multiple tokens.\n * Each token can have its own period amount, duration, and start date.\n *\n * @param environment - The DeleGator environment.\n * @param configs - The configurations for the MultiTokenPeriodBuilder.\n * @returns The caveat object for the MultiTokenPeriodEnforcer.\n */\nexport const multiTokenPeriodBuilder = (\n environment: DeleGatorEnvironment,\n configs: MultiTokenPeriodBuilderConfig,\n): Caveat => {\n if (!configs || configs.length === 0) {\n throw new Error('MultiTokenPeriodBuilder: configs array cannot be empty');\n }\n\n configs.forEach((config) => {\n if (!isAddress(config.token)) {\n throw new Error(`Invalid token address: ${String(config.token)}`);\n }\n\n if (config.periodAmount <= 0) {\n throw new Error('Invalid period amount: must be greater than 0');\n }\n\n if (config.periodDuration <= 0) {\n throw new Error('Invalid period duration: must be greater than 0');\n }\n });\n\n // Each config requires 116 bytes:\n // - 20 bytes for token address\n // - 32 bytes for periodAmount\n // - 32 bytes for periodDuration\n // - 32 bytes for startDate\n const termsArray = configs.reduce<Hex[]>(\n (acc, { token, periodAmount, periodDuration, startDate }) => [\n ...acc,\n pad(token, { size: 20 }),\n toHex(periodAmount, { size: 32 }),\n toHex(periodDuration, { size: 32 }),\n toHex(startDate, { size: 32 }),\n ],\n [],\n );\n\n const terms = concat(termsArray);\n\n const {\n caveatEnforcers: { MultiTokenPeriodEnforcer },\n } = environment;\n\n if (!MultiTokenPeriodEnforcer) {\n throw new Error('MultiTokenPeriodEnforcer not found in environment');\n }\n\n return {\n enforcer: MultiTokenPeriodEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { type Address, isAddress, encodePacked } from 'viem';\n\nimport type { DeleGatorEnvironment, Caveat } from '../types';\nimport { BalanceChangeType } from './types';\n\nexport const nativeBalanceChange = 'nativeBalanceChange';\n\nexport type NativeBalanceChangeBuilderConfig = {\n /**\n * The recipient's address as a hex string.\n */\n recipient: Address;\n /**\n * The amount by which the balance must have changed as a bigint.\n */\n balance: bigint;\n /**\n * The balance change type for the native currency.\n * Specifies whether the balance should have increased or decreased.\n * Valid parameters are BalanceChangeType.Increase and BalanceChangeType.Decrease.\n */\n changeType: BalanceChangeType;\n};\n\n/**\n * Builds a caveat struct for the NativeBalanceChangeEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object for the NativeBalanceChangeEnforcer.\n * @returns The Caveat.\n * @throws Error if the recipient address is invalid or the amount is not a positive number.\n */\nexport const nativeBalanceChangeBuilder = (\n environment: DeleGatorEnvironment,\n config: NativeBalanceChangeBuilderConfig,\n): Caveat => {\n const { recipient, balance, changeType } = config;\n\n if (!isAddress(recipient)) {\n throw new Error('Invalid recipient: must be a valid Address');\n }\n\n if (balance <= 0n) {\n throw new Error('Invalid balance: must be a positive number');\n }\n\n if (\n changeType !== BalanceChangeType.Increase &&\n changeType !== BalanceChangeType.Decrease\n ) {\n throw new Error('Invalid changeType: must be either Increase or Decrease');\n }\n\n const terms = encodePacked(\n ['uint8', 'address', 'uint256'],\n [changeType, recipient, balance],\n );\n\n const {\n caveatEnforcers: { NativeBalanceChangeEnforcer },\n } = environment;\n\n if (!NativeBalanceChangeEnforcer) {\n throw new Error('NativeBalanceChangeEnforcer not found in environment');\n }\n\n return {\n enforcer: NativeBalanceChangeEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { type Address, encodePacked, isAddress } from 'viem';\n\nimport type { Caveat, DeleGatorEnvironment } from '../types';\n\nexport const nativeTokenPayment = 'nativeTokenPayment';\n\nexport type NativeTokenPaymentBuilderConfig = {\n /**\n * The recipient's address as a hex string.\n */\n recipient: Address;\n /**\n * The amount that must be paid as a bigint.\n */\n amount: bigint;\n};\n\n/**\n * Builds a caveat struct for the NativeTokenPaymentEnforcer.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object for the NativeTokenPaymentEnforcer.\n * @returns The Caveat.\n * @throws Error if the amount is invalid or the recipient address is invalid.\n */\nexport const nativeTokenPaymentBuilder = (\n environment: DeleGatorEnvironment,\n config: NativeTokenPaymentBuilderConfig,\n): Caveat => {\n const { recipient, amount } = config;\n\n if (amount <= 0n) {\n throw new Error('Invalid amount: must be positive');\n }\n\n if (!isAddress(recipient)) {\n throw new Error('Invalid recipient: must be a valid address');\n }\n\n const terms = encodePacked(['address', 'uint256'], [recipient, amount]);\n\n const {\n caveatEnforcers: { NativeTokenPaymentEnforcer },\n } = environment;\n\n if (!NativeTokenPaymentEnforcer) {\n throw new Error('NativeTokenPaymentEnforcer not found in environment');\n }\n\n return {\n enforcer: NativeTokenPaymentEnforcer,\n terms,\n args: '0x',\n };\n};\n","import { createNativeTokenPeriodTransferTerms } from '@metamask/delegation-core';\n\nimport type { Caveat, DeleGatorEnvironment } from '../types';\n\nexport const nativeTokenPeriodTransfer = 'nativeTokenPeriodTransfer';\n\nexport type NativeTokenPeriodTransferBuilderConfig = {\n /**\n * The maximum amount of tokens that can be transferred per period.\n */\n periodAmount: bigint;\n /**\n * The duration of each period in seconds.\n */\n periodDuration: number;\n /**\n * The timestamp when the first period begins in seconds.\n */\n startDate: number;\n};\n\n/**\n * Builds a caveat struct for NativeTokenPeriodTransferEnforcer.\n * This enforcer validates that native token (ETH) transfers do not exceed a specified amount\n * within a given time period. The transferable amount resets at the beginning of each period,\n * and any unused ETH is forfeited once the period ends.\n *\n * @param environment - The DeleGator environment.\n * @param config - The configuration object containing periodAmount, periodDuration, and startDate.\n * @returns The Caveat.\n * @throws Error if any of the parameters are invalid.\n */\nexport const nativeTokenPeriodTransferBuilder = (\n environment: DeleGatorEnvironment,\n config: NativeTokenPeriodTra