Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(docs): Documenting noir codegen #4454

Merged
merged 9 commits into from
Apr 2, 2024
135 changes: 135 additions & 0 deletions docs/docs/getting_started/tooling/noir_codegen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
title: Noir Codegen for Typescript
description: Learn how to use Noir codegen to generate Typescript bindings
keywords: [Nargo, Noir, compile, TypeScript]
sidebar_position: 2
---

You can generate TypeScript bindings with `noir_codegen`, allowing for easier and faster integration of your Noir circuits into TypeScript projects.
jzaki marked this conversation as resolved.
Show resolved Hide resolved

It is used in conjunction with `nargo export` which generates JSON for specified functions in a Noir library (not binary or contract circuits).
jzaki marked this conversation as resolved.
Show resolved Hide resolved

## Installation

You can install `noir_codegen` into your project using `yarn` or `npm`:
jzaki marked this conversation as resolved.
Show resolved Hide resolved

```bash
yarn add @noir-lang/noir_codegen
```

or

```bash
npm install @noir-lang/noir_codegen
```
## Usage

### Export ABI of specified functions

Use the `#[export]` macro to indicate which functions in the noir library that you'd like to export.
```rust
#[export]
fn your_function(...
```

The following command, when run from the directory with `Nargo.toml`, will create a folder with a .json file per exported function:
jzaki marked this conversation as resolved.
Show resolved Hide resolved

```bash
jzaki marked this conversation as resolved.
Show resolved Hide resolved
nargo export
jzaki marked this conversation as resolved.
Show resolved Hide resolved
jzaki marked this conversation as resolved.
Show resolved Hide resolved
```
jzaki marked this conversation as resolved.
Show resolved Hide resolved
The .json files live in a new `exports` directory.
jzaki marked this conversation as resolved.
Show resolved Hide resolved

You can also specify the directory of Noir programs using `--program-dir` as follows:
jzaki marked this conversation as resolved.
Show resolved Hide resolved

```bash
nargo export --program-dir=./path/to/your/noir/program
```

### Run noir-codegen

The `noir-codegen` command, pass the path of your exported JSON file(s) (wildcard characters accepted too, `*.json`). :
jzaki marked this conversation as resolved.
Show resolved Hide resolved

```bash
yarn noir-codegen ./export/your_function.json
```

jzaki marked this conversation as resolved.
Show resolved Hide resolved
An `exports` directory is created with an index.ts file containing all exported functions.
jzaki marked this conversation as resolved.
Show resolved Hide resolved

You can optionally specify an output dir for your Typescript bindings to live with `--out-dir`:
jzaki marked this conversation as resolved.
Show resolved Hide resolved

```bash
yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir
```

jzaki marked this conversation as resolved.
Show resolved Hide resolved

## Example

For example, if you have a Noir program like this:

```rust
struct MyStruct {
foo: bool,
bar: [str<5>; 3],
baz: Field
}

struct NestedStruct {
foo: MyStruct,
bar: [MyStruct; 3],
baz: u64
}
#[export]
fn exported_function_foo(x: u64, y: u64, array: [u8; 5], my_struct: NestedStruct, string: str<5>) -> (u64, u64, MyStruct) {
assert(array.len() == 5);
assert(my_struct.foo.foo);
assert(string == "12345");

print(x);
assert(x < y);
(x + y, 3, my_struct.foo)
}

fn unexported_function(x: u64, y: u64) {

Check warning on line 92 in docs/docs/getting_started/tooling/noir_codegen.md

View workflow job for this annotation

GitHub Actions / Documentation

Unknown word (unexported)
assert(x != y);
}
```

After following the usage instructions, you will have an `index.ts` that looks like this:
jzaki marked this conversation as resolved.
Show resolved Hide resolved

```typescript
/* Autogenerated file, do not edit! */

/* eslint-disable */

import { Noir, InputMap, CompiledCircuit, ForeignCallHandler } from "@noir-lang/noir_js"

export { ForeignCallHandler } from "@noir-lang/noir_js"

export type u64 = string;
export type u8 = string | number;
export type Field = string;

export type MyStruct = {
foo: boolean;
bar: string[];
baz: Field;
};

export type NestedStruct = {
foo: MyStruct;
bar: MyStruct[];
baz: u64;
};


export const exported_function_foo_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"array","type":{"kind":"array","length":5,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"my_struct","type":{"kind":"struct","path":"NestedStruct","fields":[{"name":"foo","type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}},{"name":"baz","type":{"kind":"field"}}]}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}},{"name":"baz","type":{"kind":"field"}}]}}},{"name":"baz","type":{"kind":"integer","sign":"unsigned","width":64}}]},"visibility":"private"},{"name":"string","type":{"kind":"string","length":5},"visibility":"private"}],"param_witnesses":{"array":[{"start":2,"end":7}],"my_struct":[{"start":7,"end":76}],"string":[{"start":76,"end":81}],"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"integer","sign":"unsigned","width":64},{"kind":"integer","sign":"unsigned","width":64},{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}},{"name":"baz","type":{"kind":"field"}}]}]},"visibility":"private"},"return_witnesses":[83,84,85,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]},"bytecode":"H4sIAAAAAAAA/9Wbe3PbRBTFV3Gabiw7cZynQwFT2vIsSJZt2byahlLKo9CkhP+T2B46A6TT8dBPxvcjVw+4OV0sdXy1I++MR3skZ+9PR2tptdl7opT6VcXFufwsJfUDph3Q9NFMV0Avg74GegW0Br0KugraBV0DXQe9BnoddAP0Bugm6E3QW6C3Qe+A3kvqqW7B8X3Qb4C+AfpN0G+Bfht0G/Q7oG+Cfhf0LdC3Qd8B/R7oD+D8P4TjH4H+GPRd0J+A/hS0B9oH3QEdgO6C7oHugw5BD0B/Buf/ORz/AvSXoL8CfQ/0Aej7oA9Bfw36AehvQD8E/S3oR6C/A/1DwsiLk2zT/d58xb/O2gq8frc7DjtjP/BPvc7wbNDzur2z/sAf+L1Bb9QZBMF40B2Ew7Nh6A39bjD2J71hMEkaK5LzRwHO8YTKqFDOx2Kc55MiOX+S4xwXyfmzHOeoSM4ncpznFcZXJLNgW//+pv5Otppxt6XidD2fxkTRwMng0RI7lm4prpseY/vpvreS7KJxjbN8tS3irzDfDyT4L4tmcdti7XZ6Ljt1xbgVXIe0rLDzvCbO4/nFnGfs33XGLtNueJa2l5Zl8KnOjvP4ugDvHBY3bZtfL4wt50OHhnjRe8UsH1YNLKuWfVg1xJbzoR/1h2qGD1UDS9WyD1VDbEEfhtSGm+GDa2BxLfvgGmIL+hCNcWoZPtQMLDXLPtQMsQV96KbnOsuHuoGlbtkHzpiXV5eAV0NdJnZwSm2sZfiwZmBZs+wDZ8zLq0vAq6EuEzukKZRoHm6WD+sGlnXLPnDGvLxuCXg11GVihzQ1Fr1XzPKhYWBpWPaBM+blrZaAV0NdJnafpiSjee1ZPmwYWDYs+8AZ8/K6JeDVUJeJ3Y/uk80MH5oGlqZlHzhjXt7agvFWF4zXLQGvhrpM7DAar29m+LBpYNm07ANnzMu7sWC8jQXjLYO/GuoyscNonmsrw4ctA8uWZR84Y15eXQJeDXWZ2J1zamM7w4dtA8u2ZR84Y15eXQJeDXWZ2GE0rt7J8GHHwLJj2QfOmJe3umC8tQXjbZaAV0NdJnaflryo3Qwfdg0su5Z94Ix5efWC8dZLwKuhLhM7oKVX0Xq6WT7sGVj2LPuwZ4gt6EP0PtTK8KFlYGlZ9qFliC34PI7Wwuxn+LBvYNm37EMaj56x6TqF5y+e/TlVUPjihwqrpws/HPad24bvmhZPOEzzv1lVhgU6B8nWm6/4FQatDCciFYe3Ne/KvzlWyPi4w3DqYm1zX4+S7bH6r7etGPxOi8P2UWc5hGPp1mF/f6iudkD8jvM/7bgGjoZhX2GdMD3ZY/XqEtRl4Vi8LcmO+JptedCWfyTIdayK+YE4cC3m5TySu65XOCsF9hlvvuLP0Wde8e+poH/pb5C3WdR1/0WOOyiS80S4Dx0B61LSV+keR8MNeiDQcr90mRkNQ+jmTK/Q6RIE+vct3ZxpupReVWm6kKaeaBqDXtloOE1DSRpG0XCG0lQoNYXSUSgFhdJO2ipOL7mp4jSSWyoecdxRcVrI+ypOB6EUEEr7oFSPuypO6aA0Dvqx0QnRvCZdABrn0v/EaNxPcy/0nklruSilgtIoKHWC0iUoReJe4ul9FT+MKM3hgYrTGR6qOG3hkYrTE75XcVoCLcd/fPmhZeS0RPsJ85FPl87jGfV76pcn6uqD7mmyvZFsT6fT8R/Pp+3pRft0NGq/fDb9rX3x1/jF5PeLl+ofXhoRQLg1AAA="};
jzaki marked this conversation as resolved.
Show resolved Hide resolved

export async function exported_function_foo(x: u64, y: u64, array: u8[], my_struct: NestedStruct, string: string, foreignCallHandler?: ForeignCallHandler): Promise<[u64, u64, MyStruct]> {
const program = new Noir(exported_function_foo_circuit);
const args: InputMap = { x, y, array, my_struct, string };
const { returnValue } = await program.execute(args, foreignCallHandler);
return returnValue as [u64, u64, MyStruct];
}
```

As you can see, `exported_function_foo()` is now readily available to us in Typescript, and `unexported_function()` is not.

Check warning on line 135 in docs/docs/getting_started/tooling/noir_codegen.md

View workflow job for this annotation

GitHub Actions / Documentation

Unknown word (unexported)
Loading