Development on O1js in Mina
Building zkApps (zero-knowledge
applications) on the Mina Protocol using 01js is an exciting journey, especially for developers transitioning from Web2 or Web3 backgrounds. This guide will walk you through the process of creating a minimal currency contract, similar to Solidity’s smart contracts, but adapted for Mina and zero-knowledge proofs (ZKPs). By the end, you’ll have a functional zkApp called “Pengu Mina” that allows minting, transferring, and managing tokens.
What is 01js?
01js is a TypeScript library designed to simplify zkApp development on the Mina Protocol. It provides tools and abstractions to work with zero-knowledge proofs, enabling developers to build privacy-preserving and scalable decentralized applications.
What is Mina Protocol?
Mina is a lightweight blockchain that uses ZKPs to maintain a constant-sized blockchain (only 22 KB). This makes it highly efficient and accessible for developers and users alike. zkApps on Mina leverage ZKPs to enable private and verifiable computations.
Install zkApp CLI
To set up the necessary tooling, install the zkApp CLI globally:
npm install -g zkapp-cli
Initiate a New Project
Once you’ve completed the setup, it’s time to begin building your application.
Set up a New Directory:
Go to or create a directory where you have the necessary write permissions.
Start a New Project: Use the zk project command to generate the structure of your application:
zk project o1js-currency
Select project options:
When asked, choose “none” for the UI option:
? Create an accompanying UI project too? …
next
svelte
nuxt
empty
> none
Verify successful project creation: After running the command, you should see this output confirming the successful creation of your project:
✔ Create an accompanying UI project too? · none
✔ UI: Set up project
✔ Initialize Git repo
✔ Set up project
✔ NPM install
✔ NPM build contract
✔ Set project name
✔ Git init commit
Success!
Next steps:
cd 01-hello-world
git remote add origin <your-repo-url>
git push -u origin main
After running the zk project command, a new directory named o1js-currency
will be created, containing all the necessary scaffolding for your project. This includes essential tools like Prettier (for code formatting), ESLint (for static code analysis), and Jest (for testing).
To verify, navigate to the project directory and inspect its contents:
cd o1js-currency
ls
These are the following structures:
LICENSE
README.md
babel.config.cjs
build
config.json
jest-resolver.cjs
jest.config.js
keys
node_modules
package-lock.json
package.json
src
tsconfig.json
You’ll execute commands from the root directory of the o1js-currency
folder and write your smart contract code inside the src
directory. During the build or deployment process, updates will be compiled into JavaScript in the build
directory.
Preparing the Project:
First, clean up the default files that come with the project scaffold.
Remove Unnecessary Files:
To remove the default files, run the following commands:
rm src/Add.ts
rm src/Add.test.ts
rm src/interact.ts
Create New Files:
The next step is to set up the necessary files for your project. Create the following files:
zk file src/currency
touch src/main.ts
The zk file
command will create two files: src/currency.ts
and src/currency.test.ts
.
Modify src/index.ts
:
Open the src/index.ts
file in your preferred text editor and replace its existing content with:
import { currency } from './currency';
export { currency };
The src/index.ts
file acts as the main entry point for exporting the key components of your project.
Develop the zkApp Smart Contract
This is where the fun begins – creating your smart contract!
Implement the Contract:
In the src/currency.ts
file, you’ll define the logic for your zkApp currency. The example file provides line numbers and detailed code walkthroughs to assist you in the implementation.
Smart Contract Class: Detailed Explanation
The currency smart contract extends the TokenContract
class, enhancing it with state management features and additional functionality for a custom cryptocurrency. Below is a thorough breakdown of the implementation and its key components.
export class currency extends TokenContract {
@state(Field) name = State<Field>();
@state(Field) symbol = State<Field>();
@state(Field) totalSupply = State<Field>();
@state(Field) decimals = State<Field>();
@state(PublicKey) owner = State<PublicKey>();
@state(Field) circulatoryAmount = State<Field>();
}
Activation method
deploy(): Promise<void> {
super.deploy();
const permissionToEdit = Permissions.proof();
this.account.permissions.set({
...Permissions.default(),
editState: permissionToEdit,
setTokenSymbol: permissionToEdit,
send: permissionToEdit,
receive: permissionToEdit
});
return Promise.resolve();
}
The initialization method of a smart contract sets up its permissions upon deployment. It uses Permissions.proof()
to provide proof-based control, managing actions like state edits, token symbol updates, and the sending/receiving of tokens. This approach combines default permissions with specific allowances for sensitive operations, ensuring secure and flexible contract functionality.
Configuration
init() {
super.init();
this.name.set(stringToField("Pengu Mina"));
this.symbol.set(stringToField("P.M"));
this.account.tokenSymbol.set("P.M");
this.owner.set(users.owner.toPublicKey());
this.account.zkappUri.set("https://magenta-hollow-tiglon-795.mypinata.cloud/ipfs/bafybeig2mliemcvvx5yvdzo7ajsd34ys3i5lsauhbu7nrhqfmidkaqvrpi");
this.totalSupply.set(contract_int_vars.totalSupply);
this.circulatoryAmount.set(Field(0));
}
The initialization method configures the smart contract’s state values during deployment. It sets the token’s name and symbol using the stringToField
utility function, assigns the owner with the provided public key, and defines a metadata URI (zkappUri)
for external references like token details on IPFS. Additionally, it initializes the totalSupply
and sets the circulatoryAmount
to zero.
Conclusion
O1js streamlines the development of privacy-preserving zkApps on the Mina Protocol, allowing developers to build efficient applications with ease. Its integration of TypeScript and zk-SNARKs empowers the creation of scalable, secure blockchain solutions.