Skip to content

Commit

Permalink
Merge branch 'main' into spans_es
Browse files Browse the repository at this point in the history
  • Loading branch information
rcatalan98 authored Jul 12, 2023
2 parents 602a123 + 3fe842b commit a7533b0
Show file tree
Hide file tree
Showing 52 changed files with 1,459 additions and 156 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The objective of this tutorial is to quickly on-board new developers to Cairo. T

Go to webpage to learn how to install and write [Cairo](https://cairo-lang.org) in simple and direct steps.

If you want to add another example please submit a PR that adds a similar file to the [Hello World](https://github.com/lambdaclass/cairo-by-example/blob/main/content/examples/hello-world.md) in the [content/examples](https://github.com/lambdaclass/cairo-by-example/tree/main/content/examples) folder.
If you want to add another example please submit a PR that adds a similar file to the [Hello World](https://github.com/lambdaclass/cairo-by-example/blob/main/content/en/examples/hello-world.md) in the [content/examples](https://github.com/lambdaclass/cairo-by-example/tree/main/content/en/examples) folder.

Most of the CSS and hugo code was taken modified from [noir-by-example](https://github.com/sambarnes/noir-by-example/).
Most of the code is taken from [Cairo Book](https://cairo-book.github.io/) and community contributions.
Expand Down
2 changes: 1 addition & 1 deletion build/arch/.SRCINFO
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pkgbase = cairo-lang
pkgdesc = Cairo language installation
pkgver = 2.0.0
pkgrel = 1
pkgrel = 2
url = https://cairo-by-example.com/
arch = x86_64
license = MIT
Expand Down
14 changes: 11 additions & 3 deletions build/arch/PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,21 @@ build() {
}

package() {
mkdir -p $pkgdir/usr/bin/ $pkgdir/usr/lib/

mv cairo-$pkgver-$release/corelib/ $pkgdir/usr/lib/

pkgs=("cairo-run" "cairo-compile" "cairo-format" "cairo-language-server" "cairo-test" "sierra-compile" "starknet-compile" "starknet-sierra-compile")

mkdir -p $pkgdir/usr/bin/

for pkg in ${pkgs[@]}; do
mv cairo-$pkgver-$release/target/release/$pkg $pkgdir/usr/bin
mv cairo-$pkgver-$release/target/release/$pkg $pkgdir/usr/bin/
done

add_to_config
}

add_to_config() {
declare -A shells=( ["bash"]=".bashrc" ["fish"]=".config/fish/config.fish" ["zsh"]=".zshrc")

echo "export CARGO_MANIFEST_DIR=\"/usr/bin/corelib/\"" >> /home/$USER/${shells[$(basename $(echo $SHELL))]}
}
7 changes: 6 additions & 1 deletion build/homebrew/cairo-lang.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class CairoLang < Formula
desc "Cairo language installation"
depends_on "rust" => :optional
homepage "https://cairo-by-example.com/"
url "https://github.com/starkware-libs/cairo/archive/refs/tags/v2.0.0-rc4.tar.gz"
sha256 "e3dd3ce3f9ab5b69c44d01b13777d92516dcd830efb6a3d2cd46915d4f03e8a9"
Expand All @@ -12,6 +13,10 @@ def install
# Check for brewed rust
method = "brew" if exists("rustc")

if method.nil?
raise("Rust compiler not installed, please install it first!")
end

print("Detected Rust installation method: " + method.upcase + "\n")

if method == "manual"
Expand All @@ -20,9 +25,9 @@ def install
end

print(`rustup override set stable`)
print(`rustup update`)
print(`cargo build --all --release --manifest-path ./Cargo.toml`)

prefix.install Dir["./corelib/"]
bin.install "./target/release/cairo-compile"
bin.install "./target/release/cairo-format"
bin.install "./target/release/cairo-language-server"
Expand Down
93 changes: 93 additions & 0 deletions build/installer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/bin/bash

set -e

RST='\033[0m' # No Color, Reset.
YEL='\033[1;93m' # Yellow.
VIO='\033[1;95m' # Violet.
ERR='\033[1;31m' # Strong red.

# Check the operating system
os=$(uname -s)

# Cairo Version.
version="2.0.0-rc4"

case "$os" in

# Mac OS
Darwin)
echo -e "${YEL}--- Installing Cairo ${version} on Mac OS --- ${RST}"
if [[ ! $(command -v rustc) ]]; then
echo -e "${ERR}==>${RST} Rust compiler not found, please install it (homebrew or manually), and run the script again."
exit 1
fi
echo -e "${VIO}==>${RST} Downloading cairo-lang"
set -x
curl -o /tmp/cairo-lang.rb https://raw.githubusercontent.com/lambdaclass/cairo-by-example/main/build/homebrew/cairo-lang.rb && brew install --formula --build-from-source /tmp/cairo-lang.rb
set +x
corelib="$(brew --cellar cairo-lang)/$(brew list --versions cairo-lang | tr ' ' '\n' | tail -1)/corelib"
if [[ -f /Users/${USER}/.zshrc ]]; then
echo "export CARGO_MANIFEST_DIR=\"${corelib}\"" >> /Users/${USER}/.zshrc
echo "~/.zshrc has been populated with the required environment variable"
echo "For cairo to work in the current shell, you need to set it manually:"
echo "export CARGO_MANIFEST_DIR=\"${corelib}\""
elif [[ -f /Users/${USER}/.bashrc ]]; then
echo "export CARGO_MANIFEST_DIR=\"${corelib}\"" >> /Users/${USER}/.bashrc
echo "~/.bashrc has been populated with the required environment variable"
echo "For cairo to work in the current shell, you need to set it manually:"
echo "export CARGO_MANIFEST_DIR=\"${corelib}\""
else
echo "For cairo to work, please set the CARGO_MANIFEST_DIR environment variable in your shell of choice with the following value:"
echo "export CARGO_MANIFEST_DIR=\"${corelib}\""
fi
;;

# Linux
Linux)
distro=""
[[ ! -e /etc/os-release ]] && exit 1
source /etc/os-release
case "$ID" in
# XXX: Script for debian/ubuntu is not working (missing corelib/)
arch)
echo -e "${YEL}--- Installing Cairo ${version} on Arch Linux --- ${RST}"
[[ ! -e /usr/bin/yay ]] && echo -e "${ERR}No yay installation found. If you use another AUR helper, please install the cairo-lang package.${RST}"
set -x
yay -S cairo-lang
set +x
;;
# debian | ubuntu)
# [[ ! -e /etc/os-release ]] && exit 1
# echo -e "${YEL}--- Installing Cairo ${version} on Debian/Ubuntu --- ${RST}"
# echo -e "${VIO}==>${RST} Downloading .deb file..."
# set -x
# wget -O /tmp/cairo_${version}_amd64.deb https://github.com/lambdaclass/cairo-by-example/releases/download/v${version}/cairo_${version}-1_amd64.deb
# set +x
# echo -e "${VIO}==>${RST} Installing cairo-lang..."
# sudo dpkg -i /tmp/cairo_${version}_amd64.deb
# ;;
*)
echo -e "${YEL}--- Detected installation for unknown Linux distro --- ${RST}"
set -x
curl -L https://github.com/franalgaba/cairo-installer/raw/main/bin/cairo-installer | bash
set +x
;;
esac
;;

# Windows
CYGWIN* | MINGW* | MSYS*)
echo -e "${YEL}--- Installing Cairo ${version} on Windows --- ${RST}"
set -x
# TODO: Add command for Windows here
set +x
echo -e "${ERR} Windows installation is still WIP."
exit 1
;;

*)
echo -e "Unsupported operating system: $os"
exit 1
;;
esac
10 changes: 6 additions & 4 deletions content/en/examples/arrays.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ draft: false

# Arrays

You can create arrays in cairo with `ArrayTrait::new()` and add elements with the method `append`:
You can create arrays in cairo with `ArrayTrait::new()` and add elements with the method `append`:

```rust {.codebox}
use array::ArrayTrait;

fn get_array() -> Array<felt252> {
let mut numbers = ArrayTrait::new();
numbers.append(444);
numbers.append(555);

return numbers;
numbers
}
```

Expand Down Expand Up @@ -57,7 +59,7 @@ fn get_array() -> Array<felt252> {
numbers.append(444);
numbers.append(555);
return numbers;
numbers
}
#[test]
Expand All @@ -76,7 +78,7 @@ fn test_array_retrieve_elements() {
assert(first_element == 444, 'wrong first element');
assert(second_element == 555, 'wrong second element');
// array.get(2) will return None
// array.at(2) will cause an error
}
Expand Down
21 changes: 21 additions & 0 deletions content/en/examples/booleans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: "booleans"
weight: 85
draft: false
---

As with Boolean types in other programming languages, `bool`s have only two possible values: `true` and `false`.

```rust {.codebox}
fn main() {
let t: bool = true;
let true_expr = 5 == 5;
assert(t == true_expr, 'this is true');
let f: bool = false;
let false_expr = 7 == 5;
assert(f == false_expr, 'this is false');
}
```
As with other scalar types, they are one `felt252` in size.
8 changes: 7 additions & 1 deletion content/en/examples/clone_and_copy.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ From the ownership example:

```rust {.codebox}
use array::ArrayTrait;
use clone::Clone;
use array::ArrayTCloneImpl;

fn foo(arr: Array<u128>) {
// foo takes ownership of the array.
Expand All @@ -27,11 +29,14 @@ fn main() {
// foo(arr); <- fails to compile, as main doesn't own the array anymore
}
```
Try it out running `cairo-run clone_copy.cairo --available-gas 20000` in your terminal.

An example of deriving the Copy trait:

```rust {.codebox}
#[derive(Copy, Clone)]
use clone::Clone;

#[derive(Copy, Clone, Drop)]
struct Vector2 {
x: u32,
y: u32,
Expand All @@ -45,3 +50,4 @@ fn main() {
// now w is a copy of v, v is still accesible
}
```
Run the example with `cairo-run clone_copy_2.cairo --available-gas 20000` in your terminal.
130 changes: 130 additions & 0 deletions content/en/examples/contracts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
---
title: "contracts"
weight: 360
draft: false
---

#### Contracts

Contracts can be deployed to Starknet.

The contract modules are defined by adding a `#[starknet::contract]` attribute above the module definition:

```rust {.codebox}
#[starknet::contract]
mod Contract {
}
```

#### Storage

Inside a contract definition, you can define a storage, using the `#[storage]` attribute:

```rust {.codebox}
#[storage]
struct Storage {
token_supply: felt252,
decimals: u8
}
```

#### Interfaces

In order to interact with your contract, you'll want to define an interface, which gathers external (functions that mutate the storage) and view (functions that don't mutate the storage) function signatures under a trait. Traits use a generic argument, generally referring to the contract state. Static functions that do not use the storage or emit events do not require an additional argument. Interfaces are defined by adding a `#[starknet::interface]` attribute:

```rust {.codebox}
#[starknet::interface]
trait IContract<TContractState> {
fn increase_token_supply(ref self: TContractState, amount: felt252);
fn increase_decimals(ref self: TContractState, amount: u8);
fn get_token_supply(self: @TContractState) -> felt252;
}
```
#### Implementations

Functions that affect the contract state use a mutable reference to the `ContractState`: `ref self: TContractState `; while the functions that don't affect the state use: `self: @TContractState`.

And to implement this trait inside the contract, we use the `impl` keyword, with a `#[external(v0)]` attribute:

```rust {.codebox}
mod Contract {
#[storage]
struct Storage {
token_supply: felt252,
decimals: u8
}

#[external(v0)]
impl Contract of super::IContract<ContractState> {
fn increase_token_supply(ref self: ContractState, amount: felt252) { ... }
fn increase_decimals(ref self: ContractState, amount: u8) { ... }
fn get_token_supply(self: @ContractState) -> felt252 { ... }
}
}
```

#### Storage Access

In order to interact with the contract state, you can use `read` and `write` functions:

```rust {.codebox}
let current_balance = self.balance.read();
self.balance.write(current_balance + amount)
```

That can be used inside functions:

```rust {.codebox}
fn increase_token_supply(ref self: ContractState, amount: felt252) {
let current_token_supply = self.token_supply.read();
self.token_supply.write(current_token_supply + amount)
}
```

#### Constructors

When you deploy a contract, you can set its initial values using a constructor:

```rust {.codebox}
mod Contract {
#[constructor]
fn constructor(ref self: ContractState, initial_token_supply: felt252, initial_decimals: u8) {
self.token_supply.write(initial_token_supply);
self.decimals.write(initial_decimals);
}
}
```

#### Events definition

In Cairo2 all the contract events are unified under the `Event` enum:

```rust {.codebox}
#[event]
#[derive(Drop, starknet::Event)]
enum Event {
TokenSupplyIncreased: TokenSupplyIncreased,
DecimalsIncreased: DecimalsIncreased
}

#[derive(Drop, starknet::Event)]
struct TokenSupplyIncreased {
amount: felt252
}

#[derive(Drop, starknet::Event)]
struct DecimalsIncreased {
amount: u8
}
```

#### Emitting Events

In order to emit events, you can do the following:

```rust {.codebox}
fn increase_token_supply(ref self: ContractState, amount: felt252) {
...
self.emit(TokenSupplyIncreased { amount });
}
```
Loading

0 comments on commit a7533b0

Please sign in to comment.