1"use strict";(globalThis.webpackChunkdocs=globalThis.webpackChunkdocs||[]).push([[3386],{31644(e,n,r){r.r(n),r.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>p,frontMatter:()=>s,metadata:()=>i,toc:()=>d});const i=JSON.parse('{"id":"tooling/noir_codegen","title":"Noir Codegen for TypeScript","description":"Learn how to use Noir codegen to generate TypeScript bindings","source":"@site/versioned_docs/version-v1.0.0-rc.1/tooling/noir_codegen.md","sourceDirName":"tooling","slug":"/tooling/noir_codegen","permalink":"/docs/v1.0.0-rc.1/tooling/noir_codegen","draft":false,"unlisted":false,"editUrl":"https://github.com/noir-lang/noir/edit/master/docs/versioned_docs/version-v1.0.0-rc.1/tooling/noir_codegen.md","tags":[],"version":"v1.0.0-rc.1","frontMatter":{"title":"Noir Codegen for TypeScript","description":"Learn how to use Noir codegen to generate TypeScript bindings","keywords":["Nargo","Noir","compile","TypeScript"]},"sidebar":"sidebar","previous":{"title":"Dev Containers","permalink":"/docs/v1.0.0-rc.1/tooling/devcontainer"},"next":{"title":"How to use Oracles","permalink":"/docs/v1.0.0-rc.1/guides/how_to_use_oracles"}}');var o=r(74848),t=r(28453);
1const s={title:"Noir Codegen for TypeScript",description:"Learn how to use Noir codegen to generate TypeScript bindings",keywords:["Nargo","Noir","compile","TypeScript"]},c=void 0,a={},d=[{value:"Installation",id:"installation",level:2},{value:"Your TypeScript project",id:"your-typescript-project",level:3},{value:"Add TypeScript module - <code>noir_codegen</code>",id:"add-typescript-module---noir_codegen",level:3},{value:"Nargo library",id:"nargo-library",level:3},{value:"Usage",id:"usage",level:2},{value:"Export ABI of specified functions",id:"export-abi-of-specified-functions",level:3},{value:"Generate TypeScript bindings from exported functions",id:"generate-typescript-bindings-from-exported-functions",level:3},{value:"Example .nr function to .ts output",id:"example-nr-function-to-ts-output",level:2}];function l(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,t.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.p,{children:"When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained."}),"\n",(0,o.jsx)(n.p,{children:"Now you can generate TypeScript bindings for your Noir programs in two steps:"}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsxs)(n.li,{children:["Exporting Noir functions using ",(0,o.jsx)(n.code,{children:"nargo export"})]}),"\n",(0,o.jsxs)(n.li,{children:["Using the TypeScript module ",(0,o.jsx)(n.code,{children:"noir_codegen"})," to generate TypeScript binding"]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Note:"})," you can only export functions from a Noir ",(0,o.jsx)(n.em,{children:"library"})," (not binary or contract program types)."]}),"\n",(0,o.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,o.jsx)(n.h3,{id:"your-typescript-project",children:"Your TypeScript project"}),"\n",(0,o.jsxs)(n.p,{children:["If you don't already have a TypeScript project you can add the module with ",(0,o.jsx)(n.code,{children:"yarn"})," (or ",(0,o.jsx)(n.code,{children:"npm"}),"), then initialize it:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"yarn add typescript -D\nnpx tsc --init\n"})}),"\n",(0,o.jsxs)(n.h3,{id:"add-typescript-module---noir_codegen",children:["Add TypeScript module - ",(0,o.jsx)(n.code,{children:"noir_codegen"})]}),"\n",(0,o.jsx)(n.p,{children:"The following command will add the module to your project's devDependencies:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"yarn add @noir-lang/noir_codegen -D\n"})}),"\n",(0,o.jsx)(n.h3,{id:"nargo-library",children:"Nargo library"}),"\n",(0,o.jsxs)(n.p,{children:["Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the ",(0,o.jsx)(n.a,{href:"/docs/v1.0.0-rc.1/installation",children:"installation guide"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["If you're in a new project, make a ",(0,o.jsx)(n.code,{children:"circuits"})," folder and create a new Noir library:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"mkdir circuits && cd circuits\nnargo new --lib myNoirLib\n"})}),"\n",(0,o.jsx)(n.h2,{id:"usage",children:"Usage"}),"\n",(0,o.jsx)(n.h3,{id:"export-abi-of-specified-functions",children:"Export ABI of specified functions"}),"\n",(0,o.jsxs)(n.p,{children:["First go to the ",(0,o.jsx)(n.code,{children:".nr"})," files in your Noir library, and add the ",(0,o.jsx)(n.code,{children:"#[export]"})," macro to each function that you want to use in TypeScript."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:"#[export]\nfn your_function(...\n"})}),"\n",(0,o.jsxs)(n.p,{children:["From your Noir library (where ",(0,o.jsx)(n.code,{children:"Nargo.toml"})," is), run the following command:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"nargo export\n"})}),"\n",(0,o.jsxs)(n.p,{children:["You will now have an ",(0,o.jsx)(n.code,{children:"export"})," directory with a .json file per exported function."]}),"\n",(0,o.jsxs)(n.p,{children:["You can also specify the directory of Noir programs using ",(0,o.jsx)(n.code,{children:"--program-dir"}),", for example:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"nargo export --program-dir=./circuits/myNoirLib\n"})}),"\n",(0,o.jsx)(n.h3,{id:"generate-typescript-bindings-from-exported-functions",children:"Generate TypeScript bindings from exported functions"}),"\n",(0,o.jsxs)(n.p,{children:["To use the ",(0,o.jsx)(n.code,{children:"noir-codegen"})," package we added to the TypeScript project:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"yarn noir-codegen ./export/your_function.json\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This creates an ",(0,o.jsx)(n.code,{children:"exports"})," directory with an ",(0,o.jsx)(n.code,{children:"index.ts"})," file containing all exported functions."]}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Note:"})," adding ",(0,o.jsx)(n.code,{children:"--out-dir"})," allows you to specify an output dir for your TypeScript bindings to go. Eg:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir\n"})}),"\n",(0,o.jsx)(n.h2,{id:"example-nr-function-to-ts-output",children:"Example .nr function to .ts output"}),"\n",(0,o.jsx)(n.p,{children:"Consider a Noir library with this function:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:"#[export]\nfn is_equal(x: Field, y: Field) -> bool {\n x == y\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["After the export and codegen steps, you should have an ",(0,o.jsx)(n.code,{children:"index.ts"})," like:"]}
1),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-typescript",children:'export type Field = string;\n\n\nexport const is_equal_circuit: CompiledCircuit = \n{"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"}},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"};\n\nexport async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise<boolean> {\n const program = new Noir(is_equal_circuit);\n const args: InputMap = { x, y };\n const { returnValue } = await program.execute(args, foreignCallHandler);\n return returnValue as boolean;\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["Now the ",(0,o.jsx)(n.code,{children:"is_equal()"})," function and relevant types are readily available for use in TypeScript."]})]})}function p(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},28453(e,n,r){r.d(n,{R:()=>s,x:()=>c});var i=r(96540);const o={},t=i.createContext(o);function s(e){const n=i.useContext(t);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.