diff --git a/docs/docs/dev_docs/dapps/tutorials/contract_deployment.md b/docs/docs/dev_docs/dapps/tutorials/contract_deployment.md index 6bcd4062724..90b607a846c 100644 --- a/docs/docs/dev_docs/dapps/tutorials/contract_deployment.md +++ b/docs/docs/dev_docs/dapps/tutorials/contract_deployment.md @@ -8,24 +8,35 @@ Follow the instructions [here](../../getting_started/noir_contracts.md) to insta ## Initialise nargo project -Create a new `contracts` folder, and from there, initialise a new project called `private_token`: +Create a new `contracts` folder, and from there, initialise a new project called `token`: ```sh mkdir contracts && cd contracts -nargo new --contract private_token +nargo new --contract token ``` -Then, open the `contracts/private_token/Nargo.toml` configuration file, and add the `aztec.nr` and `value_note` libraries as dependencies: +Then, open the `contracts/token/Nargo.toml` configuration file, and add the `aztec.nr` and `value_note` libraries as dependencies: ```toml [dependencies] aztec = { git="https://github.com/AztecProtocol/aztec-nr", tag="master", directory="aztec" } value_note = { git="https://github.com/AztecProtocol/aztec-nr", tag="master", directory="value-note" } +safe_math = { git="https://github.com/AztecProtocol/aztec-nr", tag="master", directory="safe-math" } ``` -Last, copy-paste the code from the `PrivateToken` contract into `contracts/private_token/main.nr`: +Last, copy-paste the code from the `Token` contract into `contracts/token/main.nr`: -#include_code all yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr rust +#include_code token_all yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr rust + +The `Token` contract also requires two helper files. Copy-them too: + +Create `contracts/token/types.nr` and copy-paste the following: + +#include_code token_types_all yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr rust + +Finally, create `contracts/token/util.nr` and copy-paste the following: + +#include_code token_util_all yarn-project/noir-contracts/src/contracts/token_contract/src/util.nr rust ## Compile your contract @@ -38,41 +49,26 @@ yarn add -D @aztec/cli Now run the following from your project root: ```sh -yarn aztec-cli compile contracts/private_token +yarn aztec-cli compile contracts/token ``` :::info If you are using Typescript, consider including the `--typescript` option to [generate type-safe wrappers](../../contracts/compiling.md#typescript-interfaces) for your contracts. ::: -This should have created an artifact `contracts/private_token/target/private_token-Main.json` with the interface and bytecode for your contract. - -## Adding a second contract - -For the purposes of this tutorial, we'll set up a second contract: a public token contract. Follow the same steps as above for initialising a new Nargo project, include the dependencies, and copy-paste the following code into `contracts/public_token/main.nr`: - -#include_code all yarn-project/noir-contracts/src/contracts/public_token_contract/src/main.nr rust - -Compile the contract with the CLI: - -```sh -yarn aztec-cli compile contracts/public_token -``` - -With both contracts ready, we'll now proceed to deployment. +This should have created an artifact `contracts/token/target/Token.json` with the interface and bytecode for your contract. ## Deploy your contracts Let's now write a script for deploying your contracts to the Sandbox. We'll create an RPC client, and then use the `ContractDeployer` class to deploy our contracts, and store the deployment address to a local JSON file. -Create a new file `src/deploy.mjs`, importing the contract artifacts we have generated plus the dependencies we'll need, and with a call to a `main` function that we'll populate in a second: +Create a new file `src/deploy.mjs`, with a call to a `main` function that we'll populate in a second: ```js // src/deploy.mjs -import { writeFileSync } from "fs"; -import { createAztecRpcClient, ContractDeployer } from "@aztec/aztec.js"; -import PrivateTokenArtifact from "../contracts/private_token/target/PrivateToken.json" assert { type: "json" }; -import PublicTokenArtifact from "../contracts/public_token/target/PublicToken.json" assert { type: "json" }; +import { writeFileSync } from 'fs'; +import { Contract, ContractDeployer, createAztecRpcClient, getSandboxAccountsWallets } from '@aztec/aztec.js'; +import TokenContractAbi from "../contracts/token/target/Token.json" assert { type: "json" }; async function main() {} @@ -82,17 +78,17 @@ main().catch((err) => { }); ``` -Now we can deploy the contracts by adding the following code to the `src/deploy.mjs` file. Here, we are using the `ContractDeployer` class with the compiled artifact to send a new deployment transaction. The `wait` method will block execution until the transaction is successfully mined, and return a receipt with the deployed contract address. +Now we will import the contract artifacts we have generated plus the dependencies we'll need, and then we can deploy the contracts by adding the following code to the `src/deploy.mjs` file. Here, we are using the `ContractDeployer` class with the compiled artifact to send a new deployment transaction. The `wait` method will block execution until the transaction is successfully mined, and return a receipt with the deployed contract address. #include_code dapp-deploy yarn-project/end-to-end/src/sample-dapp/deploy.mjs javascript -Note that the private token constructor expects an `owner` address to mint an initial set of tokens to. We are using the first account from the Sandbox for this. +Note that the token's `_initialize()` method expects an `owner` address to mint an initial set of tokens to. We are using the first account from the Sandbox for this. :::info If you are using the generated typescript classes, you can drop the generic `ContractDeployer` in favor of using the `deploy` method of the generated class, which will automatically load the artifact for you and type-check the constructor arguments: ```typescript -await PrivateToken.deploy(client, 100n, owner.address).send().wait(); +await Token.deploy(client).send().wait(); ``` ::: @@ -100,8 +96,7 @@ await PrivateToken.deploy(client, 100n, owner.address).send().wait(); Run the snippet above as `node src/deploy.mjs`, and you should see the following output, along with a new `addresses.json` file in your project root: ```text -Private token deployed to 0x2950b0f290422ff86b8ee8b91af4417e1464ddfd9dda26de8af52dac9ea4f869 -Public token deployed to 0x2b54f68fd1e18f7dcfa71e3be3c91bb06ecbe727a28d609e964c225a4b5549c8 +Token deployed to 0x2950b0f290422ff86b8ee8b91af4417e1464ddfd9dda26de8af52dac9ea4f869 ``` ## Next steps diff --git a/docs/docs/dev_docs/dapps/tutorials/contract_interaction.md b/docs/docs/dev_docs/dapps/tutorials/contract_interaction.md index 3f4508a2f2f..bf029bdea39 100644 --- a/docs/docs/dev_docs/dapps/tutorials/contract_interaction.md +++ b/docs/docs/dev_docs/dapps/tutorials/contract_interaction.md @@ -4,12 +4,12 @@ In this section, we'll write the logic in our app that will interact with the co ## Showing user balance -Let's start by showing our user balance for the private token across their accounts. To do this, we can leverage the `balance_of_private` unconstrained view function of the private token contract: +Let's start by showing our user's private balance for the token across their accounts. To do this, we can leverage the `balance_of_private` unconstrained view function of the token contract: #include_code balance_of_private yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr rust :::info -Note that this function will only return a valid response for accounts registered in the RPC Server, since it requires access to the [user's private state](../../wallets/main.md#private-state). In other words, you cannot query the balance of another user for a private token contract. +Note that this function will only return a valid response for accounts registered in the RPC Server, since it requires access to the [user's private state](../../wallets/main.md#private-state). In other words, you cannot query the private balance of another user for the token contract. ::: To do this, let's first initialise a new `Contract` instance using `aztec.js` that represents our deployed token contracts. Create a new `src/contracts.mjs` file with the imports for our artifacts and other dependencies: @@ -18,8 +18,7 @@ To do this, let's first initialise a new `Contract` instance using `aztec.js` th // src/contracts.mjs import { Contract } from "@aztec/aztec.js"; import { readFileSync } from "fs"; -import PrivateTokenArtifact from "../contracts/private_token/target/PrivateToken.json" assert { type: "json" }; -import PublicTokenArtifact from "../contracts/public_token/target/PublicToken.json" assert { type: "json" }; +import TokenContractAbi from "../contracts/token/target/Token.json" assert { type: "json" }; ``` And then add the following code for initialising the `Contract` instances: @@ -30,7 +29,7 @@ And then add the following code for initialising the `Contract` instances: You can use the typescript autogenerated interface instead of the generic `Contract` class to get type-safe methods. ::: -We can now get the private token instance in our main code in `src/index.mjs`, and query the private balance for each of the user accounts. To query a function, without sending a transaction, use the `view` function of the method: +We can now get the token instance in our main code in `src/index.mjs`, and query the private balance for each of the user accounts. To query a function, without sending a transaction, use the `view` function of the method: #include_code showPrivateBalances yarn-project/end-to-end/src/sample-dapp/index.mjs javascript @@ -46,7 +45,7 @@ Balance of 0x0e1f60e8566e2c6d32378bdcadb7c63696e853281be798c107266b8c3a88ea9b: 0 Now that we can see the balance for each user, let's transfer tokens from one account to another. To do this, we will first need access to a `Wallet` object. This wraps access to an RPC Server and also provides an interface to craft and sign transactions on behalf of one of the user accounts. -We can initialise a wallet using one of the `getAccount` methods from `aztec.js``, along with the corresponding signing and encryption keys: +We can initialise a wallet using one of the `getAccount` methods from `aztec.js`, along with the corresponding signing and encryption keys: ```js import { getSchnorrAccount } from "@aztec/aztec.js"; @@ -57,7 +56,13 @@ const wallet = await getSchnorrAccount( ).getWallet(); ``` -For ease of use, `aztec.js` also ships with a helper `getSandboxAccountsWallets` method that returns a wallet for each of the pre-initialised accounts in the Sandbox, so you can send transactions as any of them. We'll use one of these wallets to initialise the `Contract` instance that represents our private token contract, so every transaction sent through it will be sent through that wallet. +For ease of use, `aztec.js` also ships with a helper `getSandboxAccountsWallets` method that returns a wallet for each of the pre-initialised accounts in the Sandbox, so you can send transactions as any of them. + +```js +import { getSandboxAccountsWallets } from '@aztec/aztec.js'; +``` + +We'll use one of these wallets to initialise the `Contract` instance that represents our private token contract, so every transaction sent through it will be sent through that wallet. #include_code transferPrivateFunds yarn-project/end-to-end/src/sample-dapp/index.mjs javascript @@ -116,7 +121,7 @@ Balance of 0x226f8087792beff8d5009eb94e65d2a4a505b70baf4a9f28d33c8d620b0ba972: 0 Balance of 0x0e1f60e8566e2c6d32378bdcadb7c63696e853281be798c107266b8c3a88ea9b: 0 ``` -Public functions can emit [unencrypted public logs](../../contracts/events.md#unencrypted-events), which we can query via the RPC Server interface. In particular, the public token contract emits a generic `Coins minted` whenever the `mint` method is called: +Public functions can emit [unencrypted public logs](../../contracts/events.md#unencrypted-events), which we can query via the RPC Server interface. For example, here we have a `mint` method that emits a generic `Coins minted` whenever it is called: #include_code unencrypted_log yarn-project/noir-contracts/src/contracts/public_token_contract/src/main.nr rust @@ -124,12 +129,6 @@ We can extend our code by querying the logs emitted on the last block when the m #include_code showLogs yarn-project/end-to-end/src/sample-dapp/index.mjs javascript -Running the code again would now show an extra line with: - -```text -Log: Coins minted -``` - :::info At the time of this writing, there is no event-based mechanism in the `aztec.js` library to subscribe to events. The only option to consume them is to poll on every new block detected. This will change in a future version. ::: diff --git a/docs/docs/dev_docs/dapps/tutorials/testing.md b/docs/docs/dev_docs/dapps/tutorials/testing.md index d75b984686a..24da56dbf84 100644 --- a/docs/docs/dev_docs/dapps/tutorials/testing.md +++ b/docs/docs/dev_docs/dapps/tutorials/testing.md @@ -27,9 +27,9 @@ Create a new file `src/index.test.mjs` with the imports we'll be using and an em ```js import { createSandbox } from "@aztec/aztec-sandbox"; import { Contract, createAccount } from "@aztec/aztec.js"; -import PrivateTokenArtifact from "../contracts/private_token/target/PrivateToken.json" assert { type: "json" }; +import TokenContractAbi from "../contracts/token/target/Token.json" assert { type: "json" }; -describe("private token", () => {}); +describe("token", () => {}); ``` Let's set up our test suite. We'll start [a new Sandbox instance within the test](../../testing/testing.md#running-sandbox-in-the-nodejs-process), create two fresh accounts to test with, and deploy an instance of our contract. The `aztec-sandbox` and `aztec.js` provide the helper functions we need to do this: @@ -40,7 +40,7 @@ Note that, since we are starting a new Sandbox instance, we need to `stop` it in ## Writing our test -Now that we have a working test environment, we can write our first test for exercising the `transfer` function on the private token contract. We will use the same `aztec.js` methods we used when building our dapp: +Now that we have a working test environment, we can write our first test for exercising the `transfer` function on the token contract. We will use the same `aztec.js` methods we used when building our dapp: #include_code test yarn-project/end-to-end/src/sample-dapp/index.test.mjs javascript diff --git a/yarn-project/end-to-end/src/sample-dapp/deploy.mjs b/yarn-project/end-to-end/src/sample-dapp/deploy.mjs index 1fa4036fee5..9010da5a29b 100644 --- a/yarn-project/end-to-end/src/sample-dapp/deploy.mjs +++ b/yarn-project/end-to-end/src/sample-dapp/deploy.mjs @@ -12,12 +12,13 @@ async function main() { const [owner] = await getSandboxAccountsWallets(client); const token = await Contract.deploy(client, TokenContractAbi, []).send().deployed(); - await token.withWallet(owner).methods._initialize({ address: owner.getAddress() }).send().wait(); console.log(`Token deployed at ${token.address.toString()}`); - const addresses = { token: token.address.toString() }; + const addresses = { + token: token.address.toString(), + }; writeFileSync('addresses.json', JSON.stringify(addresses, null, 2)); } // docs:end:dapp-deploy diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr index 30c1d55b3ae..76c6a88ecb4 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr @@ -1,3 +1,4 @@ +// docs:start:token_all mod types; mod util; @@ -421,3 +422,4 @@ contract Token { } } +// docs:end:token_all diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr index d2deceb268f..438f7ab53d4 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr @@ -1,3 +1,4 @@ +// docs:start:token_types_all use dep::std::hash::pedersen; use dep::std::hash::pedersen_with_separator; use dep::aztec::note::{ @@ -125,4 +126,5 @@ global TransparentNoteMethods = NoteInterface { compute_nullifier, get_header, set_header, -}; \ No newline at end of file +}; +// docs:end:token_types_all \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/util.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/util.nr index 09d030e3318..701d0dd0527 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/util.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/util.nr @@ -1,3 +1,4 @@ +// docs:start:token_util_all use dep::std::hash::{pedersen_with_separator}; use dep::aztec::constants_gen::GENERATOR_INDEX__SIGNATURE_PAYLOAD; @@ -5,4 +6,5 @@ fn compute_message_hash(args: [Field; N]) -> Field { // @todo @lherskind We should probably use a separate generator for this, // to avoid any potential collisions with payloads. pedersen_with_separator(args, GENERATOR_INDEX__SIGNATURE_PAYLOAD)[0] -} \ No newline at end of file +} +// docs:end:token_util_all \ No newline at end of file