Skip to content

Commit df5fe10

Browse files
committed
Add caveat terms builders to core package, and use them in the caveatBuilders.
- exactCalldata - nativeTokenPeriodTransfer - nativeTokenStreaming - timestamp - valueLte
1 parent b996faa commit df5fe10

18 files changed

Lines changed: 1239 additions & 108 deletions
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import {
2+
defaultOptions,
3+
prepareResult,
4+
type EncodingOptions,
5+
type ResultValue,
6+
} from '../returns';
7+
import type { Hex } from '../types';
8+
9+
/**
10+
* Terms for configuring an ExactCalldata caveat.
11+
*/
12+
export type ExactCalldataTerms = {
13+
/** The expected calldata to match against. */
14+
callData: Hex;
15+
};
16+
17+
/**
18+
* Creates terms for an ExactCalldata caveat that ensures the provided execution calldata
19+
* matches exactly the expected calldata.
20+
*
21+
* @param terms - The terms for the ExactCalldata caveat.
22+
* @param encodingOptions - The encoding options for the result.
23+
* @returns The terms as the calldata itself.
24+
* @throws Error if the `callData` is invalid.
25+
*/
26+
export function createExactCalldataTerms(
27+
terms: ExactCalldataTerms,
28+
encodingOptions?: EncodingOptions<'hex'>,
29+
): Hex;
30+
export function createExactCalldataTerms(
31+
terms: ExactCalldataTerms,
32+
encodingOptions: EncodingOptions<'bytes'>,
33+
): Uint8Array;
34+
/**
35+
* Creates terms for an ExactCalldata caveat that ensures the provided execution calldata
36+
* matches exactly the expected calldata.
37+
* @param terms - The terms for the ExactCalldata caveat.
38+
* @param encodingOptions - The encoding options for the result.
39+
* @returns The terms as the calldata itself.
40+
* @throws Error if the `callData` is invalid.
41+
*/
42+
export function createExactCalldataTerms(
43+
terms: ExactCalldataTerms,
44+
encodingOptions: EncodingOptions<ResultValue> = defaultOptions,
45+
): Hex | Uint8Array {
46+
const { callData } = terms;
47+
48+
if (!callData.startsWith('0x')) {
49+
throw new Error('Invalid callData: must be a hex string starting with 0x');
50+
}
51+
52+
// For exact calldata, the terms are simply the expected calldata
53+
return prepareResult(callData, encodingOptions);
54+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export { createValueLteTerms } from './valueLte';
2+
export { createTimestampTerms } from './timestamp';
3+
export { createNativeTokenPeriodTransferTerms } from './nativeTokenPeriodTransfer';
4+
export { createExactCalldataTerms } from './exactCalldata';
5+
export { createNativeTokenStreamingTerms } from './nativeTokenStreaming';
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import {
2+
defaultOptions,
3+
prepareResult,
4+
type EncodingOptions,
5+
type ResultValue,
6+
} from '../returns';
7+
import type { Hex } from '../types';
8+
import { toHexString } from '../utils';
9+
10+
/**
11+
* Terms for configuring a periodic transfer allowance of native tokens.
12+
*/
13+
export type NativeTokenPeriodTransferTerms = {
14+
/** The maximum amount that can be transferred within each period (in wei). */
15+
periodAmount: bigint;
16+
/** The duration of each period in seconds. */
17+
periodDuration: number;
18+
/** Unix timestamp when the first period begins. */
19+
startDate: number;
20+
};
21+
22+
/**
23+
* Creates terms for a NativeTokenPeriodTransfer caveat that validates that native token (ETH) transfers
24+
* do not exceed a specified amount within a given time period. The transferable amount resets at the
25+
* beginning of each period, and any unused ETH is forfeited once the period ends.
26+
*
27+
* @param terms - The terms for the NativeTokenPeriodTransfer caveat.
28+
* @param encodingOptions - The encoding options for the result.
29+
* @returns The terms as a 96-byte hex string (32 bytes for each parameter).
30+
* @throws Error if any of the numeric parameters are invalid.
31+
*/
32+
export function createNativeTokenPeriodTransferTerms(
33+
terms: NativeTokenPeriodTransferTerms,
34+
encodingOptions?: EncodingOptions<'hex'>,
35+
): Hex;
36+
export function createNativeTokenPeriodTransferTerms(
37+
terms: NativeTokenPeriodTransferTerms,
38+
encodingOptions: EncodingOptions<'bytes'>,
39+
): Uint8Array;
40+
/**
41+
* Creates terms for a NativeTokenPeriodTransfer caveat that validates that native token (ETH) transfers
42+
* do not exceed a specified amount within a given time period.
43+
*
44+
* @param terms - The terms for the NativeTokenPeriodTransfer caveat.
45+
* @param encodingOptions - The encoding options for the result.
46+
* @returns The terms as a 96-byte hex string (32 bytes for each parameter).
47+
* @throws Error if any of the numeric parameters are invalid.
48+
*/
49+
export function createNativeTokenPeriodTransferTerms(
50+
terms: NativeTokenPeriodTransferTerms,
51+
encodingOptions: EncodingOptions<ResultValue> = defaultOptions,
52+
): Hex | Uint8Array {
53+
const { periodAmount, periodDuration, startDate } = terms;
54+
55+
if (periodAmount <= 0n) {
56+
throw new Error('Invalid periodAmount: must be a positive number');
57+
}
58+
59+
if (periodDuration <= 0) {
60+
throw new Error('Invalid periodDuration: must be a positive number');
61+
}
62+
63+
if (startDate <= 0) {
64+
throw new Error('Invalid startDate: must be a positive number');
65+
}
66+
67+
const periodAmountHex = toHexString({ value: periodAmount, size: 32 });
68+
const periodDurationHex = toHexString({ value: periodDuration, size: 32 });
69+
const startDateHex = toHexString({ value: startDate, size: 32 });
70+
71+
const hexValue = `0x${periodAmountHex}${periodDurationHex}${startDateHex}`;
72+
73+
return prepareResult(hexValue, encodingOptions);
74+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import {
2+
defaultOptions,
3+
prepareResult,
4+
type EncodingOptions,
5+
type ResultValue,
6+
} from '../returns';
7+
import type { Hex } from '../types';
8+
import { toHexString } from '../utils';
9+
10+
// Upper bound for timestamps (January 1, 10000 CE)
11+
const TIMESTAMP_UPPER_BOUND_SECONDS = 253402300799;
12+
13+
/**
14+
* Terms for configuring a linear streaming allowance of native tokens.
15+
*/
16+
export type NativeTokenStreamingTerms = {
17+
/** The initial amount available immediately (in wei). */
18+
initialAmount: bigint;
19+
/** The maximum total amount that can be transferred (in wei). */
20+
maxAmount: bigint;
21+
/** The rate at which allowance increases per second (in wei). */
22+
amountPerSecond: bigint;
23+
/** Unix timestamp when streaming begins. */
24+
startTime: number;
25+
};
26+
27+
/**
28+
* Creates terms for the NativeTokenStreaming caveat, configuring a linear
29+
* streaming allowance of native tokens.
30+
*
31+
* @param terms - The terms for the NativeTokenStreaming caveat.
32+
* @param encodingOptions - The encoding options for the result.
33+
* @returns Hex-encoded terms for the caveat (128 bytes).
34+
* @throws Error if initialAmount is negative.
35+
* @throws Error if maxAmount is not positive.
36+
* @throws Error if maxAmount is less than initialAmount.
37+
* @throws Error if amountPerSecond is not positive.
38+
* @throws Error if startTime is not positive.
39+
* @throws Error if startTime exceeds upper bound.
40+
*/
41+
export function createNativeTokenStreamingTerms(
42+
terms: NativeTokenStreamingTerms,
43+
encodingOptions?: EncodingOptions<'hex'>,
44+
): Hex;
45+
export function createNativeTokenStreamingTerms(
46+
terms: NativeTokenStreamingTerms,
47+
encodingOptions: EncodingOptions<'bytes'>,
48+
): Uint8Array;
49+
/**
50+
* Creates terms for the NativeTokenStreaming caveat, configuring a linear
51+
* streaming allowance of native tokens.
52+
*
53+
* @param terms - The terms for the NativeTokenStreaming caveat.
54+
* @param encodingOptions - The encoding options for the result.
55+
* @returns The terms as a 128-byte hex string.
56+
* @throws Error if any of the numeric parameters are invalid.
57+
*/
58+
export function createNativeTokenStreamingTerms(
59+
terms: NativeTokenStreamingTerms,
60+
encodingOptions: EncodingOptions<ResultValue> = defaultOptions,
61+
): Hex | Uint8Array {
62+
const { initialAmount, maxAmount, amountPerSecond, startTime } = terms;
63+
64+
if (initialAmount < 0n) {
65+
throw new Error('Invalid initialAmount: must be greater than zero');
66+
}
67+
68+
if (maxAmount <= 0n) {
69+
throw new Error('Invalid maxAmount: must be a positive number');
70+
}
71+
72+
if (maxAmount < initialAmount) {
73+
throw new Error('Invalid maxAmount: must be greater than initialAmount');
74+
}
75+
76+
if (amountPerSecond <= 0n) {
77+
throw new Error('Invalid amountPerSecond: must be a positive number');
78+
}
79+
80+
if (startTime <= 0) {
81+
throw new Error('Invalid startTime: must be a positive number');
82+
}
83+
84+
if (startTime > TIMESTAMP_UPPER_BOUND_SECONDS) {
85+
throw new Error(
86+
'Invalid startTime: must be less than or equal to 253402300799',
87+
);
88+
}
89+
90+
const initialAmountHex = toHexString({ value: initialAmount, size: 32 });
91+
const maxAmountHex = toHexString({ value: maxAmount, size: 32 });
92+
const amountPerSecondHex = toHexString({ value: amountPerSecond, size: 32 });
93+
const startTimeHex = toHexString({ value: startTime, size: 32 });
94+
95+
const hexValue = `0x${initialAmountHex}${maxAmountHex}${amountPerSecondHex}${startTimeHex}`;
96+
97+
return prepareResult(hexValue, encodingOptions);
98+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import {
2+
defaultOptions,
3+
prepareResult,
4+
type EncodingOptions,
5+
type ResultValue,
6+
} from '../returns';
7+
import type { Hex } from '../types';
8+
import { toHexString } from '../utils';
9+
10+
// Upper bound for timestamps (equivalent to January 1, 10000 CE)
11+
const TIMESTAMP_UPPER_BOUND_SECONDS = 253402300799;
12+
13+
/**
14+
* Terms for configuring a timestamp threshold for delegation usage.
15+
*/
16+
export type TimestampTerms = {
17+
/** The timestamp (in seconds) after which the delegation can be used. */
18+
timestampAfterThreshold: number;
19+
/** The timestamp (in seconds) before which the delegation can be used. */
20+
timestampBeforeThreshold: number;
21+
};
22+
23+
/**
24+
* Creates terms for a Timestamp caveat that enforces time-based constraints on delegation usage.
25+
*
26+
* @param terms - The terms for the Timestamp caveat.
27+
* @param encodingOptions - The encoding options for the result.
28+
* @returns The terms as a 32-byte hex string (16 bytes for each timestamp).
29+
* @throws Error if the timestamps are invalid.
30+
*/
31+
export function createTimestampTerms(
32+
terms: TimestampTerms,
33+
encodingOptions?: EncodingOptions<'hex'>,
34+
): Hex;
35+
export function createTimestampTerms(
36+
terms: TimestampTerms,
37+
encodingOptions: EncodingOptions<'bytes'>,
38+
): Uint8Array;
39+
/**
40+
* Creates terms for a Timestamp caveat that enforces time-based constraints on delegation usage.
41+
*
42+
* @param terms - The terms for the Timestamp caveat.
43+
* @param encodingOptions - The encoding options for the result.
44+
* @returns The terms as a 32-byte hex string (16 bytes for each timestamp).
45+
* @throws Error if the timestamps are invalid.
46+
*/
47+
export function createTimestampTerms(
48+
terms: TimestampTerms,
49+
encodingOptions: EncodingOptions<ResultValue> = defaultOptions,
50+
): Hex | Uint8Array {
51+
const { timestampAfterThreshold, timestampBeforeThreshold } = terms;
52+
53+
if (timestampAfterThreshold < 0) {
54+
throw new Error(
55+
'Invalid timestampAfterThreshold: must be zero or positive',
56+
);
57+
}
58+
59+
if (timestampBeforeThreshold < 0) {
60+
throw new Error(
61+
'Invalid timestampBeforeThreshold: must be zero or positive',
62+
);
63+
}
64+
65+
if (timestampBeforeThreshold > TIMESTAMP_UPPER_BOUND_SECONDS) {
66+
throw new Error(
67+
`Invalid timestampBeforeThreshold: must be less than or equal to ${TIMESTAMP_UPPER_BOUND_SECONDS}`,
68+
);
69+
}
70+
71+
if (timestampAfterThreshold > TIMESTAMP_UPPER_BOUND_SECONDS) {
72+
throw new Error(
73+
`Invalid timestampAfterThreshold: must be less than or equal to ${TIMESTAMP_UPPER_BOUND_SECONDS}`,
74+
);
75+
}
76+
77+
if (
78+
timestampBeforeThreshold !== 0 &&
79+
timestampAfterThreshold >= timestampBeforeThreshold
80+
) {
81+
throw new Error(
82+
'Invalid thresholds: timestampBeforeThreshold must be greater than timestampAfterThreshold when both are specified',
83+
);
84+
}
85+
86+
const afterThresholdHex = toHexString({
87+
value: timestampAfterThreshold,
88+
size: 16,
89+
});
90+
const beforeThresholdHex = toHexString({
91+
value: timestampBeforeThreshold,
92+
size: 16,
93+
});
94+
95+
const hexValue = `0x${afterThresholdHex}${beforeThresholdHex}`;
96+
97+
return prepareResult(hexValue, encodingOptions);
98+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import {
2+
defaultOptions,
3+
prepareResult,
4+
type EncodingOptions,
5+
type ResultValue,
6+
} from '../returns';
7+
import type { Hex } from '../types';
8+
import { toHexString } from '../utils';
9+
10+
/**
11+
* Terms for configuring a ValueLte caveat.
12+
*/
13+
export type ValueLteTerms = {
14+
/** The maximum value allowed for the transaction as a bigint. */
15+
maxValue: bigint;
16+
};
17+
18+
/**
19+
* Creates terms for a ValueLte caveat that limits the maximum value of native tokens that can be spent.
20+
*
21+
* @param terms - The terms for the ValueLte caveat.
22+
* @param options - The encoding options for the result.
23+
* @returns The terms as a 32-byte hex string.
24+
* @throws Error if the maxValue is negative.
25+
*/
26+
export function createValueLteTerms(
27+
terms: ValueLteTerms,
28+
options?: EncodingOptions<'hex'>,
29+
): Hex;
30+
export function createValueLteTerms(
31+
terms: ValueLteTerms,
32+
options: EncodingOptions<'bytes'>,
33+
): Uint8Array;
34+
/**
35+
* Creates terms for a ValueLte caveat that limits the maximum value of native tokens that can be spent.
36+
*
37+
* @param terms - The terms for the ValueLte caveat.
38+
* @param options - The encoding options for the result.
39+
* @returns The terms as a 32-byte hex string.
40+
* @throws Error if the maxValue is negative.
41+
*/
42+
export function createValueLteTerms(
43+
terms: ValueLteTerms,
44+
options: EncodingOptions<ResultValue> = defaultOptions,
45+
): Hex | Uint8Array {
46+
const { maxValue } = terms;
47+
48+
if (maxValue < 0n) {
49+
throw new Error('Invalid maxValue: must be greater than or equal to zero');
50+
}
51+
const hexValue = toHexString({ value: maxValue, size: 32 });
52+
53+
return prepareResult(hexValue, options);
54+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export type { Hex } from './types';
2+
3+
export {
4+
createValueLteTerms,
5+
createTimestampTerms,
6+
createNativeTokenPeriodTransferTerms,
7+
createExactCalldataTerms,
8+
createNativeTokenStreamingTerms,
9+
} from './caveats';

0 commit comments

Comments
 (0)