Build the next
generation of software with the SuiStack

Identity, data, payments, compute, and coordination — unified into a single programmable surface for AI‑native and globally interoperable applications
module hero::example; use sui::balance::{Self, Balance}; use sui::coin::{Self, Coin}; use sui::event; use sui::sui::SUI; public struct Hero has key, store { id: UID, game_id: ID, health: u64, experience: u64, sword: Option<Sword>, } public struct Sword has key, store { id: UID, game_id: ID, magic: u64, strength: u64, } public struct Potion has key, store { id: UID, game_id: ID, potency: u64, } public struct Boar has key, store { id: UID, game_id: ID, health: u64, strength: u64, } public struct Game has key { id: UID, payments: Balance<SUI>, } public struct Admin has key, store { id: UID, game_id: ID, boars_created: u64, potions_created: u64, } public struct BoarSlainEvent has copy, drop { slayer_address: address, boar: ID, hero: ID, game_id: ID, } const MAX_HP: u64 = 1000; const MAX_MAGIC: u64 = 10; const MIN_SWORD_COST: u64 = 100; const EWrongGame: u64 = 0; const EBoarWon: u64 = 1; const EHeroTired: u64 = 2; const ENotAdmin: u64 = 3; const EInsufficientFunds: u64 = 5; const EAlreadyEquipped: u64 = 6; const ENotEquipped: u64 = 7; public fun new_sword(game: &mut Game, payment: Coin<SUI>, ctx: &mut TxContext): Sword { let value = payment.value(); assert!(value >= MIN_SWORD_COST, EInsufficientFunds); coin::put(&mut game.payments, payment); let magic = (value - MIN_SWORD_COST) / MIN_SWORD_COST; Sword { id: object::new(ctx), magic: magic.min(MAX_MAGIC), strength: 1, game_id: object::id(game), } } public fun new_hero(sword: Sword, ctx: &mut TxContext): Hero { Hero { id: object::new(ctx), game_id: sword.game_id, health: 100, experience: 0, sword: option::some(sword), } } public fun new_game(ctx: &mut TxContext): Admin { let game = Game { id: object::new(ctx), payments: balance::zero(), }; let admin = Admin { id: object::new(ctx), game_id: object::id(&game), boars_created: 0, potions_created: 0, }; transfer::share_object(game); admin } public fun new_potion(admin: &mut Admin, potency: u64, ctx: &mut TxContext): Potion { admin.potions_created = admin.potions_created + 1; Potion { id: object::new(ctx), potency, game_id: admin.game_id } } public fun new_boar(admin: &mut Admin, health: u64, strength: u64, ctx: &mut TxContext): Boar { admin.boars_created = admin.boars_created + 1; Boar { id: object::new(ctx), health, strength, game_id: admin.game_id } } public fun slay(hero: &mut Hero, boar: Boar, ctx: &TxContext) { assert!(hero.game_id == boar.game_id, EWrongGame); let Boar { id: boar_id, strength: boar_strength, health: mut boar_health, game_id: _, } = boar; let experience = boar_health; loop { let hero_strength = hero.hero_strength(); if (boar_health < hero_strength) { break } else { boar_health = boar_health - hero_strength; }; assert!(hero.health >= boar_strength, EBoarWon); hero.health = hero.health - boar_strength; }; hero.experience = hero.experience + experience; if (hero.sword.is_some()) { hero.sword.borrow_mut().level_up_sword(1) }; event::emit(BoarSlainEvent { slayer_address: ctx.sender(), hero: object::id(hero), boar: boar_id.uid_to_inner(), game_id: hero.game_id, }); boar_id.delete(); } public fun hero_strength(hero: &Hero): u64 { assert!(hero.health > 0, EHeroTired); let sword_strength = if (hero.sword.is_some()) { hero.sword.borrow().sword_strength() } else { 0 }; (hero.experience * hero.health) + sword_strength } fun level_up_sword(sword: &mut Sword, amount: u64) { sword.strength = sword.strength + amount } public fun sword_strength(sword: &Sword): u64 { sword.magic + sword.strength } public fun heal(hero: &mut Hero, potion: Potion) { let Potion { id, potency, game_id } = potion; id.delete(); assert!(hero.game_id == game_id, EWrongGame); hero.health = (hero.health + potency).min(MAX_HP) } public fun equip(hero: &mut Hero, sword: Sword) { assert!(hero.sword.is_none(), EAlreadyEquipped); hero.sword.fill(sword); } public fun unequip(hero: &mut Hero): Sword { assert!(hero.sword.is_some(), ENotEquipped); option::extract(&mut hero.sword) } public fun take_payment(admin: &Admin, game: &mut Game, ctx: &mut TxContext): Coin<SUI> { assert!(admin.game_id == object::id(game), ENotAdmin); coin::from_balance(game.payments.withdraw_all(), ctx) } #[test_only] use sui::test_scenario as ts; #[test] fun slay_boar_test() { let mut ts = ts::begin(@0x0); let admin = @0xAD; let alice = @0xA; let bob = @0xb; setup_game(admin, &mut ts); acquire_hero(alice, MIN_SWORD_COST, &mut ts); { ts.next_tx(admin); let game: Game = ts.take_shared(); let mut cap: Admin = ts.take_from_sender(); let boar: Boar = cap.new_boar(9, 9, ts.ctx()); transfer::public_transfer(boar, alice); ts.return_to_sender(cap); ts::return_shared(game); }; { ts.next_tx(alice); let mut hero: Hero = ts.take_from_sender(); let boar: Boar = ts.take_from_sender(); hero.slay(boar, ts.ctx()); ts.return_to_sender(hero); }; { ts.next_tx(admin); let mut cap: Admin = ts.take_from_sender(); let potion: Potion = cap.new_potion(1, ts.ctx()); transfer::public_transfer(potion, alice); ts.return_to_sender(cap); }; { ts.next_tx(alice); let mut hero: Hero = ts.take_from_sender(); let potion: Potion = ts.take_from_sender(); let potency = potion.potency; let before = hero.health; hero.heal(potion); assert!(hero.health == before + potency, 0); ts.return_to_sender(hero); }; acquire_hero(bob, MIN_SWORD_COST + 42, &mut ts); { ts.next_tx(admin); let mut game: Game = ts.take_shared(); let cap: Admin = ts.take_from_sender(); let payment = cap.take_payment(&mut game, ts.ctx()); assert!(payment.value() == MIN_SWORD_COST * 2 + 42, 0); transfer::public_transfer(payment, admin); ts.return_to_sender(cap); ts::return_shared(game); }; ts.end(); } #[test] #[expected_failure(abort_code = EWrongGame)] fun test_wrong_game() { let mut ts = ts::begin(@0x0); let admin0 = @0xAD0; let admin1 = @0xAD1; let player = @0xA; setup_game(admin0, &mut ts); let g0 = { ts.next_tx(@0x0); ts::most_recent_id_shared<Game>().destroy_some() }; setup_game(admin1, &mut ts); { ts.next_tx(player); let mut game: Game = ts.take_shared_by_id(g0); let coin = coin::mint_for_testing(MIN_SWORD_COST, ts.ctx()); let sword = game.new_sword(coin, ts.ctx()); let hero = sword.new_hero(ts.ctx()); transfer::public_transfer(hero, player); ts::return_shared(game); }; { ts.next_tx(admin1); let mut cap: Admin = ts.take_from_sender(); let potion: Potion = cap.new_potion(1, ts.ctx()); transfer::public_transfer(potion, player); ts.return_to_sender(cap); }; { ts.next_tx(player); let mut hero: Hero = ts.take_from_sender(); let potion: Potion = ts.take_from_sender(); hero.heal(potion); }; abort 1337 } #[test] #[expected_failure(abort_code = EHeroTired)] fun test_hero_tired() { let mut ts = ts::begin(@0x0); let admin = @0xAD; let player = @0xA; setup_game(admin, &mut ts); acquire_hero(player, MIN_SWORD_COST, &mut ts); { ts.next_tx(admin); let game: Game = ts.take_shared(); let mut cap: Admin = ts.take_from_sender(); let boar: Boar = cap.new_boar(9, 9, ts.ctx()); transfer::public_transfer(boar, player); ts.return_to_sender(cap); ts::return_shared(game); }; { ts.next_tx(player); let mut hero: Hero = ts.take_from_sender(); let boar: Boar = ts.take_from_sender(); hero.health = 0; hero.slay(boar, ts.ctx()); }; abort 1337 } #[test] #[expected_failure(abort_code = EBoarWon)] fun test_boar_win() { let mut ts = ts::begin(@0x0); let admin = @0xAD; let player = @0xA; setup_game(admin, &mut ts); acquire_hero(player, MIN_SWORD_COST, &mut ts); { ts.next_tx(admin); let game: Game = ts.take_shared(); let mut cap: Admin = ts.take_from_sender(); let boar: Boar = cap.new_boar(9, 9, ts.ctx()); transfer::public_transfer(boar, player); ts.return_to_sender(cap); ts::return_shared(game); }; { ts.next_tx(player); let mut hero: Hero = ts.take_from_sender(); let boar: Boar = ts.take_from_sender(); hero.health = 1; hero.slay(boar, ts.ctx()); }; abort 1337 } #[test] #[expected_failure(abort_code = EInsufficientFunds)] fun test_insufficient_funds() { let mut ts = ts::begin(@0x0); let admin = @0xAD; let player = @0xA; setup_game(admin, &mut ts); acquire_hero(player, MIN_SWORD_COST - 1, &mut ts); abort 1337 } #[test] #[expected_failure(abort_code = ENotEquipped)] fun test_unequip_empty() { let admin = @0xAD; let player = @0xA; let mut ts = ts::begin(admin); let _admin = new_game(ts.ctx()); ts.next_tx(player); let mut game: Game = ts.take_shared(); let coin = coin::mint_for_testing(MIN_SWORD_COST, ts.ctx()); let sword = game.new_sword(coin, ts.ctx()); let mut hero = sword.new_hero(ts.ctx()); let _s0 = hero.unequip(); let _s1 = hero.unequip(); abort 1337 } #[test] #[expected_failure(abort_code = EAlreadyEquipped)] fun test_equip_already_equipped() { let admin = @0xAD; let player = @0xA; let mut ts = ts::begin(admin); let _admin = new_game(ts.ctx()); ts.next_tx(player); let mut game: Game = ts.take_shared(); let c0 = coin::mint_for_testing(MIN_SWORD_COST, ts.ctx()); let s0 = game.new_sword(c0, ts.ctx()); let c1 = coin::mint_for_testing(MIN_SWORD_COST, ts.ctx()); let s1 = game.new_sword(c1, ts.ctx()); let mut hero = s0.new_hero(ts.ctx()); hero.equip(s1); abort 1337 } #[test_only] fun setup_game(admin: address, ts: &mut ts::Scenario) { ts.next_tx(admin); let cap = new_game(ts.ctx()); transfer::public_transfer(cap, admin); } #[test_only] fun acquire_hero(player: address, payment: u64, ts: &mut ts::Scenario) { ts.next_tx(player); let mut game: Game = ts.take_shared(); let coin = coin::mint_for_testing(payment, ts.ctx()); let sword = game.new_sword(coin, ts.ctx()); let hero = sword.new_hero(ts.ctx()); transfer::public_transfer(hero, player); ts::return_shared(game); }
module hero::example; use sui::balance::{Self, Balance}; use sui::coin::{Self, Coin}; use sui::event; use sui::sui::SUI; public struct Hero has key, store { id: UID, game_id: ID, health: u64, experience: u64, sword: Option<Sword>, } public struct Sword has key, store { id: UID, game_id: ID, magic: u64, strength: u64, } public struct Potion has key, store { id: UID, game_id: ID, potency: u64, } public struct Boar has key, store { id: UID, game_id: ID, health: u64, strength: u64, } public struct Game has key { id: UID, payments: Balance<SUI>, } public struct Admin has key, store { id: UID, game_id: ID, boars_created: u64, potions_created: u64, } public struct BoarSlainEvent has copy, drop { slayer_address: address, boar: ID, hero: ID, game_id: ID, } const MAX_HP: u64 = 1000; const MAX_MAGIC: u64 = 10; const MIN_SWORD_COST: u64 = 100; const EWrongGame: u64 = 0; const EBoarWon: u64 = 1; const EHeroTired: u64 = 2; const ENotAdmin: u64 = 3; const EInsufficientFunds: u64 = 5; const EAlreadyEquipped: u64 = 6; const ENotEquipped: u64 = 7; public fun new_sword(game: &mut Game, payment: Coin<SUI>, ctx: &mut TxContext): Sword { let value = payment.value(); assert!(value >= MIN_SWORD_COST, EInsufficientFunds); coin::put(&mut game.payments, payment); let magic = (value - MIN_SWORD_COST) / MIN_SWORD_COST; Sword { id: object::new(ctx), magic: magic.min(MAX_MAGIC), strength: 1, game_id: object::id(game), } } public fun new_hero(sword: Sword, ctx: &mut TxContext): Hero { Hero { id: object::new(ctx), game_id: sword.game_id, health: 100, experience: 0, sword: option::some(sword), } } public fun new_game(ctx: &mut TxContext): Admin { let game = Game { id: object::new(ctx), payments: balance::zero(), }; let admin = Admin { id: object::new(ctx), game_id: object::id(&game), boars_created: 0, potions_created: 0, }; transfer::share_object(game); admin } public fun new_potion(admin: &mut Admin, potency: u64, ctx: &mut TxContext): Potion { admin.potions_created = admin.potions_created + 1; Potion { id: object::new(ctx), potency, game_id: admin.game_id } } public fun new_boar(admin: &mut Admin, health: u64, strength: u64, ctx: &mut TxContext): Boar { admin.boars_created = admin.boars_created + 1; Boar { id: object::new(ctx), health, strength, game_id: admin.game_id } } public fun slay(hero: &mut Hero, boar: Boar, ctx: &TxContext) { assert!(hero.game_id == boar.game_id, EWrongGame); let Boar { id: boar_id, strength: boar_strength, health: mut boar_health, game_id: _, } = boar; let experience = boar_health; loop { let hero_strength = hero.hero_strength(); if (boar_health < hero_strength) { break } else { boar_health = boar_health - hero_strength; }; assert!(hero.health >= boar_strength, EBoarWon); hero.health = hero.health - boar_strength; }; hero.experience = hero.experience + experience; if (hero.sword.is_some()) { hero.sword.borrow_mut().level_up_sword(1) }; event::emit(BoarSlainEvent { slayer_address: ctx.sender(), hero: object::id(hero), boar: boar_id.uid_to_inner(), game_id: hero.game_id, }); boar_id.delete(); } public fun hero_strength(hero: &Hero): u64 { assert!(hero.health > 0, EHeroTired); let sword_strength = if (hero.sword.is_some()) { hero.sword.borrow().sword_strength() } else { 0 }; (hero.experience * hero.health) + sword_strength } fun level_up_sword(sword: &mut Sword, amount: u64) { sword.strength = sword.strength + amount } public fun sword_strength(sword: &Sword): u64 { sword.magic + sword.strength } public fun heal(hero: &mut Hero, potion: Potion) { let Potion { id, potency, game_id } = potion; id.delete(); assert!(hero.game_id == game_id, EWrongGame); hero.health = (hero.health + potency).min(MAX_HP) } public fun equip(hero: &mut Hero, sword: Sword) { assert!(hero.sword.is_none(), EAlreadyEquipped); hero.sword.fill(sword); } public fun unequip(hero: &mut Hero): Sword { assert!(hero.sword.is_some(), ENotEquipped); option::extract(&mut hero.sword) } public fun take_payment(admin: &Admin, game: &mut Game, ctx: &mut TxContext): Coin<SUI> { assert!(admin.game_id == object::id(game), ENotAdmin); coin::from_balance(game.payments.withdraw_all(), ctx) } #[test_only] use sui::test_scenario as ts; #[test] fun slay_boar_test() { let mut ts = ts::begin(@0x0); let admin = @0xAD; let alice = @0xA; let bob = @0xb; setup_game(admin, &mut ts); acquire_hero(alice, MIN_SWORD_COST, &mut ts); { ts.next_tx(admin); let game: Game = ts.take_shared(); let mut cap: Admin = ts.take_from_sender(); let boar: Boar = cap.new_boar(9, 9, ts.ctx()); transfer::public_transfer(boar, alice); ts.return_to_sender(cap); ts::return_shared(game); }; { ts.next_tx(alice); let mut hero: Hero = ts.take_from_sender(); let boar: Boar = ts.take_from_sender(); hero.slay(boar, ts.ctx()); ts.return_to_sender(hero); }; { ts.next_tx(admin); let mut cap: Admin = ts.take_from_sender(); let potion: Potion = cap.new_potion(1, ts.ctx()); transfer::public_transfer(potion, alice); ts.return_to_sender(cap); }; { ts.next_tx(alice); let mut hero: Hero = ts.take_from_sender(); let potion: Potion = ts.take_from_sender(); let potency = potion.potency; let before = hero.health; hero.heal(potion); assert!(hero.health == before + potency, 0); ts.return_to_sender(hero); }; acquire_hero(bob, MIN_SWORD_COST + 42, &mut ts); { ts.next_tx(admin); let mut game: Game = ts.take_shared(); let cap: Admin = ts.take_from_sender(); let payment = cap.take_payment(&mut game, ts.ctx()); assert!(payment.value() == MIN_SWORD_COST * 2 + 42, 0); transfer::public_transfer(payment, admin); ts.return_to_sender(cap); ts::return_shared(game); }; ts.end(); } #[test] #[expected_failure(abort_code = EWrongGame)] fun test_wrong_game() { let mut ts = ts::begin(@0x0); let admin0 = @0xAD0; let admin1 = @0xAD1; let player = @0xA; setup_game(admin0, &mut ts); let g0 = { ts.next_tx(@0x0); ts::most_recent_id_shared<Game>().destroy_some() }; setup_game(admin1, &mut ts); { ts.next_tx(player); let mut game: Game = ts.take_shared_by_id(g0); let coin = coin::mint_for_testing(MIN_SWORD_COST, ts.ctx()); let sword = game.new_sword(coin, ts.ctx()); let hero = sword.new_hero(ts.ctx()); transfer::public_transfer(hero, player); ts::return_shared(game); }; { ts.next_tx(admin1); let mut cap: Admin = ts.take_from_sender(); let potion: Potion = cap.new_potion(1, ts.ctx()); transfer::public_transfer(potion, player);
module hero::example; use sui::balance::{Self, Balance}; use sui::coin::{Self, Coin}; use sui::event; use sui::sui::SUI; public struct Hero has key, store { id: UID, game_id: ID, health: u64, experience: u64, sword: Option<Sword>, } public struct Sword has key, store { id: UID, game_id: ID, magic: u64, strength: u64, } public struct Potion has key, store { id: UID, game_id: ID, potency: u64, } public struct Boar has key, store { id: UID, game_id: ID, health: u64, strength: u64, } public struct Game has key { id: UID, payments: Balance<SUI>, } public struct Admin has key, store { id: UID, game_id: ID, boars_created: u64, potions_created: u64, } public struct BoarSlainEvent has copy, drop { slayer_address: address, boar: ID, hero: ID, game_id: ID, } const MAX_HP: u64 = 1000; const MAX_MAGIC: u64 = 10; const MIN_SWORD_COST: u64 = 100; const EWrongGame: u64 = 0; const EBoarWon: u64 = 1; const EHeroTired: u64 = 2; const ENotAdmin: u64 = 3; const EInsufficientFunds: u64 = 5; const EAlreadyEquipped: u64 = 6; const ENotEquipped: u64 = 7; public fun new_sword(game: &mut Game, payment: Coin<SUI>, ctx: &mut TxContext): Sword { let value = payment.value(); assert!(value >= MIN_SWORD_COST, EInsufficientFunds); coin::put(&mut game.payments, payment); let magic = (value - MIN_SWORD_COST) / MIN_SWORD_COST; Sword { id: object::new(ctx), magic: magic.min(MAX_MAGIC), strength: 1, game_id: object::id(game), } } public fun new_hero(sword: Sword, ctx: &mut TxContext): Hero { Hero { id: object::new(ctx), game_id: sword.game_id, health: 100, experience: 0, sword: option::some(sword), } } public fun new_game(ctx: &mut TxContext): Admin { let game = Game { id: object::new(ctx), payments: balance::zero(), }; let admin = Admin { id: object::new(ctx), game_id: object::id(&game), boars_created: 0, potions_created: 0, }; transfer::share_object(game); admin } public fun new_potion(admin: &mut Admin, potency: u64, ctx: &mut TxContext): Potion { admin.potions_created = admin.potions_created + 1; Potion { id: object::new(ctx), potency, game_id: admin.game_id } } public fun new_boar(admin: &mut Admin, health: u64, strength: u64, ctx: &mut TxContext): Boar { admin.boars_created = admin.boars_created + 1; Boar { id: object::new(ctx), health, strength, game_id: admin.game_id } } public fun slay(hero: &mut Hero, boar: boar_id.uid_to_inner(), game_id: hero.game_id, }); boar_id.delete(); } public fun hero_strength(hero: &Hero): u64

400ms
settlement

Machine-speed coordination for autonomous applications

13B+
total
transactions

Global coordination at internet scale

1 universal
API surface

Shared state that lets agents and apps coordinate across trust boundaries

Apps for every
Use
Case

The Sui Stack lets developers build interoperable, AI‑ready applications across content, communication, gaming, commerce, and more — all on a unified, global API surface instead of a patchwork of backend services.

Explore the
Sui
Stack

A modular ecosystem of composable capabilities for building Al‑native, interoperable applications. Choose the identity, data, compute, and coordination layers you need to build software traditional infrastructure can't support.

Sui

sui.io

Walrus

walrus.xyz

Walrus Sites

wal.app

Seal

seal.mystenlabs.com

Nautilus

sui.io/nautilus

zkLogin & Passkeys

enoki.mystenlabs.com

SuiNS

suins.io

DeepBook

deepbook.tech

Sui

Capability
A globally shared, low-latency execution environment that lets applications and agents coordinate through a universal API surface. Ideal for dynamic workflows that need trusted state across services
Web2 Comparison
Firebase + Postgres + API Gateway, but globally shared, verifiable, 
and composable by default.

Walrus

Capability
Verifiable, content-addressed storage for files, datasets, logs, and models — with built-in provenance and integrity. Enables portable, tamper-proof data across apps and trust boundaries.
Web2 Comparison
AWS S3 / GCS, but with built-in provenance, integrity, and portable access policies.

Walrus Sites

Capability
Serverless, content-addressed frontends and applications served directly from storage. Guarantees that clients load exactly the code you deployed, with no servers or intermediaries.
Web2 Comparison
Vercel / Netlify, but trustless, serverless, and tamper-proof 
at the hosting layer.

Seal

Capability
Programmable, privacy-preserving access control that attaches policies directly to the data. Allows apps to share and license data securely without custom permission plumbing.
Web2 Comparison
AWS KMS + IAM + custom ACL logic, but portable, programmable, 
and enforceable across trust boundaries.

Nautilus

Capability
Confidential, verifiable offchain compute for inference, training, 
and business logic. Produces proof-like attestations that apps can trust without relying on a vendor.
Web2 Comparison
AWS Nitro Enclaves, but with verifiable proofs 
you can settle onchain.

zkLogin & Passkeys

Capability
Passwordless identity that links users’ existing Web2 accounts 
to secure keys — enabling frictionless onboarding and agent-friendly delegation without exposing sensitive data.
Web2 Comparison
OAuth + passkeys, but private, portable, 
and agent-friendly.

SuiNS

Capability
Human-readable names for users, agents, and apps 
that make discovery and coordination easier across 
the ecosystem.
Web2 Comparison
DNS, but native to Sui’s object model.

DeepBook

Capability
A fast, open, programmable liquidity layer that apps and agents 
can call directly. Enables atomic payments, multi-party transactions, and machine-speed commerce flows.
Web2 Comparison
Stripe + NASDAQ matching engine, 
but composable and trustless.

Sui

Capability
A globally shared, low-latency execution environment that lets applications and agents coordinate through a universal API surface. Ideal for dynamic workflows that need trusted state across services.
Web2 Comparison
Firebase + Postgres + API Gateway, but globally shared, verifiable, and composable by default.

Walrus

Capability
Verifiable, content-addressed storage for files, datasets, logs, and models — with built-in provenance and integrity. Enables portable, tamper-proof data across apps and trust boundaries.
Web2 Comparison
AWS S3 / GCS, but with built-in provenance, integrity, and portable access policies.

Walrus Sites

Capability
Serverless, content-addressed frontends and applications served directly from storage. Guarantees that clients load exactly the code you deployed, with no servers or intermediaries.
Web2 Comparison
Vercel / Netlify, but trustless, serverless, and tamper-proof at the hosting layer.

Seal

Capability
Programmable, privacy-preserving access control that attaches policies directly to the data. Allows apps to share and license data securely without custom permission plumbing.
Web2 Comparison
AWS KMS + IAM + custom ACL logic, but portable, programmable, and enforceable across trust boundaries.

Nautilus

Capability
Confidential, verifiable offchain compute for inference, training, and business logic. Produces proof-like attestations that apps can trust without relying on a vendor.
Web2 Comparison
AWS Nitro Enclaves, but with verifiable proofs you can settle onchain.

zkLogin & Passkeys

Capability
Passwordless identity that links users’ existing Web2 accounts to secure keys — enabling frictionless onboarding and agent-friendly delegation without exposing sensitive data.
Web2 Comparison
OAuth + passkeys, but private, portable, and agent-friendly.

SuiNS

Capability
Human-readable names for users, agents, and apps that make discovery and coordination easier across the ecosystem.
Web2 Comparison
DNS, but native to Sui’s 
object model.

DeepBook

Capability
A fast, open, programmable liquidity layer that apps and agents can call directly. Enables atomic payments, multi-party transactions, and machine-speed commerce flows.
Web2 Comparison
Stripe + NASDAQ matching engine, 
but composable and trustless.

Connect
With
Us

module hero::example; use sui::balance::{Self, Balance}; use sui::coin::{Self, Coin}; use sui::event; use sui::sui::SUI; public struct Hero has key, store { id: UID, game_id: ID, health: u64, experience: u64, sword: Option<Sword>, } public struct Sword has key, store { id: UID, game_id: ID, magic: u64, strength: u64, } public struct Potion has key, store { id: UID, game_id: ID, potency: u64, } public struct Boar has key, store { id: UID, game_id: ID, health: u64, strength: u64, } public struct Game has key { id: UID, payments: Balance<SUI>, } public struct Admin has key, store { id: UID, game_id: ID, boars_created: u64, potions_created: u64, } public struct BoarSlainEvent has copy, drop { slayer_address: address, boar: ID, hero: ID, game_id: ID, } const MAX_HP: u64 = 1000; const MAX_MAGIC: u64 = 10; const MIN_SWORD_COST: u64 = 100; const EWrongGame: u64 = 0; const EBoarWon: u64 = 1; const EHeroTired: u64 = 2; const ENotAdmin: u64 = 3; const EInsufficientFunds: u64 = 5; const EAlreadyEquipped: u64 = 6; const ENotEquipped: u64 = 7; public fun new_sword(game: &mut Game, payment: Coin<SUI>, ctx: &mut TxContext): Sword { let value = payment.value(); assert!(value >= MIN_SWORD_COST, EInsufficientFunds); coin::put(&mut game.payments, payment); let magic = (value - MIN_SWORD_COST) / MIN_SWORD_COST; Sword { id: object::new(ctx), magic: magic.min(MAX_MAGIC), strength: 1, game_id: object::id(game), } } public fun new_hero(sword: Sword, ctx: &mut TxContext): Hero { Hero { id: object::new(ctx), game_id: sword.game_id, health: 100, experience: 0, sword: option::some(sword), } } public fun new_game(ctx: &mut TxContext): Admin { let game = Game { id: object::new(ctx), payments: balance::zero(), }; let admin = Admin { id: object::new(ctx), game_id: object::id(&game), boars_created: 0, potions_created: 0, }; transfer::share_object(game); admin } public fun new_potion(admin: &mut Admin, potency: u64, ctx: &mut TxContext): Potion { admin.potions_created = admin.potions_created + 1; Potion { id: object::new(ctx), potency, game_id: admin.game_id } } public fun new_boar(admin: &mut Admin, health: u64, strength: u64, ctx: &mut TxContext): Boar { admin.boars_created = admin.boars_created + 1; Boar { id: object::new(ctx), health, strength, game_id: admin.game_id } } public fun slay(hero: &mut Hero, boar: Boar, ctx: &TxContext) { assert!(hero.game_id == boar.game_id, EWrongGame); let Boar { id: boar_id, strength: boar_strength, health: mut boar_health, game_id: _, } = boar; let experience =
module hero::example; use sui::balance::{Self, Balance}; use sui::coin::{Self, Coin}; use sui::event; use sui::sui::SUI; public struct Hero has key, store { id: UID, game_id: ID, health: u64, experience: u64, sword: Option<Sword>, } public struct Sword has key, store { id: UID, game_id: ID, magic: u64, strength: u64, } public struct Potion has key, store { id: UID, game_id: ID, potency: u64, } public struct Boar has key, store { id: UID, game_id: ID, health: u64, strength: u64, } public struct Game has key { id: UID, payments: Balance<SUI>, } public struct Admin has key, store { id: UID, game_id: ID, boars_created: u64, potions_created: u64, } public struct BoarSlainEvent has copy, drop { slayer_address: address, boar: ID, hero: ID, game_id: ID, } const MAX_HP: u64 = 1000; const MAX_MAGIC: u64 = 10; const MIN_SWORD_COST: u64 = 100; const EWrongGame: u64 = 0; const EBoarWon: u64 = 1; const EHeroTired: u64 = 2; const ENotAdmin: u64 = 3; const EInsufficientFunds: u64 = 5; const EAlreadyEquipped: u64 = 6; const ENotEquipped: u64 = 7; public fun new_sword(game: &mut Game, payment: Coin<SUI>, ctx: &mut TxContext): Sword { let value = payment.value(); assert!(value >= MIN_SWORD_COST, EInsufficientFunds); coin::put(&mut game.payments, payment); let magic = (value - MIN_SWORD_COST) / MIN_SWORD_COST; Sword { id: object::new(ctx), magic: magic.min(MAX_MAGIC), strength: 1, game_id: object::id(game), } } public fun new_hero(sword: Sword, ctx: &mut TxContext): Hero { Hero { id: object::new(ctx), game_id: sword.game_id, health: 100, experience: 0, sword: option::some(sword), } } public fun new_game(ctx: &mut TxContext): Admin { let game = Game { id: object::new(ctx), payments: balance::zero(), }; let admin = Admin { id: object::new(ctx), game_id: object::id(&game), boars_created: 0, potions_created: 0, }; transfer::share_object(game); admin } public fun new_potion(admin: &mut Admin, potency: u64, ctx: &mut TxContext): Potion { admin.potions_created = admin.potions_created + 1; Potion { id: object::new(ctx), potency, game_id: admin.game_id } } public fun new_boar(admin: &mut Admin, health: u64, strength: u64, ctx: &mut TxContext): Boar { admin.boars_created = admin.boars_created + 1; Boar { id: object::new(ctx), health, strength, game_id: admin.game_id } } public fun slay(hero: &mut Hero, boar: Boar, ctx: &TxContext) { assert!(hero.game_id == boar.game_id, EWrongGame); let Boar { id: boar_id, strength: boar_strength, health: mut boar_health, game_id: _, } = boar; let experience = boar_health; loop { let hero_strength = hero.hero_strength(); if (boar_health < hero_strength) { break } else { boar_health = boar_health - hero_strength; }; assert!(hero.health >= boar_strength, EBoarWon); hero.health = hero.health - boar_strength; }; hero.experience = hero.experience + experience; if (hero.sword.is_some()) { hero.sword.borrow_mut().level_up_sword(1) }; event::emit(BoarSlainEvent { slayer_address: ctx.sender(), hero: object::id(hero), boar: boar_id.uid_to_inner(), game_id: hero.game_id, }); boar_id.delete(); } public fun hero_strength(hero: &Hero): u64 { assert!(hero.health > 0, EHeroTired); let sword_strength = if (hero.sword.is_some()) { hero.sword.borrow().sword_strength() } else { 0 }; (hero.experience * hero.health) + sword_strength } fun level_up_sword(sword: &mut Sword, amount: u64) { sword.strength = sword.strength + amount } public fun sword_strength(sword: &Sword): u64 { sword.magic + sword.strength } public fun heal(hero: &mut Hero, potion: Potion) { let Potion { id, potency, game_id } = potion; id.delete(); assert!(hero.game_id == game_id, EWrongGame); hero.health = (hero.health + potency).min(MAX_HP) } public fun equip(hero: &mut Hero, sword: Sword) { assert!(hero.sword.is_none(), EAlreadyEquipped); hero.sword.fill(sword); } public fun unequip(hero: &mut Hero): Sword { assert!(hero.sword.is_some(), ENotEquipped); option::extract(&mut hero.sword) } public fun take_payment(admin: &Admin, game: &mut Game, ctx: &mut TxContext): Coin<SUI> { assert!(admin.game_id == object::id(game), ENotAdmin); coin::from_balance(game.payments.withdraw_all(), ctx) } #[test_only] use sui::test_scenario as ts; #[test] fun slay_boar_test() { let mut ts = ts::begin(@0x0); let admin = @0xAD; let alice = @0xA; let bob = @0xb; setup_game(admin, &mut ts); acquire_hero(alice, MIN_SWORD_COST, &mut ts); { ts.next_tx(admin); let game: Game = ts.take_shared(); let mut cap: Admin = ts.take_from_sender(); let boar: Boar = cap.new_boar(9, 9, ts.ctx()); transfer::public_transfer(boar, alice); ts.return_to_sender(cap); ts::return_shared(game); }; { ts.next_tx(alice); let mut hero: Hero = ts.take_from_sender(); let boar: Boar = ts.take_from_sender(); hero.slay(boar, ts.ctx()); ts.return_to_sender(hero); }; { ts.next_tx(admin); let mut cap: Admin = ts.take_from_sender(); let potion: Potion = cap.new_potion(1, ts.ctx()); transfer::public_transfer(potion, alice); ts.return_to_sender(cap); }; { ts.next_tx(alice); let mut hero: Hero = ts.take_from_sender(); let potion: Potion = ts.take_from_sender(); let potency = potion.potency; let before = hero.health; hero.heal(potion); assert!(hero.health == before + potency, 0); ts.return_to_sender(hero); }; acquire_hero(bob, MIN_SWORD_COST + 42, &mut ts); { ts.next_tx(admin); let mut game: Game = ts.take_shared(); let cap: Admin = ts.take_from_sender(); let payment = cap.take_payment(&mut game, ts.ctx()); assert!(payment.value() == MIN_SWORD_COST * 2 + 42, 0); transfer::public_transfer(payment, admin); ts.return_to_sender(cap); ts::return_shared(game); }; ts.end(); } #[test] #[expected_failure(abort_code = EWrongGame)] fun test_wrong_game() { let mut ts = ts::begin(@0x0); let admin0 = @0xAD0; let admin1 = @0xAD1; let player = @0xA; setup_game(admin0, &mut ts); let g0 = { ts.next_tx(@0x0); ts::most_recent_id_shared<Game>().destroy_some() }; setup_game(admin1, &mut ts); { ts.next_tx(player); let mut game: Game = ts.take_shared_by_id(g0); let coin = coin::mint_for_testing(MIN_SWORD_COST, ts.ctx()); let sword = game.new_sword(coin, ts.ctx()); let hero = sword.new_hero(ts.ctx()); transfer::public_transfer(hero, player); ts::return_shared(game); }; { ts.next_tx(admin1); let mut cap: Admin = ts.take_from_sender(); let potion: Potion = cap.new_potion(1, ts.ctx()); transfer::public_transfer(potion, player);
module hero::example; use sui::balance::{Self, Balance}; use sui::coin::{Self, Coin}; use sui::event; use sui::sui::SUI; public struct Hero has key, store { id: UID, game_id: ID, health: u64, experience: u64, sword: Option<Sword>, } public struct Sword has key, store { id: UID, game_id: ID, magic: u64, strength: u64, } public struct Potion has key, store { id: UID, game_id: ID, potency: u64, } public struct Boar has key, store { id: UID, game_id: ID, healt