Skip to content

Commit

Permalink
[move] reorganize examples directory
Browse files Browse the repository at this point in the history
- Splitting the examples directory into several smaller directories with clearly defined themes
- Added a README to each dir with brief descriptions of the examples (including teasers of some coming soon)
- Minor cleanup/refactoring to prevent dependencies between example dirs
  • Loading branch information
sblackshear committed Mar 9, 2022
1 parent 2f50ab5 commit 6add802
Show file tree
Hide file tree
Showing 25 changed files with 459 additions and 130 deletions.
12 changes: 0 additions & 12 deletions sui_programmability/examples/Move.toml

This file was deleted.

12 changes: 12 additions & 0 deletions sui_programmability/examples/basics/Move.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "Basics"
version = "0.0.1"

[dependencies]
Sui = { local = "../../framework" }

[addresses]
Basics = "0x0"

[dev-addresses]
Basics = "0x0"
6 changes: 6 additions & 0 deletions sui_programmability/examples/basics/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Basics

Very basic examples to illustrate the nuts and bolts of programming in Sui.

* Object: a heavily commented example of a custom object.
* Sandwich: example of object exchange logic--combining ham and bread objects to produce a sandwich.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// An example of a custom object with comments explaining the relevant bits
module Examples::CustomObjectTemplate {
module Basics::Object {
use Sui::ID::VersionedID;
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/// Example of objects that can be combined to create
/// new objects
module Examples::CombinableObjects {
use Examples::TrustedCoin::EXAMPLE;
module Basics::Sandwich {
use Sui::Coin::{Self, Coin};
use Sui::ID::{Self, VersionedID};
use Sui::GAS::GAS;
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};

Expand All @@ -30,16 +30,16 @@ module Examples::CombinableObjects {
const EINSUFFICIENT_FUNDS: u64 = 0;

/// Exchange `c` for some ham
public fun buy_ham(c: Coin<EXAMPLE>, ctx: &mut TxContext): Ham {
public fun buy_ham(c: Coin<GAS>, ctx: &mut TxContext): Ham {
assert!(Coin::value(&c) == HAM_PRICE, EINSUFFICIENT_FUNDS);
Transfer::transfer(c, admin());
Transfer::transfer(c, GROCERY);
Ham { id: TxContext::new_id(ctx) }
}

/// Exchange `c` for some bread
public fun buy_bread(c: Coin<EXAMPLE>, ctx: &mut TxContext): Bread {
public fun buy_bread(c: Coin<GAS>, ctx: &mut TxContext): Bread {
assert!(Coin::value(&c) == BREAD_PRICE, EINSUFFICIENT_FUNDS);
Transfer::transfer(c, admin());
Transfer::transfer(c, GROCERY);
Bread { id: TxContext::new_id(ctx) }
}

Expand All @@ -53,8 +53,4 @@ module Examples::CombinableObjects {
ID::delete(bread_id);
Transfer::transfer(Sandwich { id: TxContext::new_id(ctx) }, TxContext::sender(ctx))
}

fun admin(): address {
GROCERY
}
}
12 changes: 12 additions & 0 deletions sui_programmability/examples/defi/Move.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "DeFi"
version = "0.0.1"

[dependencies]
Sui = { local = "../../framework" }

[addresses]
DeFi = "0x0"

[dev-addresses]
DeFi = "0x0"
4 changes: 4 additions & 0 deletions sui_programmability/examples/defi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# DeFi

* Escrow: an atomic swap leveraging an escrow agent that is trusted for liveness, but not safety (i.e., the agent cannot steal the goods being swapped).
* Uniswap 1.0-style DEX (coming soon).
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
/// An escrow for atomic swap of objects that
/// trusts a third party for liveness, but not
/// safety.
module Sui::Escrow {
/// An escrow for atomic swap of objects that trusts a third party for liveness, but not safety.
module DeFi::Escrow {
use Sui::ID::{Self, ID, VersionedID};
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};
Expand Down
12 changes: 12 additions & 0 deletions sui_programmability/examples/fungible_tokens/Move.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "FungibleTokens"
version = "0.0.1"

[dependencies]
Sui = { local = "../../framework" }

[addresses]
FungibleTokens = "0x0"

[dev-addresses]
FungibleTokens = "0x0"
5 changes: 5 additions & 0 deletions sui_programmability/examples/fungible_tokens/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Fungible Tokens

* MANAGED: a token managed by a treasurer trusted for minting and burning. This is how (e.g.) a fiat-backed stablecoin would work.
* FIXED: a token with a fixed supply (coming soon).
* ALGO: a token with an algorithmic issuance policy (coming soon).
43 changes: 43 additions & 0 deletions sui_programmability/examples/fungible_tokens/sources/MANAGED.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/// Example coin with a trusted manager responsible for minting/burning (e.g., a stablecoin)
/// By convention, modules defining custom coin types use upper case names, in constrast to
/// ordinary modules, which use camel case.
module FungibleTokens::MANAGED {
use Sui::Coin::{Self, Coin, TreasuryCap};
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};

/// Name of the coin. By convention, this type has the same name as its parent module
/// and has no fields. The full type of the coin defined by this module will be `COIN<MANAGED>`.
struct MANAGED has drop {}

/// Register the trusted currency to acquire its `TreasuryCap`. Because
/// this is a module initializer, it ensures the currency only gets
/// registered once.
fun init(ctx: &mut TxContext) {
// Get a treasury cap for the coin and give it to the transaction
// sender
let treasury_cap = Coin::create_currency<MANAGED>(MANAGED{}, ctx);
Transfer::transfer(treasury_cap, TxContext::sender(ctx))
}

/// Manager can mint new coins
public fun mint(treasury_cap: &mut TreasuryCap<MANAGED>, amount: u64, ctx: &mut TxContext): Coin<MANAGED> {
Coin::mint<MANAGED>(amount, treasury_cap, ctx)
}

/// Manager can burn coins
public fun burn(treasury_cap: &mut TreasuryCap<MANAGED>, coin: Coin<MANAGED>, _ctx: &mut TxContext) {
Coin::burn(coin, treasury_cap)
}

/// Manager can transfer the treasury capability to a new manager
public fun transfer_cap(treasury_cap: TreasuryCap<MANAGED>, recipient: address, _ctx: &mut TxContext) {
Coin::transfer_cap<MANAGED>(treasury_cap, recipient);
}

#[test_only]
/// Wrapper of module initializer for testing
public fun test_init(ctx: &mut TxContext) {
init(ctx)
}
}
12 changes: 12 additions & 0 deletions sui_programmability/examples/games/Move.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "Games"
version = "0.0.1"

[dependencies]
Sui = { local = "../../framework" }

[addresses]
Games = "0x0"

[dev-addresses]
Games = "0x0"
9 changes: 9 additions & 0 deletions sui_programmability/examples/games/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Games

Examples of toy games built on top of Sui!

* Tic Tac Toe: the pencil and paper classic, now on Sui.
* Hero: an adventure game where an intrepid hero slays vicious boars with a magic sword and heals himself with potions.
* Sea Hero: a permissionless mod of the Hero game where the hero can slay sea monsters to earn RUM tokens.
* Sea Hero Helper: a permissionless mod of the economics of the Sea Hero game. A weak hero can request help from a stronger hero, who receives a share of the monster slaying reward.
* Rock Paper Scissors (coming soon).
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/// Example of a game character with basic attributes, inventory, and
/// associated logic.
module Examples::Hero {
use Examples::TrustedCoin::EXAMPLE;
module Games::Hero {
use Sui::Coin::{Self, Coin};
use Sui::Event;
use Sui::ID::{Self, ID, VersionedID};
use Sui::Math;
use Sui::GAS::GAS;
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};
use Std::Option::{Self, Option};
Expand Down Expand Up @@ -200,7 +200,7 @@ module Examples::Hero {
/// to the admin. Amount of magic in the sword depends on how much you pay
/// for it.
public fun create_sword(
payment: Coin<EXAMPLE>,
payment: Coin<GAS>,
ctx: &mut TxContext
): Sword {
let value = Coin::value(&payment);
Expand All @@ -219,7 +219,7 @@ module Examples::Hero {
}
}

public fun acquire_hero(payment: Coin<EXAMPLE>, ctx: &mut TxContext) {
public fun acquire_hero(payment: Coin<GAS>, ctx: &mut TxContext) {
let sword = create_sword(payment, ctx);
let hero = create_hero(sword, ctx);
Transfer::transfer(hero, TxContext::sender(ctx))
Expand Down Expand Up @@ -293,8 +293,7 @@ module Examples::Hero {

#[test]
public fun slay_boar_test() {
use Examples::TrustedCoin::{Self, EXAMPLE};
use Sui::Coin::{Self, TreasuryCap};
use Sui::Coin;
use Sui::TestScenario;

let admin = ADMIN;
Expand All @@ -303,23 +302,12 @@ module Examples::Hero {
let scenario = &mut TestScenario::begin(&admin);
// Run the module initializers
{
let ctx = TestScenario::ctx(scenario);
TrustedCoin::test_init(ctx);
init(ctx);
};
// Admin mints 500 coins and sends them to the Player so they can buy game items
TestScenario::next_tx(scenario, &admin);
{
let treasury_cap = TestScenario::remove_object<TreasuryCap<EXAMPLE>>(scenario);
let ctx = TestScenario::ctx(scenario);
let coins = Coin::mint(500, &mut treasury_cap, ctx);
Coin::transfer(coins, copy player);
TestScenario::return_object(scenario, treasury_cap);
init(TestScenario::ctx(scenario));
};
// Player purchases a hero with the coins
TestScenario::next_tx(scenario, &player);
{
let coin = TestScenario::remove_object<Coin<EXAMPLE>>(scenario);
let coin = Coin::mint_for_testing(500, TestScenario::ctx(scenario));
acquire_hero(coin, TestScenario::ctx(scenario));
};
// Admin sends a boar to the Player
Expand All @@ -338,4 +326,4 @@ module Examples::Hero {
TestScenario::return_object(scenario, hero)
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,16 @@
/// earns RUM tokens for hero's owner.
/// Note that this mod does not require special permissions from `Hero` module;
/// anyone is free to create a mod like this.
module Examples::HeroMod {
use Examples::Hero::{Self, Hero};
module Games::SeaHero {
use Games::Hero::{Self, Hero};
use Sui::ID::{Self, VersionedID};
use Sui::Coin::{Self, Coin, TreasuryCap };
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};

/// A new kind of monster for the hero to fight
struct SeaMonster has key, store {
id: VersionedID,
/// Tokens that the user will earn for slaying this monster
reward: Coin<RUM>
}

/// Admin capability granting permission to mint RUM tokens and
/// create monsters
struct SeaScapeAdmin has key {
struct SeaHeroAdmin has key {
id: VersionedID,
/// Permission to mint RUM
treasury_cap: TreasuryCap<RUM>,
Expand All @@ -33,6 +26,13 @@ module Examples::HeroMod {
monster_max: u64
}

/// A new kind of monster for the hero to fight
struct SeaMonster has key, store {
id: VersionedID,
/// Tokens that the user will earn for slaying this monster
reward: Coin<RUM>
}

/// Type of the sea game token
struct RUM has drop {}

Expand All @@ -56,7 +56,7 @@ module Examples::HeroMod {
assert!(monster_max > 0, EINVALID_MONSTER_SUPPLY);

Transfer::transfer(
SeaScapeAdmin {
SeaHeroAdmin {
id: TxContext::new_id(ctx),
treasury_cap: Coin::create_currency<RUM>(RUM{}, ctx),
monsters_created: 0,
Expand Down Expand Up @@ -90,7 +90,7 @@ module Examples::HeroMod {
/// Game admin can reate a monster wrapping a coin worth `reward` and send
/// it to `recipient`
public fun create_monster(
admin: &mut SeaScapeAdmin,
admin: &mut SeaHeroAdmin,
reward_amount: u64,
recipient: address,
ctx: &mut TxContext
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/// Mod of the economics of the SeaScape game. In the game, a `Hero` can onAly
/// Mod of the economics of the SeaHero game. In the game, a `Hero` can onAly
/// slay a `SeaMonster` if they have sufficient strength. This mod allows a
/// player with a weak `Hero` to ask a player with a stronger `Hero` to slay
/// the monster for them in exchange for some of the reward.
module Examples::EconMod {
use Examples::HeroMod::{Self, SeaMonster, RUM};
use Examples::Hero::Hero;
/// Anyone can create a mod like this--the permission of the `SeaHero` game
/// is not required.
module Games::SeaHeroHelper {
use Games::SeaHero::{Self, SeaMonster, RUM};
use Games::Hero::Hero;
use Sui::Coin::{Self, Coin};
use Sui::ID::{Self, VersionedID};
use Sui::Transfer;
Expand Down Expand Up @@ -40,7 +42,7 @@ module Examples::EconMod {
// make sure the advertised reward is not too large + that the owner
// gets a nonzero reward
assert!(
HeroMod::monster_reward(&monster) > helper_reward,
SeaHero::monster_reward(&monster) > helper_reward,
EINVALID_HELPER_REWARD
);
Transfer::transfer(
Expand All @@ -66,7 +68,7 @@ module Examples::EconMod {
helper_reward
} = wrapper;
ID::delete(id);
let owner_reward = HeroMod::slay(hero, monster);
let owner_reward = SeaHero::slay(hero, monster);
let helper_reward = Coin::withdraw(&mut owner_reward, helper_reward, ctx);
Transfer::transfer(owner_reward, monster_owner);
helper_reward
Expand All @@ -82,12 +84,12 @@ module Examples::EconMod {
helper_reward: _
} = wrapper;
ID::delete(id);
HeroMod::transfer_monster(monster, monster_owner)
SeaHero::transfer_monster(monster, monster_owner)
}

/// Return the number of coins that `wrapper.owner` will earn if the
/// the helper slays the monster in `wrapper.
public fun owner_reward(wrapper: &HelpMeSlayThisMonster): u64 {
HeroMod::monster_reward(&wrapper.monster) - wrapper.helper_reward
SeaHero::monster_reward(&wrapper.monster) - wrapper.helper_reward
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Examples::TicTacToe {
module Games::TicTacToe {
use Std::Option::{Self, Option};
use Std::Vector;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#[test_only]
module Examples::TicTacToeTests {
module Games::TicTacToeTests {
use Sui::TestScenario::{Self, Scenario};
use Examples::TicTacToe::{Self, Mark, MarkMintCap, TicTacToe, Trophy};
use Games::TicTacToe::{Self, Mark, MarkMintCap, TicTacToe, Trophy};

const SEND_MARK_FAILED: u64 = 0;
const UNEXPECTED_WINNER: u64 = 1;
Expand Down
Loading

0 comments on commit 6add802

Please sign in to comment.