@aztec/foundation 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/abi/buffer.js +2 -2
- package/dest/fields/fields.d.ts +1 -0
- package/dest/fields/fields.d.ts.map +1 -1
- package/dest/fields/fields.js +6 -3
- package/package.json +2 -2
- package/src/abi/abi.ts +337 -0
- package/src/abi/buffer.ts +36 -0
- package/src/abi/decoder.ts +176 -0
- package/src/abi/encoder.ts +143 -0
- package/src/abi/index.ts +6 -0
- package/src/abi/selector.ts +243 -0
- package/src/abi/utils.ts +50 -0
- package/src/array/array.ts +86 -0
- package/src/array/index.ts +1 -0
- package/src/async-map/index.ts +18 -0
- package/src/aztec-address/index.ts +36 -0
- package/src/bigint-buffer/index.ts +87 -0
- package/src/collection/array.ts +64 -0
- package/src/collection/index.ts +1 -0
- package/src/committable/committable.ts +46 -0
- package/src/committable/index.ts +1 -0
- package/src/crypto/index.ts +16 -0
- package/src/crypto/keccak/index.ts +33 -0
- package/src/crypto/pedersen/index.ts +1 -0
- package/src/crypto/pedersen/pedersen.elliptic.ts +584 -0
- package/src/crypto/pedersen/pedersen.noble.ts +573 -0
- package/src/crypto/pedersen/pedersen.wasm.ts +42 -0
- package/src/crypto/random/index.ts +42 -0
- package/src/crypto/sha256/index.ts +3 -0
- package/src/errors/index.ts +6 -0
- package/src/eth-address/index.ts +234 -0
- package/src/fields/coordinate.ts +104 -0
- package/src/fields/fields.ts +328 -0
- package/src/fields/index.ts +3 -0
- package/src/fields/point.ts +145 -0
- package/src/fifo/bounded_serial_queue.ts +100 -0
- package/src/fifo/index.ts +4 -0
- package/src/fifo/memory_fifo.ts +118 -0
- package/src/fifo/semaphore.ts +33 -0
- package/src/fifo/serial_queue.ts +81 -0
- package/src/index.ts +29 -0
- package/src/json-rpc/README.md +55 -0
- package/src/json-rpc/class_converter.ts +213 -0
- package/src/json-rpc/client/index.ts +1 -0
- package/src/json-rpc/client/json_rpc_client.ts +147 -0
- package/src/json-rpc/convert.ts +163 -0
- package/src/json-rpc/fixtures/class_a.ts +15 -0
- package/src/json-rpc/fixtures/class_b.ts +15 -0
- package/src/json-rpc/fixtures/test_state.ts +59 -0
- package/src/json-rpc/index.ts +8 -0
- package/src/json-rpc/js_utils.ts +20 -0
- package/src/json-rpc/server/index.ts +2 -0
- package/src/json-rpc/server/json_proxy.ts +60 -0
- package/src/json-rpc/server/json_rpc_server.ts +269 -0
- package/src/log/console.ts +39 -0
- package/src/log/debug.ts +83 -0
- package/src/log/index.ts +5 -0
- package/src/log/log_fn.ts +5 -0
- package/src/log/log_history.ts +44 -0
- package/src/log/logger.ts +137 -0
- package/src/mutex/index.ts +83 -0
- package/src/mutex/mutex_database.ts +12 -0
- package/src/noir/index.ts +1 -0
- package/src/noir/noir_package_config.ts +54 -0
- package/src/retry/index.ts +99 -0
- package/src/running-promise/index.ts +60 -0
- package/src/serialize/buffer_reader.ts +286 -0
- package/src/serialize/field_reader.ts +143 -0
- package/src/serialize/free_funcs.ts +147 -0
- package/src/serialize/index.ts +5 -0
- package/src/serialize/serialize.ts +303 -0
- package/src/serialize/types.ts +40 -0
- package/src/sleep/index.ts +71 -0
- package/src/testing/index.ts +1 -0
- package/src/testing/test_data.ts +36 -0
- package/src/timer/elapsed.ts +23 -0
- package/src/timer/index.ts +3 -0
- package/src/timer/timeout.ts +64 -0
- package/src/timer/timer.ts +48 -0
- package/src/transport/browser/index.ts +4 -0
- package/src/transport/browser/message_port_socket.ts +48 -0
- package/src/transport/browser/shared_worker_connector.ts +21 -0
- package/src/transport/browser/shared_worker_listener.ts +53 -0
- package/src/transport/browser/worker_connector.ts +30 -0
- package/src/transport/browser/worker_listener.ts +54 -0
- package/src/transport/dispatch/create_dispatch_fn.ts +35 -0
- package/src/transport/dispatch/create_dispatch_proxy.ts +141 -0
- package/src/transport/dispatch/messages.ts +58 -0
- package/src/transport/index.ts +11 -0
- package/src/transport/interface/connector.ts +9 -0
- package/src/transport/interface/listener.ts +16 -0
- package/src/transport/interface/socket.ts +15 -0
- package/src/transport/interface/transferable.ts +125 -0
- package/src/transport/node/index.ts +2 -0
- package/src/transport/node/node_connector.ts +30 -0
- package/src/transport/node/node_connector_socket.ts +52 -0
- package/src/transport/node/node_listener.ts +34 -0
- package/src/transport/node/node_listener_socket.ts +48 -0
- package/src/transport/transport_client.ts +131 -0
- package/src/transport/transport_server.ts +108 -0
- package/src/trees/index.ts +54 -0
- package/src/types/index.ts +8 -0
- package/src/url/index.ts +73 -0
- package/src/wasm/README.md +6 -0
- package/src/wasm/empty_wasi_sdk.ts +166 -0
- package/src/wasm/fixtures/gcd.wasm +0 -0
- package/src/wasm/fixtures/gcd.wat +27 -0
- package/src/wasm/index.ts +1 -0
- package/src/wasm/wasm_module.ts +260 -0
- package/src/worker/browser/index.ts +2 -0
- package/src/worker/browser/start_web_module.ts +23 -0
- package/src/worker/browser/web_data_store.ts +38 -0
- package/src/worker/browser/web_worker.ts +24 -0
- package/src/worker/data_store.ts +19 -0
- package/src/worker/index.ts +2 -0
- package/src/worker/node/index.ts +2 -0
- package/src/worker/node/node_data_store.ts +27 -0
- package/src/worker/node/node_worker.ts +22 -0
- package/src/worker/node/start_node_module.ts +29 -0
- package/src/worker/wasm_worker.ts +7 -0
- package/src/worker/worker_pool.ts +73 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Fr } from '../fields/index.js';
|
|
2
|
+
import { ABIType, FunctionAbi } from './abi.js';
|
|
3
|
+
import { isAddressStruct, isFunctionSelectorStruct, isWrappedFieldStruct } from './utils.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Encodes arguments for a function call.
|
|
7
|
+
* Missing support for integer and string.
|
|
8
|
+
*/
|
|
9
|
+
class ArgumentEncoder {
|
|
10
|
+
private flattened: Fr[] = [];
|
|
11
|
+
|
|
12
|
+
constructor(private abi: FunctionAbi, private args: any[]) {}
|
|
13
|
+
|
|
14
|
+
static typeSize(abiType: ABIType): number {
|
|
15
|
+
switch (abiType.kind) {
|
|
16
|
+
case 'field':
|
|
17
|
+
case 'boolean':
|
|
18
|
+
case 'integer':
|
|
19
|
+
return 1;
|
|
20
|
+
case 'string':
|
|
21
|
+
return abiType.length;
|
|
22
|
+
case 'array':
|
|
23
|
+
return abiType.length * ArgumentEncoder.typeSize(abiType.type);
|
|
24
|
+
case 'struct':
|
|
25
|
+
return abiType.fields.reduce((acc, field) => acc + ArgumentEncoder.typeSize(field.type), 0);
|
|
26
|
+
default: {
|
|
27
|
+
const exhaustiveCheck: never = abiType;
|
|
28
|
+
throw new Error(`Unhandled abi type: ${exhaustiveCheck}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Encodes a single argument from the given type to field.
|
|
35
|
+
* @param abiType - The abi type of the argument.
|
|
36
|
+
* @param arg - The value to encode.
|
|
37
|
+
* @param name - Name.
|
|
38
|
+
*/
|
|
39
|
+
private encodeArgument(abiType: ABIType, arg: any, name?: string) {
|
|
40
|
+
if (arg === undefined || arg == null) {
|
|
41
|
+
throw new Error(`Undefined argument ${name ?? 'unnamed'} of type ${abiType.kind}`);
|
|
42
|
+
}
|
|
43
|
+
switch (abiType.kind) {
|
|
44
|
+
case 'field':
|
|
45
|
+
if (typeof arg === 'number') {
|
|
46
|
+
this.flattened.push(new Fr(BigInt(arg)));
|
|
47
|
+
} else if (typeof arg === 'bigint') {
|
|
48
|
+
this.flattened.push(new Fr(arg));
|
|
49
|
+
} else if (typeof arg === 'boolean') {
|
|
50
|
+
this.flattened.push(new Fr(arg ? 1n : 0n));
|
|
51
|
+
} else if (typeof arg === 'object') {
|
|
52
|
+
if (Buffer.isBuffer(arg)) {
|
|
53
|
+
this.flattened.push(Fr.fromBuffer(arg));
|
|
54
|
+
} else if (typeof arg.toField === 'function') {
|
|
55
|
+
this.flattened.push(arg.toField());
|
|
56
|
+
} else {
|
|
57
|
+
throw new Error(`Argument for ${name} cannot be serialized to a field`);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
throw new Error(`Invalid argument "${arg}" of type ${abiType.kind}`);
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case 'boolean':
|
|
64
|
+
this.flattened.push(new Fr(arg ? 1n : 0n));
|
|
65
|
+
break;
|
|
66
|
+
case 'array':
|
|
67
|
+
for (let i = 0; i < abiType.length; i += 1) {
|
|
68
|
+
this.encodeArgument(abiType.type, arg[i], `${name}[${i}]`);
|
|
69
|
+
}
|
|
70
|
+
break;
|
|
71
|
+
case 'string':
|
|
72
|
+
for (let i = 0; i < abiType.length; i += 1) {
|
|
73
|
+
// If the string is shorter than the defined length, pad it with 0s.
|
|
74
|
+
const toInsert = i < arg.length ? BigInt((arg as string).charCodeAt(i)) : 0n;
|
|
75
|
+
this.flattened.push(new Fr(toInsert));
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
case 'struct': {
|
|
79
|
+
// If the abi expects a struct like { address: Field } and the supplied arg does not have
|
|
80
|
+
// an address field in it, we try to encode it as if it were a field directly.
|
|
81
|
+
const isAddress = isAddressStruct(abiType);
|
|
82
|
+
if (isAddress && typeof arg.address === 'undefined' && typeof arg.inner === 'undefined') {
|
|
83
|
+
this.encodeArgument({ kind: 'field' }, arg, `${name}.inner`);
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
// Or if the supplied argument does have an address field in it, like a CompleteAddress,
|
|
87
|
+
// we encode it directly as a field.
|
|
88
|
+
if (isAddress && typeof arg.address !== 'undefined') {
|
|
89
|
+
this.encodeArgument({ kind: 'field' }, arg.address, `${name}.address`);
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
if (isFunctionSelectorStruct(abiType)) {
|
|
93
|
+
this.encodeArgument({ kind: 'integer', sign: 'unsigned', width: 32 }, arg.value ?? arg, `${name}.inner`);
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
if (isWrappedFieldStruct(abiType)) {
|
|
97
|
+
this.encodeArgument({ kind: 'field' }, arg.inner ?? arg, `${name}.inner`);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
for (const field of abiType.fields) {
|
|
101
|
+
this.encodeArgument(field.type, arg[field.name], `${name}.${field.name}`);
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
case 'integer':
|
|
106
|
+
this.flattened.push(new Fr(arg));
|
|
107
|
+
break;
|
|
108
|
+
default:
|
|
109
|
+
throw new Error(`Unsupported type: ${abiType}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Encodes all the arguments for the given function ABI.
|
|
115
|
+
* @returns The encoded arguments.
|
|
116
|
+
*/
|
|
117
|
+
public encode() {
|
|
118
|
+
for (let i = 0; i < this.abi.parameters.length; i += 1) {
|
|
119
|
+
const parameterAbi = this.abi.parameters[i];
|
|
120
|
+
this.encodeArgument(parameterAbi.type, this.args[i], parameterAbi.name);
|
|
121
|
+
}
|
|
122
|
+
return this.flattened;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Encodes all the arguments for a function call.
|
|
128
|
+
* @param abi - The function ABI entry.
|
|
129
|
+
* @param args - The arguments to encode.
|
|
130
|
+
* @returns The encoded arguments.
|
|
131
|
+
*/
|
|
132
|
+
export function encodeArguments(abi: FunctionAbi, args: any[]) {
|
|
133
|
+
return new ArgumentEncoder(abi, args).encode();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Returns the size of the arguments for a function ABI.
|
|
138
|
+
* @param abi - The function ABI entry.
|
|
139
|
+
* @returns The size of the arguments.
|
|
140
|
+
*/
|
|
141
|
+
export function countArgumentsSize(abi: FunctionAbi) {
|
|
142
|
+
return abi.parameters.reduce((acc, parameter) => acc + ArgumentEncoder.typeSize(parameter.type), 0);
|
|
143
|
+
}
|
package/src/abi/index.ts
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { randomBytes } from 'crypto';
|
|
2
|
+
|
|
3
|
+
import { fromHex, toBigIntBE, toBufferBE } from '../bigint-buffer/index.js';
|
|
4
|
+
import { keccak } from '../crypto/keccak/index.js';
|
|
5
|
+
import { Fr } from '../fields/index.js';
|
|
6
|
+
import { BufferReader, FieldReader } from '../serialize/index.js';
|
|
7
|
+
import { type ABIParameter } from './abi.js';
|
|
8
|
+
import { decodeFunctionSignature } from './decoder.js';
|
|
9
|
+
|
|
10
|
+
/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
|
|
11
|
+
|
|
12
|
+
/** A selector is the first 4 bytes of the hash of a signature. */
|
|
13
|
+
abstract class Selector {
|
|
14
|
+
/** The size of the selector in bytes. */
|
|
15
|
+
public static SIZE = 4;
|
|
16
|
+
|
|
17
|
+
constructor(/** Value of the selector */ public value: number) {
|
|
18
|
+
if (value > 2 ** (Selector.SIZE * 8) - 1) {
|
|
19
|
+
throw new Error(`Selector must fit in ${Selector.SIZE} bytes (got value ${value}).`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Checks if the selector is empty (all bytes are 0).
|
|
25
|
+
* @returns True if the selector is empty (all bytes are 0).
|
|
26
|
+
*/
|
|
27
|
+
public isEmpty(): boolean {
|
|
28
|
+
return this.value === 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Serialize as a buffer.
|
|
33
|
+
* @param bufferSize - The buffer size.
|
|
34
|
+
* @returns The buffer.
|
|
35
|
+
*/
|
|
36
|
+
toBuffer(bufferSize = Selector.SIZE): Buffer {
|
|
37
|
+
return toBufferBE(BigInt(this.value), bufferSize);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Serialize as a hex string.
|
|
42
|
+
* @returns The string.
|
|
43
|
+
*/
|
|
44
|
+
toString(): string {
|
|
45
|
+
return this.toBuffer().toString('hex');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Checks if this selector is equal to another.
|
|
50
|
+
* @param other - The other selector.
|
|
51
|
+
* @returns True if the selectors are equal.
|
|
52
|
+
*/
|
|
53
|
+
equals(other: Selector): boolean {
|
|
54
|
+
return this.value === other.value;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Returns a new field with the same contents as this EthAddress.
|
|
59
|
+
*
|
|
60
|
+
* @returns An Fr instance.
|
|
61
|
+
*/
|
|
62
|
+
public toField() {
|
|
63
|
+
return new Fr(BigInt(this.value));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Function selector branding */
|
|
68
|
+
export interface FunctionSelector {
|
|
69
|
+
/** Brand. */
|
|
70
|
+
_branding: 'FunctionSelector';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** A function selector is the first 4 bytes of the hash of a function signature. */
|
|
74
|
+
export class FunctionSelector extends Selector {
|
|
75
|
+
/**
|
|
76
|
+
* Checks if this function selector is equal to another.
|
|
77
|
+
* @returns True if the function selectors are equal.
|
|
78
|
+
*/
|
|
79
|
+
equals(otherName: string, otherParams: ABIParameter[]): boolean;
|
|
80
|
+
equals(other: FunctionSelector): boolean;
|
|
81
|
+
equals(other: FunctionSelector | string, otherParams?: ABIParameter[]): boolean {
|
|
82
|
+
if (typeof other === 'string') {
|
|
83
|
+
return this.equals(FunctionSelector.fromNameAndParameters(other, otherParams!));
|
|
84
|
+
}
|
|
85
|
+
return this.value === other.value;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Deserializes from a buffer or reader, corresponding to a write in cpp.
|
|
90
|
+
* @param buffer - Buffer or BufferReader to read from.
|
|
91
|
+
* @returns The Selector.
|
|
92
|
+
*/
|
|
93
|
+
static fromBuffer(buffer: Buffer | BufferReader) {
|
|
94
|
+
const reader = BufferReader.asReader(buffer);
|
|
95
|
+
const value = Number(toBigIntBE(reader.readBytes(Selector.SIZE)));
|
|
96
|
+
return new FunctionSelector(value);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Converts a field to selector.
|
|
101
|
+
* @param fr - The field to convert.
|
|
102
|
+
* @returns The selector.
|
|
103
|
+
*/
|
|
104
|
+
static fromField(fr: Fr) {
|
|
105
|
+
return new FunctionSelector(Number(fr.toBigInt()));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static fromFields(fields: Fr[] | FieldReader) {
|
|
109
|
+
const reader = FieldReader.asReader(fields);
|
|
110
|
+
return FunctionSelector.fromField(reader.readField());
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Creates a selector from a signature.
|
|
115
|
+
* @param signature - Signature to generate the selector for (e.g. "transfer(field,field)").
|
|
116
|
+
* @returns selector.
|
|
117
|
+
*/
|
|
118
|
+
static fromSignature(signature: string) {
|
|
119
|
+
// throw if signature contains whitespace
|
|
120
|
+
if (/\s/.test(signature)) {
|
|
121
|
+
throw new Error('Signature cannot contain whitespace');
|
|
122
|
+
}
|
|
123
|
+
return FunctionSelector.fromBuffer(keccak(Buffer.from(signature)).subarray(0, Selector.SIZE));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Create a Selector instance from a hex-encoded string.
|
|
128
|
+
* The input 'address' should be prefixed with '0x' or not, and have exactly 64 hex characters.
|
|
129
|
+
* Throws an error if the input length is invalid or address value is out of range.
|
|
130
|
+
*
|
|
131
|
+
* @param selector - The hex-encoded string representing the Selector.
|
|
132
|
+
* @returns An Selector instance.
|
|
133
|
+
*/
|
|
134
|
+
static fromString(selector: string) {
|
|
135
|
+
const buf = fromHex(selector);
|
|
136
|
+
if (buf.length !== Selector.SIZE) {
|
|
137
|
+
throw new Error(`Invalid Selector length ${buf.length} (expected ${Selector.SIZE}).`);
|
|
138
|
+
}
|
|
139
|
+
return FunctionSelector.fromBuffer(buf);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Creates an empty selector.
|
|
144
|
+
* @returns An empty selector.
|
|
145
|
+
*/
|
|
146
|
+
static empty() {
|
|
147
|
+
return new FunctionSelector(0);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Creates a function selector for a given function name and parameters.
|
|
152
|
+
* @param name - The name of the function.
|
|
153
|
+
* @param parameters - An array of ABIParameter objects, each containing the type information of a function parameter.
|
|
154
|
+
* @returns A Buffer containing the 4-byte selector.
|
|
155
|
+
*/
|
|
156
|
+
static fromNameAndParameters(args: { name: string; parameters: ABIParameter[] }): FunctionSelector;
|
|
157
|
+
static fromNameAndParameters(name: string, parameters: ABIParameter[]): FunctionSelector;
|
|
158
|
+
static fromNameAndParameters(
|
|
159
|
+
nameOrArgs: string | { name: string; parameters: ABIParameter[] },
|
|
160
|
+
maybeParameters?: ABIParameter[],
|
|
161
|
+
): FunctionSelector {
|
|
162
|
+
const { name, parameters } =
|
|
163
|
+
typeof nameOrArgs === 'string' ? { name: nameOrArgs, parameters: maybeParameters! } : nameOrArgs;
|
|
164
|
+
const signature = decodeFunctionSignature(name, parameters);
|
|
165
|
+
const selector = this.fromSignature(signature);
|
|
166
|
+
// If using the debug logger here it kill the typing in the `server_world_state_synchronizer` and jest tests.
|
|
167
|
+
// console.log(`selector for ${signature} is ${selector}`);
|
|
168
|
+
return selector;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Creates a random instance.
|
|
173
|
+
*/
|
|
174
|
+
static random() {
|
|
175
|
+
return FunctionSelector.fromBuffer(randomBytes(Selector.SIZE));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Event selector branding */
|
|
180
|
+
export interface EventSelector {
|
|
181
|
+
/** Brand. */
|
|
182
|
+
_branding: 'EventSelector';
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** An event selector is the first 4 bytes of the hash of an event signature. */
|
|
186
|
+
export class EventSelector extends Selector {
|
|
187
|
+
/**
|
|
188
|
+
* Deserializes from a buffer or reader, corresponding to a write in cpp.
|
|
189
|
+
* @param buffer - Buffer or BufferReader to read from.
|
|
190
|
+
* @returns The Selector.
|
|
191
|
+
*/
|
|
192
|
+
static fromBuffer(buffer: Buffer | BufferReader) {
|
|
193
|
+
const reader = BufferReader.asReader(buffer);
|
|
194
|
+
const value = Number(toBigIntBE(reader.readBytes(Selector.SIZE)));
|
|
195
|
+
return new EventSelector(value);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Converts a field to selector.
|
|
200
|
+
* @param fr - The field to convert.
|
|
201
|
+
* @returns The selector.
|
|
202
|
+
*/
|
|
203
|
+
static fromField(fr: Fr) {
|
|
204
|
+
return new EventSelector(Number(fr.toBigInt()));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Creates a selector from a signature.
|
|
209
|
+
* @param signature - Signature to generate the selector for (e.g. "transfer(field,field)").
|
|
210
|
+
* @returns selector.
|
|
211
|
+
*/
|
|
212
|
+
static fromSignature(signature: string) {
|
|
213
|
+
// throw if signature contains whitespace
|
|
214
|
+
if (/\s/.test(signature)) {
|
|
215
|
+
throw new Error('Signature cannot contain whitespace');
|
|
216
|
+
}
|
|
217
|
+
return EventSelector.fromBuffer(keccak(Buffer.from(signature)).subarray(0, Selector.SIZE));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Create a Selector instance from a hex-encoded string.
|
|
222
|
+
* The input 'address' should be prefixed with '0x' or not, and have exactly 64 hex characters.
|
|
223
|
+
* Throws an error if the input length is invalid or address value is out of range.
|
|
224
|
+
*
|
|
225
|
+
* @param selector - The hex-encoded string representing the Selector.
|
|
226
|
+
* @returns An Selector instance.
|
|
227
|
+
*/
|
|
228
|
+
static fromString(selector: string) {
|
|
229
|
+
const buf = fromHex(selector);
|
|
230
|
+
if (buf.length !== Selector.SIZE) {
|
|
231
|
+
throw new Error(`Invalid Selector length ${buf.length} (expected ${Selector.SIZE}).`);
|
|
232
|
+
}
|
|
233
|
+
return EventSelector.fromBuffer(buf);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Creates an empty selector.
|
|
238
|
+
* @returns An empty selector.
|
|
239
|
+
*/
|
|
240
|
+
static empty() {
|
|
241
|
+
return new EventSelector(0);
|
|
242
|
+
}
|
|
243
|
+
}
|
package/src/abi/utils.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type ABIType } from './abi.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns whether the ABI type is an Aztec or Ethereum Address defined in Aztec.nr.
|
|
5
|
+
* @param abiType - Type to check.
|
|
6
|
+
* @returns Boolean.
|
|
7
|
+
*/
|
|
8
|
+
export function isAddressStruct(abiType: ABIType) {
|
|
9
|
+
return isEthAddressStruct(abiType) || isAztecAddressStruct(abiType);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Returns whether the ABI type is an Ethereum Address defined in Aztec.nr.
|
|
14
|
+
* @param abiType - Type to check.
|
|
15
|
+
* @returns Boolean.
|
|
16
|
+
*/
|
|
17
|
+
export function isEthAddressStruct(abiType: ABIType) {
|
|
18
|
+
return abiType.kind === 'struct' && abiType.path.endsWith('types::address::EthAddress');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Returns whether the ABI type is an Aztec Address defined in Aztec.nr.
|
|
23
|
+
* @param abiType - Type to check.
|
|
24
|
+
* @returns Boolean.
|
|
25
|
+
*/
|
|
26
|
+
export function isAztecAddressStruct(abiType: ABIType) {
|
|
27
|
+
return abiType.kind === 'struct' && abiType.path.endsWith('types::address::AztecAddress');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Returns whether the ABI type is an Function Selector defined in Aztec.nr.
|
|
32
|
+
* @param abiType - Type to check.
|
|
33
|
+
* @returns Boolean.
|
|
34
|
+
*/
|
|
35
|
+
export function isFunctionSelectorStruct(abiType: ABIType) {
|
|
36
|
+
return abiType.kind === 'struct' && abiType.path.endsWith('types::abis::function_selector::FunctionSelector');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Returns whether the ABI type is a struct with a single `inner` field.
|
|
41
|
+
* @param abiType - Type to check.
|
|
42
|
+
*/
|
|
43
|
+
export function isWrappedFieldStruct(abiType: ABIType) {
|
|
44
|
+
return (
|
|
45
|
+
abiType.kind === 'struct' &&
|
|
46
|
+
abiType.fields.length === 1 &&
|
|
47
|
+
abiType.fields[0].name === 'inner' &&
|
|
48
|
+
abiType.fields[0].type.kind === 'field'
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Tuple } from '../serialize/index.js';
|
|
2
|
+
|
|
3
|
+
export type { FieldsOf } from '../types/index.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Create an array over an integer range.
|
|
7
|
+
* @param n - The number of integers.
|
|
8
|
+
* @param offset - The starting number.
|
|
9
|
+
* @returns The array of numbers.
|
|
10
|
+
*/
|
|
11
|
+
export function range(n: number, offset = 0) {
|
|
12
|
+
const ret: number[] = [];
|
|
13
|
+
for (let i = 0; i < n; i++) {
|
|
14
|
+
ret.push(offset + i);
|
|
15
|
+
}
|
|
16
|
+
return ret;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Create an array over an integer range, filled with a function 'fn'.
|
|
21
|
+
* This is used over e.g. lodash because it resolved to a tuple type, needed for our fixed array type safety.
|
|
22
|
+
* @param n - The number of integers.
|
|
23
|
+
* @param fn - The generator function.
|
|
24
|
+
* @returns The array of numbers.
|
|
25
|
+
*/
|
|
26
|
+
export function makeTuple<T, N extends number>(length: N, fn: (i: number) => T, offset = 0) {
|
|
27
|
+
return Array.from({ length }, (v: any, i: number) => fn(i + offset)) as Tuple<T, N>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Create an array over an integer range, filled with a function 'fn'. However, the latter half of the array are set to zeros.
|
|
32
|
+
* see `makeTuple` above.
|
|
33
|
+
* @param n - The number of integers.
|
|
34
|
+
* @param fn - The generator function.
|
|
35
|
+
* @returns The array of numbers.
|
|
36
|
+
*/
|
|
37
|
+
export function makeHalfFullTuple<T, N extends number>(length: N, fn: (i: number) => T, offset = 0) {
|
|
38
|
+
return Array.from({ length }, (v: any, i: number) => (i < length / 2 ? fn(i + offset) : fn(0))) as Tuple<T, N>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Assert a member of an object is a certain length.
|
|
43
|
+
* @param obj - An object.
|
|
44
|
+
* @param member - A member string.
|
|
45
|
+
* @param length - The length.
|
|
46
|
+
*/
|
|
47
|
+
export function assertMemberLength<
|
|
48
|
+
F extends string,
|
|
49
|
+
T extends {
|
|
50
|
+
[f in F]: {
|
|
51
|
+
/**
|
|
52
|
+
* A property which the tested member of the object T has to have.
|
|
53
|
+
*/
|
|
54
|
+
length: number;
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
>(obj: T, member: F, length: number) {
|
|
58
|
+
if (obj[member].length !== length) {
|
|
59
|
+
throw new Error(`Expected ${member} to have length ${length} but was ${obj[member].length}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Assert all subarrays in a member of an object are a certain length.
|
|
65
|
+
* @param obj - An object.
|
|
66
|
+
* @param member - A member string.
|
|
67
|
+
* @param length - The expected length for each subarray.
|
|
68
|
+
*/
|
|
69
|
+
export function assertItemsLength<
|
|
70
|
+
F extends string,
|
|
71
|
+
T extends {
|
|
72
|
+
[f in F]: {
|
|
73
|
+
/**
|
|
74
|
+
* A property which the tested member of the object T has to have.
|
|
75
|
+
*/
|
|
76
|
+
length: number;
|
|
77
|
+
}[];
|
|
78
|
+
},
|
|
79
|
+
>(obj: T, member: F, length: number) {
|
|
80
|
+
const arrays = obj[member];
|
|
81
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
82
|
+
if (arrays[i].length !== length) {
|
|
83
|
+
throw new Error(`Expected ${member}[${i}] to have length ${length} but was ${arrays[i].length}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './array.js';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps an array of elements by applying an asynchronous function to each element in sequence,
|
|
3
|
+
* and returns a new array with the results. The function receives each element of the array
|
|
4
|
+
* and its index as arguments, and should return a Promise that resolves to the desired value.
|
|
5
|
+
*
|
|
6
|
+
* @typeParam T - The original array element type.
|
|
7
|
+
* @typeParam U - The resulting array element type.
|
|
8
|
+
* @param arr - The array to map.
|
|
9
|
+
* @param fn - The async function to apply on each element of the array.
|
|
10
|
+
* @returns A Promise that resolves to a new array containing the mapped values.
|
|
11
|
+
*/
|
|
12
|
+
export async function asyncMap<T, U>(arr: T[], fn: (e: T, i: number) => Promise<U>): Promise<U[]> {
|
|
13
|
+
const results: U[] = [];
|
|
14
|
+
for (let i = 0; i < arr.length; ++i) {
|
|
15
|
+
results.push(await fn(arr[i], i));
|
|
16
|
+
}
|
|
17
|
+
return results;
|
|
18
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Fr } from '../fields/index.js';
|
|
2
|
+
import { FieldReader } from '../serialize/index.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* AztecAddress represents a 32-byte address in the Aztec Protocol.
|
|
6
|
+
* It provides methods to create, manipulate, and compare addresses.
|
|
7
|
+
* The maximum value of an address is determined by the field modulus and all instances of AztecAddress.
|
|
8
|
+
* It should have a value less than or equal to this max value.
|
|
9
|
+
* This class also provides helper functions to convert addresses from strings, buffers, and other formats.
|
|
10
|
+
*/
|
|
11
|
+
export class AztecAddress extends Fr {
|
|
12
|
+
constructor(buffer: Buffer) {
|
|
13
|
+
if (buffer.length !== 32) {
|
|
14
|
+
throw new Error(`Invalid AztecAddress length ${buffer.length}.`);
|
|
15
|
+
}
|
|
16
|
+
super(buffer);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static fromField(fr: Fr) {
|
|
20
|
+
return new AztecAddress(fr.toBuffer());
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static fromFields(fields: Fr[] | FieldReader) {
|
|
24
|
+
const reader = FieldReader.asReader(fields);
|
|
25
|
+
return AztecAddress.fromField(reader.readField());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static fromBigInt(value: bigint) {
|
|
29
|
+
return AztecAddress.fromField(new Fr(value));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static fromString(buf: string) {
|
|
33
|
+
const buffer = Buffer.from(buf.replace(/^0x/i, ''), 'hex');
|
|
34
|
+
return new AztecAddress(buffer);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a little-endian buffer into a BigInt.
|
|
3
|
+
* @param buf - The little-endian buffer to convert.
|
|
4
|
+
* @returns A BigInt with the little-endian representation of buf.
|
|
5
|
+
*/
|
|
6
|
+
export function toBigIntLE(buf: Buffer): bigint {
|
|
7
|
+
const reversed = Buffer.from(buf);
|
|
8
|
+
reversed.reverse();
|
|
9
|
+
const hex = reversed.toString('hex');
|
|
10
|
+
if (hex.length === 0) {
|
|
11
|
+
return BigInt(0);
|
|
12
|
+
}
|
|
13
|
+
return BigInt(`0x${hex}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Convert a big-endian buffer into a BigInt.
|
|
18
|
+
* @param buf - The big-endian buffer to convert.
|
|
19
|
+
* @returns A BigInt with the big-endian representation of buf.
|
|
20
|
+
*/
|
|
21
|
+
export function toBigIntBE(buf: Buffer): bigint {
|
|
22
|
+
const hex = buf.toString('hex');
|
|
23
|
+
if (hex.length === 0) {
|
|
24
|
+
return BigInt(0);
|
|
25
|
+
}
|
|
26
|
+
return BigInt(`0x${hex}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Convert a BigInt to a little-endian buffer.
|
|
31
|
+
* @param num - The BigInt to convert.
|
|
32
|
+
* @param width - The number of bytes that the resulting buffer should be.
|
|
33
|
+
* @returns A little-endian buffer representation of num.
|
|
34
|
+
*/
|
|
35
|
+
export function toBufferLE(num: bigint, width: number): Buffer {
|
|
36
|
+
if (num < BigInt(0)) {
|
|
37
|
+
throw new Error(`Cannot convert negative bigint ${num.toString()} to buffer with toBufferLE.`);
|
|
38
|
+
}
|
|
39
|
+
const hex = num.toString(16);
|
|
40
|
+
const buffer = Buffer.from(hex.padStart(width * 2, '0').slice(0, width * 2), 'hex');
|
|
41
|
+
buffer.reverse();
|
|
42
|
+
return buffer;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Convert a BigInt to a big-endian buffer.
|
|
47
|
+
* @param num - The BigInt to convert.
|
|
48
|
+
* @param width - The number of bytes that the resulting buffer should be.
|
|
49
|
+
* @returns A big-endian buffer representation of num.
|
|
50
|
+
*/
|
|
51
|
+
export function toBufferBE(num: bigint, width: number): Buffer {
|
|
52
|
+
if (num < BigInt(0)) {
|
|
53
|
+
throw new Error(`Cannot convert negative bigint ${num.toString()} to buffer with toBufferBE.`);
|
|
54
|
+
}
|
|
55
|
+
const hex = num.toString(16);
|
|
56
|
+
const buffer = Buffer.from(hex.padStart(width * 2, '0').slice(0, width * 2), 'hex');
|
|
57
|
+
if (buffer.length > width) {
|
|
58
|
+
throw new Error(`Number ${num.toString(16)} does not fit in ${width}`);
|
|
59
|
+
}
|
|
60
|
+
return buffer;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Converts a BigInt to its hex representation.
|
|
65
|
+
* @param num - The BigInt to convert.
|
|
66
|
+
* @param padTo32 - Whether to pad the resulting string to 32 bytes.
|
|
67
|
+
* @returns An even-length 0x-prefixed string.
|
|
68
|
+
*/
|
|
69
|
+
export function toHex(num: bigint, padTo32 = false): `0x${string}` {
|
|
70
|
+
const str = num.toString(16);
|
|
71
|
+
const targetLen = str.length % 2 === 0 ? str.length : str.length + 1;
|
|
72
|
+
const paddedStr = str.padStart(padTo32 ? 64 : targetLen, '0');
|
|
73
|
+
return `0x${paddedStr}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Converts a hex string to a buffer. Throws if input is not a valid hex string.
|
|
78
|
+
* @param value - The hex string to convert. May be 0x prefixed or not.
|
|
79
|
+
* @returns A buffer.
|
|
80
|
+
*/
|
|
81
|
+
export function fromHex(value: string): Buffer {
|
|
82
|
+
const hexRegex = /^(0x)?[0-9a-fA-F]*$/;
|
|
83
|
+
if (!hexRegex.test(value) || value.length % 2 !== 0) {
|
|
84
|
+
throw new Error(`Invalid hex string: ${value}`);
|
|
85
|
+
}
|
|
86
|
+
return Buffer.from(value.replace(/^0x/i, ''), 'hex');
|
|
87
|
+
}
|