diff --git a/yarn-project/foundation/src/abi/abi.ts b/yarn-project/foundation/src/abi/abi.ts index a25a802dace9..160be402bff1 100644 --- a/yarn-project/foundation/src/abi/abi.ts +++ b/yarn-project/foundation/src/abi/abi.ts @@ -309,6 +309,20 @@ export type ContractNote = { * Type of the note (e.g., 'TransparentNote') */ typ: string; + /** + * Fields of the note. + */ + fields: NoteField[]; +}; + +/** Type representing a field of a note (e.g. `amount` in `TokenNote`). */ +export type NoteField = { + /** Name of the field (e.g. `amount`). */ + name: string; + /** Index where the note field starts in the serialized note array. */ + index: number; + /** Whether the field can be unset when creating the note (in the partial notes flow). */ + nullable: boolean; }; /** diff --git a/yarn-project/types/src/abi/contract_artifact.ts b/yarn-project/types/src/abi/contract_artifact.ts index b7484f0c0b9f..a474920eddf3 100644 --- a/yarn-project/types/src/abi/contract_artifact.ts +++ b/yarn-project/types/src/abi/contract_artifact.ts @@ -254,24 +254,41 @@ function getStorageLayout(input: NoirCompiledContract) { * @return A record of the note types and their ids */ function getNoteTypes(input: NoirCompiledContract) { - type t = { - kind: string; - fields: [{ kind: string; sign: boolean; value: string }, { kind: string; value: string }]; - }; - - const notes = input.outputs.globals.notes as t[]; + // The type is useless here as it does not give us any guarantee (e.g. `AbiValue` can be one of many different + // types) so we nuke it and later we manually check the values are as we expect. + const notes = input.outputs.globals.notes as any[]; if (!notes) { return {}; } return notes.reduce((acc: Record, note) => { - const name = note.fields[1].value as string; - // Note id is encoded as a hex string - const id = NoteSelector.fromField(Fr.fromString(note.fields[0].value)); + const noteFields = note.fields; + + // We find note type id by looking for respective kinds as each of them is unique + const rawNoteTypeId = noteFields.find((field: any) => field.kind === 'integer'); + const rawName = noteFields.find((field: any) => field.kind === 'string'); + const rawNoteFields = noteFields.find((field: any) => field.kind === 'struct'); + + if (!rawNoteTypeId || !rawName || !rawNoteFields) { + throw new Error(`Could not find note type id, name or fields for note ${note}`); + } + + const noteTypeId = NoteSelector.fromField(Fr.fromString(rawNoteTypeId.value)); + const name = rawName.value as string; + + // Note type id is encoded as a hex string + const fields = rawNoteFields.fields.map((field: any) => { + return { + name: field.name, + index: parseInt(field.value.fields[0].value.value, 16), + nullable: field.value.fields[1].value.value, + }; + }); acc[name] = { - id, + id: noteTypeId, typ: name, + fields, }; return acc; }, {});