Skip to content

Commit

Permalink
[book] Sui Move by Example (#3126)
Browse files Browse the repository at this point in the history
- adds a book to the repo
- sets a layout + structure
- fills in main parts of the sui move
  • Loading branch information
damirka authored Jul 11, 2022
1 parent 378106d commit 1c1a8c3
Show file tree
Hide file tree
Showing 47 changed files with 959 additions and 0 deletions.
2 changes: 2 additions & 0 deletions doc/book/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
book
.DS_Store
7 changes: 7 additions & 0 deletions doc/book/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Sui Move by Example

This is the home for Sui Move by Example book.

## Contributions

Feel free to contribute to the book by submitting a pull request.
11 changes: 11 additions & 0 deletions doc/book/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[book]
title = "Sui Move by Example"
description = "Handy collection of Examples for Sui blockchain. Made with love by MystenLabs"
authors = ["damirka"]
language = "en"
multilingual = false
src = "src"

[output.html]
git-repository-url = "https://github.com/MystenLabs/sui"
git-repository-icon = "fa-github"
1 change: 1 addition & 0 deletions doc/book/examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
9 changes: 9 additions & 0 deletions doc/book/examples/Move.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "sui-by-example"
version = "0.1.0"

[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework", rev = "main" }

[addresses]
examples = "0x0"
3 changes: 3 additions & 0 deletions doc/book/examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Sui Move Examples

This directory contains actual samples of the Move code used in the Sui Move by Example book.
6 changes: 6 additions & 0 deletions doc/book/examples/sources/basics/bag.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

module examples::bag_example {

}
75 changes: 75 additions & 0 deletions doc/book/examples/sources/basics/custom-transfer.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

module examples::restricted_transfer {
use sui::tx_context::{Self, TxContext};
use sui::balance::{Self, Balance};
use sui::coin::{Self, Coin};
use sui::id::VersionedID;
use sui::transfer;
use sui::sui::SUI;

/// For when paid amount is not equal to the transfer price.
const EWrongAmount: u64 = 0;

/// A Capability that allows bearer to create new `TitleDeed`s.
struct GovernmentCapability has key { id: VersionedID }

/// An object that marks a property ownership. Can only be issued
/// by an authority.
struct TitleDeed has key {
id: VersionedID,
// ... some additional fields
}

/// A centralized registry that approves property ownership
/// transfers and collects fees.
struct LandRegistry has key {
id: VersionedID,
balance: Balance<SUI>,
fee: u64
}

/// Create a `LandRegistry` on module init.
fun init(ctx: &mut TxContext) {
transfer::transfer(GovernmentCapability {
id: tx_context::new_id(ctx)
}, tx_context::sender(ctx));

transfer::share_object(LandRegistry {
id: tx_context::new_id(ctx),
balance: balance::zero<SUI>(),
fee: 10000
})
}

/// Create `TitleDeed` and transfer it to the property owner.
/// Only owner of the `GovernmentCapability` can perform this action.
public entry fun issue_title_deed(
_: &GovernmentCapability,
for: address,
ctx: &mut TxContext
) {
transfer::transfer(TitleDeed {
id: tx_context::new_id(ctx)
}, for)
}

/// A custom transfer function. Required due to `TitleDeed` not having
/// a `store` ability. All transfers of `TitleDeed`s have to go through
/// this function and pay a fee to the `LandRegistry`.
public entry fun transfer_ownership(
registry: &mut LandRegistry,
paper: TitleDeed,
fee: Coin<SUI>,
to: address,
) {
assert!(coin::value(&fee) == registry.fee, EWrongAmount);

// add a payment to the LandRegistry balance
balance::join(&mut registry.balance, coin::into_balance(fee));

// finally call the transfer function
transfer::transfer(paper, to)
}
}
26 changes: 26 additions & 0 deletions doc/book/examples/sources/basics/entry-functions.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

module examples::object {
use sui::transfer;
use sui::id::VersionedID;
use sui::tx_context::{Self, TxContext};

struct Object has key {
id: VersionedID
}

/// If function is defined as public - any module can call it.
/// Non-entry functions are also allowed to have return values.
public fun create(ctx: &mut TxContext): Object {
Object { id: tx_context::new_id(ctx) }
}

/// Entrypoints can't have return values as they can only be called
/// directly in a transaction and the returned value can't be used.
/// However, `entry` without `public` disallows calling this method from
/// other Move modules.
entry fun create_and_transfer(to: address, ctx: &mut TxContext) {
transfer::transfer(create(ctx), to)
}
}
93 changes: 93 additions & 0 deletions doc/book/examples/sources/basics/events.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

/// Extended example of a shared object. Now with addition of events!
module examples::donuts_with_events {
use sui::transfer;
use sui::sui::SUI;
use sui::coin::{Self, Coin};
use sui::id::{Self, ID, VersionedID};
use sui::balance::{Self, Balance};
use sui::tx_context::{Self, TxContext};

// This is the only dependency you need for events.
use sui::event;

/// For when Coin balance is too low.
const ENotEnough: u64 = 0;

/// Capability that grants an owner the right to collect profits.
struct ShopOwnerCap has key { id: VersionedID }

/// A purchasable Donut. For simplicity's sake we ignore implementation.
struct Donut has key { id: VersionedID }

struct DonutShop has key {
id: VersionedID,
price: u64,
balance: Balance<SUI>
}

// ====== Events ======

/// For when someone has purchased a donut.
struct DonutBought has copy, drop {
id: ID
}

/// For when DonutShop owner has collected profits.
struct ProfitsCollected has copy, drop {
amount: u64
}

// ====== Functions ======

fun init(ctx: &mut TxContext) {
transfer::transfer(ShopOwnerCap {
id: tx_context::new_id(ctx)
}, tx_context::sender(ctx));

transfer::share_object(DonutShop {
id: tx_context::new_id(ctx),
price: 1000,
balance: balance::zero()
})
}

/// Buy a donut.
public entry fun buy_donut(
shop: &mut DonutShop, payment: &mut Coin<SUI>, ctx: &mut TxContext
) {
assert!(coin::value(payment) >= shop.price, ENotEnough);

let coin_balance = coin::balance_mut(payment);
let paid = balance::split(coin_balance, shop.price);
let id = tx_context::new_id(ctx);

balance::join(&mut shop.balance, paid);

// Emit the event using future object's ID.
event::emit(DonutBought { id: *id::inner(&id) });
transfer::transfer(Donut { id }, tx_context::sender(ctx))
}

/// Consume donut and get nothing...
public entry fun eat_donut(d: Donut) {
let Donut { id } = d;
id::delete(id);
}

/// Take coin from `DonutShop` and transfer it to tx sender.
/// Requires authorization with `ShopOwnerCap`.
public entry fun collect_profits(
_: &ShopOwnerCap, shop: &mut DonutShop, ctx: &mut TxContext
) {
let amount = balance::value(&shop.balance);
let profits = coin::take(&mut shop.balance, amount, ctx);

// simply create new type instance and emit it
event::emit(ProfitsCollected { amount });

transfer::transfer(profits, tx_context::sender(ctx))
}
}
23 changes: 23 additions & 0 deletions doc/book/examples/sources/basics/init-function.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

module examples::one_timer {
use sui::transfer;
use sui::id::VersionedID;
use sui::tx_context::{Self, TxContext};

/// The one of a kind - created in the module initializer.
struct CreatorCapability has key {
id: VersionedID
}

/// This function is only called once on module publish.
/// Use it to make sure something has happened only once, like
/// here - only module author will own a version of a
/// `CreatorCapability` struct.
fun init(ctx: &mut TxContext) {
transfer::transfer(CreatorCapability {
id: tx_context::new_id(ctx),
}, tx_context::sender(ctx))
}
}
3 changes: 3 additions & 0 deletions doc/book/examples/sources/basics/owned-objects.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

82 changes: 82 additions & 0 deletions doc/book/examples/sources/basics/shared-object.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

/// Unlike `Owned` objects, `Shared` ones can be accessed by anyone on the
/// network. Extended functionality and accessibility of this kind of objects
/// requires additional effort by securing access if needed.
module examples::donuts {
use sui::transfer;
use sui::sui::SUI;
use sui::coin::{Self, Coin};
use sui::id::{Self, VersionedID};
use sui::balance::{Self, Balance};
use sui::tx_context::{Self, TxContext};

/// For when Coin balance is too low.
const ENotEnough: u64 = 0;

/// Capability that grants an owner the right to collect profits.
struct ShopOwnerCap has key { id: VersionedID }

/// A purchasable Donut. For simplicity's sake we ignore implementation.
struct Donut has key { id: VersionedID }

/// A shared object. `key` ability is required.
struct DonutShop has key {
id: VersionedID,
price: u64,
balance: Balance<SUI>
}

/// Init function is often ideal place for initializing
/// a shared object as it is called only once.
///
/// To share an object `transfer::share_object` is used.
fun init(ctx: &mut TxContext) {
transfer::transfer(ShopOwnerCap {
id: tx_context::new_id(ctx)
}, tx_context::sender(ctx));

// Share the object to make it accessible to everyone!
transfer::share_object(DonutShop {
id: tx_context::new_id(ctx),
price: 1000,
balance: balance::zero()
})
}

/// Entry function available to everyone who owns a Coin.
public entry fun buy_donut(
shop: &mut DonutShop, payment: &mut Coin<SUI>, ctx: &mut TxContext
) {
assert!(coin::value(payment) >= shop.price, ENotEnough);

// Take amount = `shop.price` from Coin<SUI>
let coin_balance = coin::balance_mut(payment);
let paid = balance::split(coin_balance, shop.price);

// Put the coin to the Shop's balance
balance::join(&mut shop.balance, paid);

transfer::transfer(Donut {
id: tx_context::new_id(ctx)
}, tx_context::sender(ctx))
}

/// Consume donut and get nothing...
public entry fun eat_donut(d: Donut) {
let Donut { id } = d;
id::delete(id);
}

/// Take coin from `DonutShop` and transfer it to tx sender.
/// Requires authorization with `ShopOwnerCap`.
public entry fun collect_profits(
_: &ShopOwnerCap, shop: &mut DonutShop, ctx: &mut TxContext
) {
let amount = balance::value(&shop.balance);
let profits = coin::take(&mut shop.balance, amount, ctx);

transfer::transfer(profits, tx_context::sender(ctx))
}
}
28 changes: 28 additions & 0 deletions doc/book/examples/sources/basics/strings.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

module examples::strings {
use sui::id::VersionedID;
use sui::tx_context::{Self, TxContext};

// Use this dependency to get a type wrapper for UTF8 Strings
use sui::utf8::{Self, String};

/// A dummy Object that holds a String type
struct Name has key, store {
id: VersionedID,

/// Here it is - the String type
name: String
}

/// Create a name Object by passing raw bytes
public fun issue_name_nft(
name_bytes: vector<u8>, ctx: &mut TxContext
): Name {
Name {
id: tx_context::new_id(ctx),
name: utf8::string_unsafe(name_bytes)
}
}
}
Loading

0 comments on commit 1c1a8c3

Please sign in to comment.