Skip to content

Commit f78f50c

Browse files
committed
Add allowedCalldata terms builder in @metamask/delegation-core
1 parent a2f3062 commit f78f50c

6 files changed

Lines changed: 458 additions & 18 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { bytesToHex, remove0x, type BytesLike } from '@metamask/utils';
2+
3+
import {
4+
defaultOptions,
5+
prepareResult,
6+
type EncodingOptions,
7+
type ResultValue,
8+
} from '../returns';
9+
import type { Hex } from '../types';
10+
import { toHexString } from '../utils';
11+
12+
/**
13+
* Terms for configuring an AllowedCalldata caveat.
14+
*/
15+
export type AllowedCalldataTerms = {
16+
startIndex: number;
17+
value: BytesLike;
18+
};
19+
20+
/**
21+
* Creates terms for an AllowedCalldata caveat that ensures the provided execution calldata
22+
* matches the expected calldata at the specified index.
23+
*
24+
* @param terms - The terms for the AllowedCalldata caveat.
25+
* @param encodingOptions - The encoding options for the result.
26+
* @returns The terms as the calldata itself.
27+
* @throws Error if the `calldata` is invalid.
28+
*/
29+
export function createAllowedCalldataTerms(
30+
terms: AllowedCalldataTerms,
31+
encodingOptions?: EncodingOptions<'hex'>,
32+
): Hex;
33+
export function createAllowedCalldataTerms(
34+
terms: AllowedCalldataTerms,
35+
encodingOptions: EncodingOptions<'bytes'>,
36+
): Uint8Array;
37+
/**
38+
* Creates terms for an AllowedCalldata caveat that ensures the provided execution calldata
39+
* matches the expected calldata at the specified index.
40+
* @param terms - The terms for the AllowedCalldata caveat.
41+
* @param encodingOptions - The encoding options for the result.
42+
* @returns The terms as the calldata itself.
43+
* @throws Error if the `calldata` is invalid.
44+
*/
45+
export function createAllowedCalldataTerms(
46+
terms: AllowedCalldataTerms,
47+
encodingOptions: EncodingOptions<ResultValue> = defaultOptions,
48+
): Hex | Uint8Array {
49+
const { startIndex, value } = terms;
50+
51+
if (startIndex < 0) {
52+
throw new Error('Invalid startIndex: must be zero or positive');
53+
}
54+
55+
if (!Number.isInteger(startIndex)) {
56+
throw new Error('Invalid startIndex: must be a whole number');
57+
}
58+
59+
let unprefixedValue: string;
60+
61+
if (typeof value === 'string') {
62+
if (!value.startsWith('0x')) {
63+
throw new Error('Invalid value: must be a hex string starting with 0x');
64+
}
65+
unprefixedValue = remove0x(value);
66+
} else {
67+
unprefixedValue = bytesToHex(value);
68+
}
69+
70+
const indexHex = toHexString({ value: startIndex, size: 32 });
71+
72+
// The terms are the index encoded as 32 bytes followed by the expected value.
73+
return prepareResult(`0x${indexHex}${unprefixedValue}`, encodingOptions);
74+
}

packages/delegation-core/src/caveats/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export { createNativeTokenStreamingTerms } from './nativeTokenStreaming';
66
export { createERC20StreamingTerms } from './erc20Streaming';
77
export { createERC20TokenPeriodTransferTerms } from './erc20TokenPeriodTransfer';
88
export { createNonceTerms } from './nonce';
9+
export { createAllowedCalldataTerms } from './allowedCalldata';

packages/delegation-core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export {
1313
createERC20StreamingTerms,
1414
createERC20TokenPeriodTransferTerms,
1515
createNonceTerms,
16+
createAllowedCalldataTerms,
1617
} from './caveats';
1718

1819
export {

0 commit comments

Comments
 (0)