-
Notifications
You must be signed in to change notification settings - Fork 288
/
encoder.ts
83 lines (78 loc) · 2.6 KB
/
encoder.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import { ABIType, FunctionAbi } from '@aztec/foundation/abi';
import { Fr } from '@aztec/foundation/fields';
/**
* Encodes arguments for a function call.
* Missing support for integer and string.
*/
class ArgumentEncoder {
private flattened: Fr[] = [];
constructor(private abi: FunctionAbi, private args: any[]) {}
/**
* Encodes a single argument from the given type to field.
* @param abiType - The abi type of the argument.
* @param arg - The value to encode.
* @param name - Name.
*/
private encodeArgument(abiType: ABIType, arg: any, name?: string) {
if (arg === undefined || arg == null) {
throw new Error(`Undefined argument ${name ?? 'unnamed'} of type ${abiType.kind}`);
}
switch (abiType.kind) {
case 'field':
if (typeof arg === 'number') {
this.flattened.push(new Fr(BigInt(arg)));
} else if (typeof arg === 'bigint') {
this.flattened.push(new Fr(arg));
} else if (typeof arg === 'object') {
if (typeof arg.toField === 'function') {
this.flattened.push(arg.toField());
} else if (arg instanceof Fr) {
this.flattened.push(arg);
} else {
throw new Error('Argument cannot be serialised to a field');
}
} else {
throw new Error(`Invalid argument "${arg}" of type ${abiType.kind}`);
}
break;
case 'boolean':
this.flattened.push(new Fr(arg ? 1n : 0n));
break;
case 'array':
for (let i = 0; i < abiType.length; i += 1) {
this.encodeArgument(abiType.type, arg[i], `${name}[${i}]`);
}
break;
case 'struct':
for (const field of abiType.fields) {
this.encodeArgument(field.type, arg[field.name], `${name}.${field.name}`);
}
break;
case 'integer':
this.flattened.push(new Fr(arg));
break;
default:
throw new Error(`Unsupported type: ${abiType.kind}`);
}
}
/**
* Encodes all the arguments for the given function ABI.
* @returns The encoded arguments.
*/
public encode() {
for (let i = 0; i < this.abi.parameters.length; i += 1) {
const parameterAbi = this.abi.parameters[i];
this.encodeArgument(parameterAbi.type, this.args[i], parameterAbi.name);
}
return this.flattened;
}
}
/**
* Encodes all the arguments for a function call.
* @param abi - The function ABI entry.
* @param args - The arguments to encode.
* @returns The encoded arguments.
*/
export function encodeArguments(abi: FunctionAbi, args: any[]) {
return new ArgumentEncoder(abi, args).encode();
}