├── CNAME ├── site ├── packages ├── src │ ├── fonts │ │ ├── Spot-MonoLight.ttf │ │ ├── Spot-MonoBold.woff2 │ │ ├── Spot-MonoLight.woff │ │ ├── Spot-MonoLight.woff2 │ │ ├── Spot-MonoMedium.woff2 │ │ ├── Spot-MonoRegular.woff2 │ │ ├── Spot-MonoBoldItalic.woff2 │ │ ├── Spot-MonoLightItalic.woff2 │ │ ├── Spot-MonoMediumItalic.woff2 │ │ ├── Spot-MonoRegularItalic.woff2 │ │ └── fonts.css │ ├── theme │ │ ├── CodeBlock │ │ │ └── Buttons │ │ │ │ ├── WordWrapButton │ │ │ │ ├── styles.module.css │ │ │ │ └── index.tsx │ │ │ │ ├── Button │ │ │ │ └── index.tsx │ │ │ │ ├── styles.module.css │ │ │ │ ├── CopyButton │ │ │ │ ├── styles.module.css │ │ │ │ └── index.tsx │ │ │ │ ├── RenderButton │ │ │ │ └── styles.module.css │ │ │ │ └── index.tsx │ │ ├── Icon │ │ │ ├── Success │ │ │ │ └── index.tsx │ │ │ ├── Copy │ │ │ │ └── index.tsx │ │ │ └── Image │ │ │ │ └── index.tsx │ │ ├── CodeInline │ │ │ └── index.tsx │ │ ├── ColorModeToggle │ │ │ └── styles.module.css │ │ ├── prism-include-languages.js │ │ ├── prism-atom-one-dark.ts │ │ ├── prism-atom-one-light.ts │ │ ├── DocPaginator │ │ │ └── index.tsx │ │ └── DocSidebar │ │ │ └── index.tsx │ ├── css │ │ └── code.css │ └── plugins │ │ ├── mdbook-anchor-code.ts │ │ └── yaml-sidebar.ts ├── sidebar-book.ts ├── sidebar-reference.ts ├── tsconfig.json ├── .gitignore ├── README.md ├── static │ └── favicon.svg └── package.json ├── .gitignore ├── book ├── programmability │ ├── balance-and-coin.md │ ├── authorization-patterns.md │ ├── cryptography-and-hashing.md │ ├── object-capability.md │ ├── index.md │ ├── randomness.md │ ├── events.md │ ├── fast-path.md │ ├── wrapper-type-pattern.md │ └── publisher.md ├── move-advanced │ └── index.md ├── appendix │ ├── contributing.md │ ├── acknowledgements.md │ ├── publications.md │ ├── reserved-addresses.md │ ├── glossary.md │ └── transfer-functions.md ├── guides │ ├── index.md │ ├── open-sourcing-libraries.md │ └── building-against-limits.md ├── before-we-begin │ ├── move-2024.md │ ├── index.md │ ├── install-move-registry-cli.md │ ├── install-sui.md │ └── ide-support.md ├── concepts │ ├── index.md │ ├── what-is-an-account.md │ ├── address.md │ └── packages.md ├── storage │ ├── index.md │ ├── store-ability.md │ ├── internal-constraint.md │ └── transfer-to-object.md ├── move-basics │ ├── index.md │ ├── address.md │ ├── comments.md │ ├── vector.md │ ├── constants.md │ ├── abilities-introduction.md │ ├── expression.md │ ├── type-reflection.md │ └── copy-ability.md ├── index.md ├── 404.md └── object │ ├── index.md │ ├── evolution-of-move.md │ └── object-model.md ├── packages ├── reference │ ├── sources │ │ ├── uses.move │ │ ├── constants.move │ │ ├── equality.move │ │ ├── friends.move │ │ ├── functions.move │ │ ├── generics.move │ │ ├── modules.move │ │ ├── overview.move │ │ ├── packages.move │ │ ├── structs.move │ │ ├── variables.move │ │ ├── control-flow.move │ │ ├── index-syntax.move │ │ ├── introduction.move │ │ ├── method-syntax.move │ │ ├── unit-testing.move │ │ ├── coding-conventions.move │ │ ├── primitive-types.move │ │ ├── abort-and-assert.move │ │ └── abilities.move │ ├── Move.toml │ └── Move.lock ├── samples │ ├── Move.toml │ ├── sources │ │ ├── move-basics │ │ │ ├── string-custom.move │ │ │ ├── module-label.move │ │ │ ├── constants-naming.move │ │ │ ├── constants.move │ │ │ ├── function_use.move │ │ │ ├── importing-modules-external.move │ │ │ ├── importing-modules.move │ │ │ ├── importing-modules-two.move │ │ │ ├── importing-modules-self.move │ │ │ ├── comments-line.move │ │ │ ├── importing-modules-conflict-resolution.move │ │ │ ├── importing-modules-grouped.move │ │ │ ├── comments-block.move │ │ │ ├── constants-config.move │ │ │ ├── module-members.move │ │ │ ├── importing-modules-members.move │ │ │ ├── comments-doc.move │ │ │ ├── drop-ability.move │ │ │ ├── constants-shop-price.move │ │ │ ├── copy-ability.move │ │ │ ├── struct-methods-3.move │ │ │ ├── module.move │ │ │ ├── struct-methods.move │ │ │ ├── address.move │ │ │ ├── primitive-types.move │ │ │ ├── enum-and-match-2.move │ │ │ ├── type-reflection.move │ │ │ ├── vector.move │ │ │ ├── struct-methods-2.move │ │ │ ├── function.move │ │ │ ├── option.move │ │ │ ├── assert-and-abort.move │ │ │ ├── struct.move │ │ │ ├── string.move │ │ │ ├── references.move │ │ │ └── expression.move │ │ ├── programmability │ │ │ ├── randomness.move │ │ │ ├── testing.move │ │ │ ├── abstract-class.move │ │ │ ├── sui-framework.move │ │ │ ├── package-upgrades.move │ │ │ ├── transaction-blocks.move │ │ │ ├── authorization-patterns.move │ │ │ ├── cryptography-and-hashing.move │ │ │ ├── transaction-context.move │ │ │ ├── module-initializer-2.move │ │ │ ├── collections.move │ │ │ ├── capability-4.move │ │ │ ├── capability-2.move │ │ │ ├── collections-4.move │ │ │ ├── capability-3.move │ │ │ ├── collections-3.move │ │ │ ├── one-time-witness.move │ │ │ ├── module-initializer.move │ │ │ ├── collections-2.move │ │ │ ├── events.move │ │ │ ├── capability.move │ │ │ ├── witness-pattern.move │ │ │ ├── fast-path.move │ │ │ ├── wrapper-type-pattern.move │ │ │ ├── publisher.move │ │ │ ├── dynamic-object-fields.move │ │ │ ├── epoch-and-time.move │ │ │ └── display.move │ │ ├── hello-sui │ │ │ └── README.md │ │ ├── storage │ │ │ ├── store-ability.move │ │ │ └── transfer-to-object.move │ │ ├── your-first-move │ │ │ ├── hello_world.move │ │ │ ├── hello_world_debug.move │ │ │ └── hello_world_docs.move │ │ └── README.md │ ├── examples │ │ ├── ticket.move │ │ └── buffer.move │ └── Move.lock ├── .prettierrc ├── hello_world │ ├── tests │ │ └── hello_world_tests.move │ ├── sources │ │ └── hello_world.move │ ├── Move.lock │ └── Move.toml └── todo_list │ ├── Move.lock │ ├── sources │ └── todo_list.move │ ├── tests │ └── todo_list_tests.move │ └── Move.toml ├── .prettierrc ├── reference ├── book.toml ├── coding-conventions.md ├── TODO ├── primitive-types.md ├── control-flow.md ├── index.md ├── primitive-types │ └── bool.md ├── abilities │ └── object.md └── control-flow │ └── conditionals.md ├── .github ├── .github │ └── pull_request_template.md ├── actions │ └── diffs │ │ └── action.yml └── workflows │ ├── test.yml │ ├── main.yml │ └── docs.yml ├── package.json └── README.md /CNAME: -------------------------------------------------------------------------------- 1 | move-book.com 2 | -------------------------------------------------------------------------------- /site/packages: -------------------------------------------------------------------------------- 1 | ../packages -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .idea 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /book/programmability/balance-and-coin.md: -------------------------------------------------------------------------------- 1 | # Balance & Coin 2 | -------------------------------------------------------------------------------- /book/programmability/authorization-patterns.md: -------------------------------------------------------------------------------- 1 | # Authorization Patterns 2 | -------------------------------------------------------------------------------- /book/programmability/cryptography-and-hashing.md: -------------------------------------------------------------------------------- 1 | # Cryptography and Hashing 2 | -------------------------------------------------------------------------------- /book/programmability/object-capability.md: -------------------------------------------------------------------------------- 1 | # Object Capability 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/uses.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/samples/Move.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "book" 3 | edition = "2024.beta" 4 | 5 | [addresses] 6 | book = "0x0" 7 | -------------------------------------------------------------------------------- /site/src/fonts/Spot-MonoLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MystenLabs/move-book/HEAD/site/src/fonts/Spot-MonoLight.ttf -------------------------------------------------------------------------------- /packages/reference/sources/constants.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/equality.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/friends.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/functions.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/generics.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/modules.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/overview.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/packages.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/structs.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/variables.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /site/src/fonts/Spot-MonoBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MystenLabs/move-book/HEAD/site/src/fonts/Spot-MonoBold.woff2 -------------------------------------------------------------------------------- /site/src/fonts/Spot-MonoLight.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MystenLabs/move-book/HEAD/site/src/fonts/Spot-MonoLight.woff -------------------------------------------------------------------------------- /site/src/fonts/Spot-MonoLight.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MystenLabs/move-book/HEAD/site/src/fonts/Spot-MonoLight.woff2 -------------------------------------------------------------------------------- /site/src/fonts/Spot-MonoMedium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MystenLabs/move-book/HEAD/site/src/fonts/Spot-MonoMedium.woff2 -------------------------------------------------------------------------------- /packages/reference/sources/control-flow.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/index-syntax.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/introduction.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/method-syntax.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/unit-testing.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /site/src/fonts/Spot-MonoRegular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MystenLabs/move-book/HEAD/site/src/fonts/Spot-MonoRegular.woff2 -------------------------------------------------------------------------------- /packages/reference/sources/coding-conventions.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/reference/sources/primitive-types.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/samples/sources/move-basics/string-custom.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /site/src/fonts/Spot-MonoBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MystenLabs/move-book/HEAD/site/src/fonts/Spot-MonoBoldItalic.woff2 -------------------------------------------------------------------------------- /site/src/fonts/Spot-MonoLightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MystenLabs/move-book/HEAD/site/src/fonts/Spot-MonoLightItalic.woff2 -------------------------------------------------------------------------------- /packages/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "useTabs": false, 4 | "printWidth": 100, 5 | "useModuleLabel": true 6 | } 7 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/randomness.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/testing.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /site/src/fonts/Spot-MonoMediumItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MystenLabs/move-book/HEAD/site/src/fonts/Spot-MonoMediumItalic.woff2 -------------------------------------------------------------------------------- /site/src/fonts/Spot-MonoRegularItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MystenLabs/move-book/HEAD/site/src/fonts/Spot-MonoRegularItalic.woff2 -------------------------------------------------------------------------------- /packages/samples/sources/programmability/abstract-class.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/sui-framework.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/package-upgrades.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/transaction-blocks.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/authorization-patterns.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/cryptography-and-hashing.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | -------------------------------------------------------------------------------- /packages/samples/sources/hello-sui/README.md: -------------------------------------------------------------------------------- 1 | # Hello Sui 2 | 3 | This tutorial is packed as a separate package which you can find in the root of this repository. 4 | -------------------------------------------------------------------------------- /packages/reference/sources/abort-and-assert.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | module ref::abort_and_assert { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /packages/samples/sources/storage/store-ability.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | module book::store_ability { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "useTabs": false, 4 | "printWidth": 100, 5 | "semi": true, 6 | "singleQuote": true, 7 | "trailingComma": "all", 8 | "proseWrap": "always" 9 | } 10 | -------------------------------------------------------------------------------- /reference/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | title = "The Move Reference" 3 | description = "The Move Language Reference maintained by the Move core team." 4 | authors = ["The Move Contributors"] 5 | language = "en" 6 | -------------------------------------------------------------------------------- /site/src/theme/CodeBlock/Buttons/WordWrapButton/styles.module.css: -------------------------------------------------------------------------------- 1 | .wordWrapButtonIcon { 2 | width: 1.2rem; 3 | height: 1.2rem; 4 | } 5 | 6 | .wordWrapButtonEnabled .wordWrapButtonIcon { 7 | color: var(--ifm-color-primary); 8 | } 9 | -------------------------------------------------------------------------------- /.github/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Please, make sure to reflect the target in the header of your PR! 4 | 5 | ## Changes 6 | 7 | - [ ] book: ... 8 | - [ ] reference: ... 9 | - [ ] other (specify): ... 10 | -------------------------------------------------------------------------------- /site/sidebar-book.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import { loadSidebarsFromYaml } from './src/plugins/yaml-sidebar'; 5 | export default loadSidebarsFromYaml('./../book/sidebar.yml'); 6 | -------------------------------------------------------------------------------- /reference/coding-conventions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Coding Conventions | Reference' 3 | description: '' 4 | --- 5 | 6 | # Coding Conventions 7 | 8 | See [Sui's Coding Conventions for Move](https://docs.sui.io/concepts/sui-move-concepts/conventions) 9 | -------------------------------------------------------------------------------- /site/sidebar-reference.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import { loadSidebarsFromYaml } from './src/plugins/yaml-sidebar'; 5 | export default loadSidebarsFromYaml('./../reference/sidebar.yml'); 6 | -------------------------------------------------------------------------------- /site/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@docusaurus/tsconfig", 4 | "compilerOptions": { 5 | "baseUrl": "." 6 | }, 7 | "exclude": [".docusaurus", "build"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/samples/sources/move-basics/module-label.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // ANCHOR: module 5 | // Module label. 6 | module book::my_module; 7 | 8 | // module body 9 | // ANCHOR_END: module 10 | -------------------------------------------------------------------------------- /book/move-advanced/index.md: -------------------------------------------------------------------------------- 1 | # Advanced Move Usage 2 | 3 | This chapter covers advanced features of the Move language, including various extended behaviors for 4 | advanced programming. This includes advanced usage of the language itself, plus the package and 5 | build system. 6 | -------------------------------------------------------------------------------- /book/appendix/contributing.md: -------------------------------------------------------------------------------- 1 | # Appendix E: Contributing 2 | 3 | To contribute to this book, please, submit a pull request to the 4 | [GitHub repository](https://github.com/MystenLabs/move-book). The repository contains the source 5 | files for the book, written in mdBook format. 6 | -------------------------------------------------------------------------------- /book/guides/index.md: -------------------------------------------------------------------------------- 1 | # Guides 2 | 3 | This section contains a collection of guides that cover various aspects of programming on Sui. They 4 | are intended to provide a deeper understanding of Sui blockchain and Move language, while also 5 | aiming at practical challenges and solutions. 6 | -------------------------------------------------------------------------------- /packages/reference/Move.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reference" 3 | edition = "2024.alpha" 4 | 5 | [dependencies.Sui] 6 | git = "https://github.com/MystenLabs/sui.git" 7 | subdir = "crates/sui-framework/packages/sui-framework" 8 | rev = "framework/mainnet" 9 | 10 | [addresses] 11 | ref = "0x0" 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "pnpm -C site build", 4 | "start": "pnpm -C site start", 5 | "serve": "pnpm -C site serve" 6 | }, 7 | "packageManager": "pnpm@9.15.2+sha512.93e57b0126f0df74ce6bff29680394c0ba54ec47246b9cf321f0121d8d9bb03f750a705f24edc3c1180853afd7c2c3b94196d0a3d53d3e069d9e2793ef11f321" 8 | } 9 | -------------------------------------------------------------------------------- /site/src/theme/Icon/Success/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { type ReactNode } from 'react'; 2 | import type { Props } from '@theme/Icon/Success'; 3 | 4 | export default function IconSuccess(props: Props): ReactNode { 5 | return ( 6 |
7 | 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /site/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /packages/hello_world/tests/hello_world_tests.move: -------------------------------------------------------------------------------- 1 | // ANCHOR: test 2 | #[test_only] 3 | module hello_world::hello_world_tests; 4 | 5 | use std::unit_test::assert_eq; 6 | 7 | use hello_world::hello_world; 8 | 9 | #[test] 10 | fun test_hello_world() { 11 | assert_eq!(hello_world::hello_world(), b"Hello, World!".to_string()); 12 | } 13 | // ANCHOR_END: test -------------------------------------------------------------------------------- /site/src/theme/CodeBlock/Buttons/Button/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { type ReactNode } from 'react'; 2 | import clsx from 'clsx'; 3 | import type { Props } from '@theme/CodeBlock/Buttons/Button'; 4 | 5 | export default function CodeBlockButton({ className, ...props }: Props): ReactNode { 6 | return 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/capability.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // ANCHOR: main 5 | module book::capability; 6 | 7 | use std::string::String; 8 | use sui::event; 9 | 10 | /// The capability granting the application admin the right to create new 11 | /// accounts in the system. 12 | public struct AdminCap has key, store { id: UID } 13 | 14 | /// The user account in the system. 15 | public struct Account has key, store { 16 | id: UID, 17 | name: String 18 | } 19 | 20 | /// A simple `Ping` event with no data. 21 | public struct Ping has copy, drop { by: ID } 22 | 23 | /// Creates a new account in the system. Requires the `AdminCap` capability 24 | /// to be passed as the first argument. 25 | public fun new(_: &AdminCap, name: String, ctx: &mut TxContext): Account { 26 | Account { 27 | id: object::new(ctx), 28 | name, 29 | } 30 | } 31 | 32 | /// Account, and any other objects, can also be used as a Capability in the 33 | /// application. For example, to emit an event. 34 | public fun send_ping(acc: &Account) { 35 | event::emit(Ping { 36 | by: acc.id.to_inner() 37 | }) 38 | } 39 | 40 | /// Updates the account name. Can only be called by the `Account` owner. 41 | public fun update(account: &mut Account, name: String) { 42 | account.name = name; 43 | } 44 | // ANCHOR_END: main 45 | -------------------------------------------------------------------------------- /book/guides/open-sourcing-libraries.md: -------------------------------------------------------------------------------- 1 | # Open Sourcing Libraries 2 | 3 | Open sourcing libraries is a great way to contribute to the Move ecosystem. This guide will help you 4 | understand how to open source a library, how to write tests, and how to document your library. 5 | 6 | ## README 7 | 8 | TODO: readme 9 | 10 | ## Named Addresses 11 | 12 | TODO: named address 13 | 14 | ## Generating Documentation 15 | 16 | TODO: docgen 17 | 18 | ## Adding Examples 19 | 20 | When publishing a package that is intended to be used (an NFT protocol or a library), it is 21 | important to showcase how this package can be used. This is where examples come in handy. There's no 22 | special functionality for examples in Move, however, there are some conventions that are used to 23 | mark examples. First of all, only sources are included into the package bytecode, so any code placed 24 | in a different directory will not be included, but will be tested! 25 | 26 | This is why placing examples into a separate `examples/` directory is a good idea. 27 | 28 | ```bash 29 | sources/ 30 | protocol.move 31 | library.move 32 | tests/ 33 | protocol_test.move 34 | examples/ 35 | my_example.move 36 | Move.toml 37 | ``` 38 | 39 | ## Tags and Releases (Git) 40 | 41 | TODO: tags and releases 42 | 43 | ## Tricks to allow compatibility with closed source 44 | 45 | TODO: compatibility via empty functions with signatures 46 | -------------------------------------------------------------------------------- /book/appendix/glossary.md: -------------------------------------------------------------------------------- 1 | # Appendix A: Glossary 2 | 3 | - Fast Path - term used to describe a transaction that does not involve shared objects, and can be 4 | executed without the need for consensus. 5 | - Parallel Execution - term used to describe the ability of the Sui runtime to execute transactions 6 | in parallel, including the ones that involve shared objects. 7 | - Internal Type - type that is defined within the module. Fields of this type can not be accessed 8 | from outside the module, and, in case of "key"-only abilities, can not be used in `public_*` 9 | transfer functions. 10 | 11 | ## Abilities 12 | 13 | - key - ability that allows the struct to be used as a key in the storage. On Sui, the key ability 14 | marks an object and requires the first field to be a `id: UID`. 15 | - store - ability that allows the struct to be stored inside other objects. This ability relaxes 16 | restrictions applied to internal structs, allowing `public_*` transfer functions to accept them as 17 | arguments. It also enables the object to be stored as a dynamic field. 18 | - copy - ability that allows the struct to be copied. On Sui, the `copy` ability conflicts with the 19 | `key` ability, and can not be used together with it. 20 | - drop - ability that allows the struct to be ignored or discarded. On Sui, the `drop` ability 21 | cannot be used together with the `key` ability, as objects are not allowed to be ignored. 22 | -------------------------------------------------------------------------------- /site/src/fonts/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Spot Mono'; 3 | font-style: normal; 4 | font-weight: 100 300; 5 | src: url('./Spot-MonoLight.woff2') format('woff2'); 6 | } 7 | 8 | @font-face { 9 | font-family: 'Spot Mono'; 10 | font-style: italic; 11 | font-weight: 100 300; 12 | src: url('./Spot-MonoLightItalic.woff2') format('woff2'); 13 | } 14 | 15 | @font-face { 16 | font-family: 'Spot Mono'; 17 | font-style: normal; 18 | font-weight: 400 500; 19 | src: url('./Spot-MonoRegular.woff2') format('woff2'); 20 | } 21 | 22 | @font-face { 23 | font-family: 'Spot Mono'; 24 | font-style: italic; 25 | font-weight: 400 500; 26 | src: url('./Spot-MonoRegularItalic.woff2') format('woff2'); 27 | } 28 | 29 | @font-face { 30 | font-family: 'Spot Mono'; 31 | font-style: normal; 32 | font-weight: 600 700; 33 | src: url('./Spot-MonoMedium.woff2') format('woff2'); 34 | } 35 | 36 | @font-face { 37 | font-family: 'Spot Mono'; 38 | font-style: italic; 39 | font-weight: 600 700; 40 | src: url('./Spot-MonoMediumItalic.woff2') format('woff2'); 41 | } 42 | 43 | @font-face { 44 | font-family: 'Spot Mono'; 45 | font-style: normal; 46 | font-weight: 800 1000; 47 | src: url('./Spot-MonoBold.woff2') format('woff2'); 48 | } 49 | 50 | @font-face { 51 | font-family: 'Spot Mono'; 52 | font-style: italic; 53 | font-weight: 800 1000; 54 | src: url('./Spot-MonoBoldItalic.woff2') format('woff2'); 55 | } 56 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | # Copy-pasta from MystenLabs/sui/.github/workflows/docs.yml 2 | 3 | name: Documentation 4 | permissions: 5 | contents: read 6 | 7 | on: 8 | pull_request: 9 | 10 | jobs: 11 | diff: 12 | runs-on: [ubuntu-latest] 13 | outputs: 14 | isDoc: ${{ steps.diff.outputs.isDoc }} 15 | isOldDoc: ${{ steps.diff.outputs.isOldDoc }} 16 | steps: 17 | - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # Pin v4.1.1 18 | - name: Detect Changes 19 | uses: './.github/actions/diffs' 20 | id: diff 21 | 22 | # temporarily disabled, we have too many special words like MIST 23 | # spelling: 24 | # name: Lint documentation 25 | # needs: diff 26 | # if: needs.diff.outputs.isDoc == 'true' 27 | # runs-on: [ubuntu-latest] 28 | # steps: 29 | # - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # Pin v4.1.1 30 | # - name: Spell Check Docs 31 | # uses: crate-ci/typos@v1.16.11 32 | # with: 33 | # files: ./book ./reference 34 | 35 | build: 36 | runs-on: ubuntu-latest 37 | steps: 38 | - uses: actions/checkout@v4 39 | - uses: pnpm/action-setup@v4 40 | with: 41 | cache: 'pnpm' 42 | - name: Install dependencies 43 | run: pnpm i 44 | working-directory: ./site 45 | - name: Build website 46 | run: pnpm build 47 | working-directory: ./site 48 | -------------------------------------------------------------------------------- /packages/samples/sources/move-basics/vector.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #[allow(unused_variable)] 5 | module book::vector_syntax { 6 | #[test_only] 7 | use std::unit_test::assert_eq; 8 | #[test] fun test_vector() { 9 | // ANCHOR: literal 10 | // An empty vector of bool elements. 11 | let empty: vector = vector[]; 12 | 13 | // A vector of u8 elements. 14 | let v: vector = vector[10, 20, 30]; 15 | 16 | // A vector of vector elements. 17 | let vv: vector> = vector[ 18 | vector[10, 20], 19 | vector[30, 40] 20 | ]; 21 | // ANCHOR_END: literal 22 | } 23 | 24 | #[test] fun vector_methods() { 25 | // ANCHOR: methods 26 | let mut v = vector[10u8, 20, 30]; 27 | 28 | assert_eq!(v.length(), 3); 29 | assert_eq!(v.is_empty(), false); 30 | 31 | v.push_back(40); 32 | let last_value = v.pop_back(); 33 | 34 | assert_eq!(last_value, 40); 35 | // ANCHOR_END: methods 36 | } 37 | } 38 | 39 | 40 | module book::non_droppable_vec { 41 | 42 | // ANCHOR: no_drop 43 | /// A struct without `drop` ability. 44 | public struct NoDrop {} 45 | 46 | #[test] 47 | fun test_destroy_empty() { 48 | // Initialize a vector of `NoDrop` elements. 49 | let v = vector[]; 50 | 51 | // While we know that `v` is empty, we still need to call 52 | // the explicit `destroy_empty` function to discard the vector. 53 | v.destroy_empty(); 54 | } 55 | // ANCHOR_END: no_drop 56 | } 57 | -------------------------------------------------------------------------------- /packages/samples/sources/move-basics/struct-methods-2.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // ANCHOR: hero_and_villain 5 | module book::hero_and_villain; 6 | 7 | /// A struct representing a hero. 8 | public struct Hero has drop { 9 | health: u8, 10 | } 11 | 12 | /// A struct representing a villain. 13 | public struct Villain has drop { 14 | health: u8, 15 | } 16 | 17 | /// Create a new Hero. 18 | public fun new_hero(): Hero { Hero { health: 100 } } 19 | 20 | /// Create a new Villain. 21 | public fun new_villain(): Villain { Villain { health: 200 } } 22 | 23 | // Alias for the `hero_health` method. It will be imported automatically when 24 | // the module is imported. 25 | public use fun hero_health as Hero.health; 26 | 27 | public fun hero_health(hero: &Hero): u8 { hero.health } 28 | 29 | // Alias for the `villain_health` method. Will be imported automatically 30 | // when the module is imported. 31 | public use fun villain_health as Villain.health; 32 | 33 | public fun villain_health(villain: &Villain): u8 { villain.health } 34 | 35 | #[test_only] 36 | use std::unit_test::assert_eq; 37 | 38 | #[test] 39 | // Test the methods of the `Hero` and `Villain` structs. 40 | fun test_associated_methods() { 41 | let hero = new_hero(); 42 | assert_eq!(hero.health(), 100); 43 | 44 | let villain = new_villain(); 45 | assert_eq!(villain.health(), 200); 46 | } 47 | // ANCHOR_END: hero_and_villain 48 | -------------------------------------------------------------------------------- /site/src/css/code.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Mysten Labs, Inc. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | /* Magic comments for Prism; see docusaurus.config.ts */ 7 | 8 | .error-comment { 9 | --border-width: 3px; 10 | 11 | background-color: #fff3f2; 12 | display: block; 13 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 14 | padding: 0 calc(var(--ifm-pre-padding) - var(--border-width)); 15 | border-left: var(--border-width) solid #ff000080; 16 | } 17 | 18 | [data-theme='dark'] .error-comment { 19 | background-color: #ff000020; 20 | } 21 | 22 | .highlight-important { 23 | background-color: #d6f6f8; 24 | } 25 | 26 | [data-theme='dark'] .highlight-important { 27 | background-color: #14393e; 28 | } 29 | 30 | .hidden-line { 31 | display: none; 32 | } 33 | 34 | /* Code-like comments */ 35 | 36 | .comment { 37 | color: #a0a1a7; 38 | font-style: italic; 39 | } 40 | 41 | [data-theme='dark'] .comment { 42 | color: #5c6370; 43 | font-style: italic; 44 | } 45 | 46 | /* Inline code blocks, see theme/CodeInline/index.tsx */ 47 | 48 | .inline-code { 49 | font-family: 'Spot Mono', SFMono-Regular, Menlo, Monaco, monospace; 50 | background-color: var(--ifm-code-background); 51 | padding: 0.1em 0.1em; 52 | border-radius: 0.05em; 53 | } 54 | 55 | [data-theme='dark'] .inline-code { 56 | background-color: var(--ifm-code-background); 57 | } 58 | 59 | /* Code block icons */ 60 | 61 | .code-icon { 62 | font-size: calc(var(--ifm-code-font-size) + 4px); 63 | } 64 | -------------------------------------------------------------------------------- /packages/samples/examples/ticket.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | module book::ticket; 5 | 6 | /// A Ticket for an event or a service. Non-transferable by default and 7 | /// the usage varies based on the application. 8 | public struct Ticket has key { 9 | id: UID, 10 | used: bool, 11 | metadata: T 12 | } 13 | 14 | /// Create a new Ticket with the metadata and the context. 15 | /// No need for a Witness here! 16 | public fun new(metadata: T, ctx: &mut TxContext): Ticket { 17 | Ticket { 18 | id: object::new(ctx), 19 | used: false, 20 | metadata 21 | } 22 | } 23 | 24 | /// Consume the Ticket. Requires a Witness of the metadata type. 25 | /// May or may not be implemented by the application. 26 | public fun consume(_meta: T, ticket: &mut Ticket) { 27 | ticket.used = true; 28 | } 29 | 30 | /// Transfer the Ticket to another user. Requires a Witness of the metadata type. 31 | /// May or may not be implemented by the application. 32 | public fun transfer(_meta: T, ticket: Ticket, to: address) { 33 | transfer::transfer(ticket, to) 34 | } 35 | 36 | /// Get the metadata of the Ticket. 37 | public fun metadata(ticket: &Ticket): &T { 38 | &ticket.metadata 39 | } 40 | 41 | /// Check if the Ticket has been used. 42 | public fun is_used(ticket: &Ticket): bool { 43 | ticket.used 44 | } 45 | -------------------------------------------------------------------------------- /packages/samples/examples/buffer.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | module book::buffer; 5 | 6 | /// Error returned when the buffer is overflowed. 7 | const EBufferOverflow: u64 = 0; 8 | 9 | /// The Buffer struct represents a growable buffer. 10 | public struct Buffer { 11 | data: vector, 12 | expected_len: Option 13 | } 14 | 15 | /// Creates a new empty buffer. 16 | public fun new(): Buffer { 17 | Buffer { data: vector[], expected_len: option::none() } 18 | } 19 | 20 | /// Creates a new empty buffer with the specified capacity (in bytes). 21 | /// If the buffer is overflowed, tx aborts with `EBufferOverflow`. 22 | public fun alloc(len: u64): Buffer { 23 | Buffer { data: vector[], expected_len: option::some(len) } 24 | } 25 | 26 | /// Pushes the given data to the end of the buffer. 27 | public fun push(self: &mut Buffer, data: vector) { 28 | self.expected_len.do_ref!(|max_len| assert!(self.len() + data.length() <= *max_len, EBufferOverflow)); 29 | self.data.append(data) 30 | } 31 | 32 | /// Unwraps the buffer and returns the underlying vector. 33 | public fun unwrap(self: Buffer): vector { 34 | let Buffer { data, expected_len: _ } = self; 35 | data 36 | } 37 | 38 | /// Returns the length of the buffer. 39 | public fun len(self: &Buffer): u64 { 40 | self.data.length() 41 | } 42 | 43 | /// Returns `true` if the buffer is empty. 44 | public fun is_empty(self: &Buffer): bool { 45 | self.data.is_empty() 46 | } 47 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/witness-pattern.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | module book::witness_definition; 5 | 6 | // ANCHOR: definition 7 | /// Canonical definition of a witness - a type with the `drop` ability. 8 | public struct MyWitness has drop {} 9 | // ANCHOR_END: definition 10 | 11 | // ANCHOR: regulated_coin 12 | /// A custom RegulatedCoin type with implementable functions. 13 | public struct RegulatedCoin has key { 14 | id: UID, 15 | value: u64 16 | } 17 | 18 | /// Protected function - requires a Witness. 19 | /// Mints a new `RegulatedCoin` with the value. 20 | public fun mint(_: T, value: u64, ctx: &mut TxContext): RegulatedCoin { 21 | RegulatedCoin { id: object::new(ctx), value } 22 | } 23 | 24 | /// Protected function - requires a Witness. 25 | /// Burns the `RegulatedCoin` and returns the value. 26 | public fun burn(_: T, coin: RegulatedCoin): u64 { 27 | let RegulatedCoin { id, value } = coin; 28 | id.delete(); 29 | value 30 | } 31 | 32 | /// Protected function - requires a Witness. 33 | public fun transfer(_: T, coin: RegulatedCoin, to: address) { 34 | transfer::transfer(coin, to) 35 | } 36 | 37 | /// Public API - does not require a Witness. 38 | public fun join(coin: &mut RegulatedCoin, other: RegulatedCoin) { 39 | let RegulatedCoin { id, value } = other; 40 | coin.value = coin.value + value; 41 | id.delete(); 42 | } 43 | // ANCHOR_END: regulated_coin 44 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/fast-path.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // ANCHOR: main 5 | module book::coffee_machine { 6 | /// Coffee machine is a shared object, hence requires `key` ability. 7 | public struct CoffeeMachine has key { id: UID, counter: u16 } 8 | 9 | /// Cup is an owned object. 10 | public struct Cup has key, store { id: UID, has_coffee: bool } 11 | 12 | /// Initialize the module and share the `CoffeeMachine` object. 13 | fun init(ctx: &mut TxContext) { 14 | transfer::share_object(CoffeeMachine { 15 | id: object::new(ctx), 16 | counter: 0 17 | }); 18 | } 19 | 20 | /// Take a cup out of thin air. This is a fast path operation. 21 | public fun take_cup(ctx: &mut TxContext): Cup { 22 | Cup { id: object::new(ctx), has_coffee: false } 23 | } 24 | 25 | /// Make coffee and pour it into the cup. Requires consensus. 26 | public fun make_coffee(machine: &mut CoffeeMachine, cup: &mut Cup) { 27 | machine.counter = machine.counter + 1; 28 | cup.has_coffee = true; 29 | } 30 | 31 | /// Drink coffee from the cup. This is a fast path operation. 32 | public fun drink_coffee(cup: &mut Cup) { 33 | cup.has_coffee = false; 34 | } 35 | 36 | /// Put the cup back. This is a fast path operation. 37 | public fun put_back(cup: Cup) { 38 | let Cup { id, has_coffee: _ } = cup; 39 | id.delete(); 40 | } 41 | } 42 | // ANCHOR_END: main 43 | -------------------------------------------------------------------------------- /reference/primitive-types/bool.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Bool | Reference' 3 | description: '' 4 | --- 5 | 6 | # Bool 7 | 8 | `bool` is Move's primitive type for boolean `true` and `false` values. 9 | 10 | ## Literals 11 | 12 | Literals for `bool` are either `true` or `false`. 13 | 14 | ## Operations 15 | 16 | ### Logical 17 | 18 | `bool` supports three logical operations: 19 | 20 | | Syntax | Description | Equivalent Expression | 21 | | ------------------------- | ---------------------------- | ------------------------------------------------------------------- | 22 | | `&&` | short-circuiting logical and | `p && q` is equivalent to `if (p) q else false` | 23 | | || | short-circuiting logical or | p || q is equivalent to `if (p) true else q` | 24 | | `!` | logical negation | `!p` is equivalent to `if (p) false else true` | 25 | 26 | ### Control Flow 27 | 28 | `bool` values are used in several of Move's control-flow constructs: 29 | 30 | - [`if (bool) { ... }`](./../control-flow/conditionals) 31 | - [`while (bool) { .. }`](./../control-flow/loops) 32 | - [`assert!(bool, u64)`](./../abort-and-assert) 33 | 34 | ## Ownership 35 | 36 | As with the other scalar values built-in to the language, boolean values are implicitly copyable, 37 | meaning they can be copied without an explicit instruction such as 38 | [`copy`](.././variables#move-and-copy). 39 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/wrapper-type-pattern.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // ANCHOR: main 5 | module book::wrapper_type_pattern; 6 | 7 | /// Very simple stack implementation using the wrapper type pattern. Does not allow 8 | /// accessing the elements unless they are popped. 9 | public struct Stack(vector) has copy, store, drop; 10 | 11 | /// Create a new instance by wrapping the value. 12 | public fun new(value: vector): Stack { 13 | Stack(value) 14 | } 15 | 16 | /// Push an element to the stack. 17 | public fun push_back(v: &mut Stack, el: T) { 18 | v.0.push_back(el); 19 | } 20 | 21 | /// Pop an element from the stack. Unlike `vector`, this function won't 22 | /// fail if the stack is empty and will return `None` instead. 23 | public fun pop_back(v: &mut Stack): Option { 24 | if (v.0.length() == 0) option::none() 25 | else option::some(v.0.pop_back()) 26 | } 27 | 28 | /// Get the size of the stack. 29 | public fun size(v: &Stack): u64 { 30 | v.0.length() 31 | } 32 | // ANCHOR_END: main 33 | 34 | // ANCHOR: common 35 | /// Allows reading the contents of the `Stack`. 36 | public fun inner(v: &Stack): &vector { &v.0 } 37 | 38 | /// Allows mutable access to the contents of the `Stack`. 39 | public fun inner_mut(v: &mut Stack): &mut vector { &mut v.0 } 40 | 41 | /// Unpacks the `Stack` into the underlying `vector`. 42 | public fun into_inner(v: Stack): vector { 43 | let Stack(inner) = v; 44 | inner 45 | } 46 | // ANCHOR_END: common 47 | -------------------------------------------------------------------------------- /book/concepts/what-is-an-account.md: -------------------------------------------------------------------------------- 1 | # Account 2 | 3 | 17 | 18 | An account is a way to identify a user. An account is generated from a private key, and is 19 | identified by an address. An account can own objects, and can send transactions. Every transaction 20 | has a sender, and the sender is identified by an [address](./address). 21 | 22 | Sui supports multiple cryptographic algorithms for account generation. The two supported curves are 23 | ed25519, secp256k1, and there is also a special way of generating an account - zklogin. The 24 | cryptographic agility - the unique feature of Sui - allows for flexibility in the account 25 | generation. 26 | 27 | 28 | 29 | ## Further Reading 30 | 31 | - [Cryptography in Sui](https://blog.sui.io/wallet-cryptography-specifications/) in the 32 | [Sui Blog](https://blog.sui.io) 33 | - [Keys and Addresses](https://docs.sui.io/concepts/cryptography/transaction-auth/keys-addresses) in 34 | the [Sui Docs](https://docs.sui.io) 35 | - [Signatures](https://docs.sui.io/concepts/cryptography/transaction-auth/signatures) in the 36 | [Sui Docs](https://docs.sui.io) 37 | -------------------------------------------------------------------------------- /site/src/theme/DocPaginator/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import React, { type ReactNode } from 'react'; 5 | import clsx from 'clsx'; 6 | import { translate } from '@docusaurus/Translate'; 7 | import PaginatorNavLink from '@theme/PaginatorNavLink'; 8 | import type { Props } from '@theme/DocPaginator'; 9 | 10 | /** 11 | * Replaces default buttons with icons. 12 | * Swizzled part. 13 | */ 14 | export default function DocPaginator(props: Props): ReactNode { 15 | const { className, previous, next } = props; 16 | return ( 17 | 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /packages/samples/sources/move-basics/function.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #[allow(unused_variable, unused_function, unused_let_mut)] 5 | // ANCHOR: math 6 | module book::math; 7 | 8 | #[test_only] 9 | use std::unit_test::assert_eq; 10 | 11 | /// Function takes two arguments of type `u64` and returns their sum. 12 | /// The `public` visibility modifier makes the function accessible from 13 | /// outside the module. 14 | public fun add(a: u64, b: u64): u64 { 15 | a + b 16 | } 17 | 18 | #[test] 19 | fun test_add() { 20 | let sum = add(1, 2); 21 | assert_eq!(sum, 3); 22 | } 23 | // ANCHOR_END: math 24 | 25 | // ANCHOR: return_nothing 26 | fun return_nothing() { 27 | // empty expression, function returns `()` 28 | } 29 | // ANCHOR_END: return_nothing 30 | 31 | // ANCHOR: tuple_return 32 | fun get_name_and_age(): (vector, u8) { 33 | (b"John", 25) 34 | } 35 | // ANCHOR_END: tuple_return 36 | 37 | #[test] fun test_get_name_and_age() { 38 | // ANCHOR: tuple_return_imm 39 | // Tuple must be destructured to access its elements. 40 | // Name and age are declared as immutable variables. 41 | let (name, age) = get_name_and_age(); 42 | assert_eq!(name, b"John"); 43 | assert_eq!(age, 25); 44 | // ANCHOR_END: tuple_return_imm 45 | 46 | // ANCHOR: tuple_return_mut 47 | // declare name as mutable, age as immutable 48 | let (mut name, age) = get_name_and_age(); 49 | // ANCHOR_END: tuple_return_mut 50 | 51 | // ANCHOR: tuple_return_ignore 52 | // ignore the name, only use the age 53 | let (_, age) = get_name_and_age(); 54 | // ANCHOR_END: tuple_return_ignore 55 | } 56 | -------------------------------------------------------------------------------- /packages/todo_list/tests/todo_list_tests.move: -------------------------------------------------------------------------------- 1 | /* 2 | #[test_only] 3 | module todo_list::todo_list_tests { 4 | // uncomment this line to import the module 5 | // use todo_list::todo_list; 6 | 7 | const ENotImplemented: u64 = 0; 8 | 9 | #[test] 10 | fun test_todo_list() { 11 | // pass 12 | } 13 | 14 | #[test, expected_failure(abort_code = todo_list::todo_list_tests::ENotImplemented)] 15 | fun test_todo_list_fail() { 16 | abort ENotImplemented 17 | } 18 | } 19 | */ 20 | 21 | #[test_only] 22 | module todo_list::todo_list_tests { 23 | // uncomment this line to import the module 24 | // use todo_list::todo_list; 25 | 26 | // const ENotImplemented: u64 = 0; 27 | 28 | // #[test] 29 | // fun test_todo() { 30 | // let ctx = &mut tx_context::dummy(); 31 | // let (mut list, cap) = todo_list::new(ctx); 32 | 33 | // cap.add(&mut list, b"Clean the apartment".to_string()); 34 | // cap.add(&mut list, b"Buy groceries".to_string()); 35 | 36 | // assert!(list.length() == 2, 0); 37 | // assert!(cap.remove(&mut list, 0) == b"Clean the apartment".to_string(), 0); 38 | // assert!(list.length() == 1, 0); 39 | 40 | // let guest = cap.invite(&list, ctx); 41 | 42 | // guest.add(&mut list, b"Walk the dog".to_string()); 43 | 44 | // assert!(cap.remove(&mut list, 0) == b"Buy groceries".to_string(), 1); 45 | // assert!(guest.remove(&mut list, 0) == b"Walk the dog".to_string(), 2); 46 | 47 | // assert!(list.length() == 0, 3); 48 | 49 | // guest.leave(); 50 | // list.delete(cap); 51 | // } 52 | } 53 | -------------------------------------------------------------------------------- /book/before-we-begin/install-move-registry-cli.md: -------------------------------------------------------------------------------- 1 | # Install MVR 2 | 3 | [Move Registry (MVR)](https://moveregistry.com) is a package manager for Move. It allows anyone to 4 | publish and use published packages in new applications written in Move. Local binary allows 5 | searching packages in the registry as well as installing them as a part of the Sui CLI build 6 | process. 7 | 8 | ## Installing via suiup 9 | 10 | The best way to install MVR is by using [`suiup`](https://github.com/MystenLabs/suiup). Suiup 11 | provides an easy way to update and manage different versions of binaries. 12 | 13 | Installation instructions for `suiup` can be found 14 | [in the repository README](https://github.com/MystenLabs/suiup). 15 | 16 | To install Move Registry CLI, run the following command: 17 | 18 | ```bash 19 | suiup install mvr 20 | ``` 21 | 22 | After installation, Move Registry will be available as `mvr`. 23 | 24 | ## Download Binary 25 | 26 | You can download the latest MVR binary from the 27 | [releases page](https://github.com/MystenLabs/mvr/releases). The binary is available for macOS, 28 | Linux and Windows. Unlike [Sui](./install-sui.md), the MVR binary is not changing between 29 | environments and supports both `testnet` and `mainnet`. 30 | 31 | ## Install Using Cargo 32 | 33 | You can install and build MVR locally by using Cargo (requires Rust) 34 | 35 | ```bash 36 | cargo install --locked --git https://github.com/mystenlabs/mvr --branch release mvr 37 | ``` 38 | 39 | ## Troubleshooting 40 | 41 | For troubleshooting the installation process, please refer to the 42 | [Install MVR](https://docs.suins.io/move-registry/tooling/mvr-cli#installation) Guide. 43 | -------------------------------------------------------------------------------- /book/object/evolution-of-move.md: -------------------------------------------------------------------------------- 1 | # Evolution of Move 2 | 3 | While Move was created to manage digital assets, its initial storage model was bulky and not 4 | well-suited for many use cases. For instance, if Alice wanted to transfer an asset X to Bob, Bob had 5 | to create a new "empty" resource, and then Alice could transfer asset X to Bob. This process was not 6 | intuitive and presented implementation challenges, partly due to the restrictive design of 7 | [Diem](https://www.diem.com/en-us). Another drawback of the original design was the lack of built-in 8 | support for a "transfer" operation, requiring every module to implement its own storage transfer 9 | logic. Additionally, managing heterogeneous collections of assets in a single account was 10 | particularly challenging. 11 | 12 | Sui addressed these challenges by redesigning the storage and ownership model of objects to more 13 | closely resemble real-world object interactions. With a native concept of ownership and _transfer_, 14 | Alice can directly transfer asset X to Bob. Furthermore, Bob can maintain a collection of different 15 | assets without any preparatory steps. These improvements laid the foundation for the Object Model in 16 | Sui. 17 | 18 | ## Summary 19 | 20 | - Move's initial storage model was not well-suited for managing digital assets, requiring complex 21 | and restrictive transfer operations. 22 | - Sui introduced the Object Model, which provides a native concept of ownership, simplifying asset 23 | management and enabling heterogeneous collections. 24 | 25 | ## Further Reading 26 | 27 | - [Why We Created Sui Move](https://blog.sui.io/why-we-created-sui-move/) by Sam Blackshear 28 | -------------------------------------------------------------------------------- /packages/samples/sources/move-basics/option.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #[allow(unused_variable)] 5 | // ANCHOR: registry 6 | module book::user_registry; 7 | 8 | use std::string::String; 9 | 10 | /// A struct representing a user record. 11 | public struct User has drop { 12 | first_name: String, 13 | middle_name: Option, 14 | last_name: String, 15 | } 16 | 17 | /// Create a new `User` struct with the given fields. 18 | public fun register( 19 | first_name: String, 20 | middle_name: Option, 21 | last_name: String, 22 | ): User { 23 | User { first_name, middle_name, last_name } 24 | } 25 | // ANCHOR_END: registry 26 | 27 | #[test_only] 28 | use std::unit_test::{assert_eq, assert_ref_eq}; 29 | 30 | #[test] fun use_option() { 31 | 32 | // ANCHOR: usage 33 | // `option::some` creates an `Option` value with a value. 34 | let mut opt = option::some(b"Alice"); 35 | 36 | // `option::none` creates an `Option` without a value. We need to specify the 37 | // type since it can't be inferred from context. 38 | let empty : Option = option::none(); 39 | 40 | // `option.is_some()` returns true if option contains a value. 41 | assert_eq!(opt.is_some(), true); 42 | assert_eq!(empty.is_none(), true); 43 | 44 | // internal value can be `borrow`ed and `borrow_mut`ed. 45 | assert_ref_eq!(opt.borrow(), &b"Alice"); 46 | 47 | // `option.extract` takes the value out of the option, leaving the option empty. 48 | let inner = opt.extract(); 49 | 50 | // `option.is_none()` returns true if option is None. 51 | assert_eq!(opt.is_none(), true); 52 | // ANCHOR_END: usage 53 | } 54 | -------------------------------------------------------------------------------- /site/src/theme/DocSidebar/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import React, { useEffect, useState, type ReactNode } from 'react'; 5 | import DocSidebar from '@theme-original/DocSidebar'; 6 | import type DocSidebarType from '@theme/DocSidebar'; 7 | import type { WrapperProps } from '@docusaurus/types'; 8 | import { useLocation } from '@docusaurus/router'; 9 | 10 | type Props = WrapperProps; 11 | 12 | /** 13 | * Adds a smooth scroll to the active sidebar link. 14 | * Includes on-page links, not just initial loading. 15 | * @param props 16 | * @returns 17 | */ 18 | export default function DocSidebarWrapper(props: Props): ReactNode { 19 | const location = useLocation(); 20 | const [isFirstRender, setIsFirstRender] = useState(true); 21 | 22 | // swizzled part; 23 | useEffect(() => { 24 | const active = document.querySelector('.menu__link--active'); 25 | const container = document.querySelector('.menu'); 26 | 27 | if (!active || !container) return; 28 | 29 | const containerRect = container.getBoundingClientRect(); 30 | const activeRect = active.getBoundingClientRect(); 31 | 32 | const isOutOfView = 33 | activeRect.top < containerRect.top || activeRect.bottom > containerRect.bottom; 34 | 35 | if (isOutOfView) { 36 | container.scrollTo({ 37 | top: activeRect.top - containerRect.top, 38 | behavior: isFirstRender ? 'instant' : 'smooth', 39 | }); 40 | } 41 | 42 | setIsFirstRender(false); 43 | }, [location.pathname]); 44 | 45 | return ( 46 | <> 47 | 48 | 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /packages/todo_list/Move.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "todo_list" 3 | edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move 4 | # license = "" # e.g., "MIT", "GPL", "Apache 2.0" 5 | # authors = ["..."] # e.g., ["Joe Smith (joesmith@noemail.com)", "John Snow (johnsnow@noemail.com)"] 6 | 7 | [dependencies] 8 | # Note: for a CLI older than 1.45, you will need to include the following line: 9 | # Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/mainnet" } 10 | 11 | # For remote import, use the `{ git = "...", subdir = "...", rev = "..." }`. 12 | # Revision can be a branch, a tag, and a commit hash. 13 | # MyRemotePackage = { git = "https://some.remote/host.git", subdir = "remote/path", rev = "main" } 14 | 15 | # For local dependencies use `local = path`. Path is relative to the package root 16 | # Local = { local = "../path/to" } 17 | 18 | # To resolve a version conflict and force a specific version for dependency 19 | # override use `override = true` 20 | # Override = { local = "../conflicting/version", override = true } 21 | 22 | [addresses] 23 | todo_list = "0x0" 24 | 25 | # Named addresses will be accessible in Move as `@name`. They're also exported: 26 | # for example, `std = "0x1"` is exported by the Standard Library. 27 | # alice = "0xA11CE" 28 | 29 | [dev-dependencies] 30 | # The dev-dependencies section allows overriding dependencies for `--test` and 31 | # `--dev` modes. You can introduce test-only dependencies here. 32 | # Local = { local = "../path/to/dev-build" } 33 | 34 | [dev-addresses] 35 | # The dev-addresses section allows overwriting named addresses for the `--test` 36 | # and `--dev` modes. 37 | # alice = "0xB0B" 38 | -------------------------------------------------------------------------------- /packages/hello_world/Move.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello_world" 3 | edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move 4 | # license = "" # e.g., "MIT", "GPL", "Apache 2.0" 5 | # authors = ["..."] # e.g., ["Joe Smith (joesmith@noemail.com)", "John Snow (johnsnow@noemail.com)"] 6 | 7 | [dependencies] 8 | # Note: for a CLI older than 1.45, you will need to include the following line: 9 | # Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/mainnet" } 10 | 11 | # For remote import, use the `{ git = "...", subdir = "...", rev = "..." }`. 12 | # Revision can be a branch, a tag, and a commit hash. 13 | # MyRemotePackage = { git = "https://some.remote/host.git", subdir = "remote/path", rev = "main" } 14 | 15 | # For local dependencies use `local = path`. Path is relative to the package root 16 | # Local = { local = "../path/to" } 17 | 18 | # To resolve a version conflict and force a specific version for dependency 19 | # override use `override = true` 20 | # Override = { local = "../conflicting/version", override = true } 21 | 22 | [addresses] 23 | hello_world = "0x0" 24 | 25 | # Named addresses will be accessible in Move as `@name`. They're also exported: 26 | # for example, `std = "0x1"` is exported by the Standard Library. 27 | # alice = "0xA11CE" 28 | 29 | [dev-dependencies] 30 | # The dev-dependencies section allows overriding dependencies for `--test` and 31 | # `--dev` modes. You can introduce test-only dependencies here. 32 | # Local = { local = "../path/to/dev-build" } 33 | 34 | [dev-addresses] 35 | # The dev-addresses section allows overwriting named addresses for the `--test` 36 | # and `--dev` modes. 37 | # alice = "0xB0B" 38 | -------------------------------------------------------------------------------- /packages/samples/Move.lock: -------------------------------------------------------------------------------- 1 | # @generated by Move, please check-in and do not edit manually. 2 | 3 | [move] 4 | version = 3 5 | manifest_digest = "7E7244E3835EC51DBCDAF4C78A898616BDB39BB8C21B89BDD93841CDEC4E14DD" 6 | deps_digest = "F9B494B64F0615AED0E98FC12A85B85ECD2BC5185C22D30E7F67786BB52E507C" 7 | dependencies = [ 8 | { id = "Bridge", name = "Bridge" }, 9 | { id = "MoveStdlib", name = "MoveStdlib" }, 10 | { id = "Sui", name = "Sui" }, 11 | { id = "SuiSystem", name = "SuiSystem" }, 12 | ] 13 | 14 | [[move.package]] 15 | id = "Bridge" 16 | source = { git = "https://github.com/MystenLabs/sui.git", rev = "c1f1ae650fb9f9248b39a569400b4420820868db", subdir = "crates/sui-framework/packages/bridge" } 17 | 18 | dependencies = [ 19 | { id = "MoveStdlib", name = "MoveStdlib" }, 20 | { id = "Sui", name = "Sui" }, 21 | { id = "SuiSystem", name = "SuiSystem" }, 22 | ] 23 | 24 | [[move.package]] 25 | id = "MoveStdlib" 26 | source = { git = "https://github.com/MystenLabs/sui.git", rev = "c1f1ae650fb9f9248b39a569400b4420820868db", subdir = "crates/sui-framework/packages/move-stdlib" } 27 | 28 | [[move.package]] 29 | id = "Sui" 30 | source = { git = "https://github.com/MystenLabs/sui.git", rev = "c1f1ae650fb9f9248b39a569400b4420820868db", subdir = "crates/sui-framework/packages/sui-framework" } 31 | 32 | dependencies = [ 33 | { id = "MoveStdlib", name = "MoveStdlib" }, 34 | ] 35 | 36 | [[move.package]] 37 | id = "SuiSystem" 38 | source = { git = "https://github.com/MystenLabs/sui.git", rev = "c1f1ae650fb9f9248b39a569400b4420820868db", subdir = "crates/sui-framework/packages/sui-system" } 39 | 40 | dependencies = [ 41 | { id = "MoveStdlib", name = "MoveStdlib" }, 42 | { id = "Sui", name = "Sui" }, 43 | ] 44 | 45 | [move.toolchain-version] 46 | compiler-version = "1.61.2" 47 | edition = "2024.beta" 48 | flavor = "sui" 49 | -------------------------------------------------------------------------------- /book/programmability/randomness.md: -------------------------------------------------------------------------------- 1 | # Randomness 2 | 3 | 52 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/publisher.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #[allow(unused_variable)] 5 | // ANCHOR: publisher 6 | module book::publisher; 7 | 8 | use sui::package::{Self, Publisher}; 9 | 10 | /// Some type defined in the module. 11 | public struct Book {} 12 | 13 | /// The OTW for the module. 14 | public struct PUBLISHER has drop {} 15 | 16 | /// Uses the One Time Witness to claim the Publisher object. 17 | fun init(otw: PUBLISHER, ctx: &mut TxContext) { 18 | // Claim the Publisher object. 19 | let publisher: Publisher = sui::package::claim(otw, ctx); 20 | 21 | // Usually it is transferred to the sender. 22 | // It can also be stored in another object. 23 | transfer::public_transfer(publisher, ctx.sender()) 24 | } 25 | // ANCHOR_END: publisher 26 | 27 | public struct USE_PUBLISHER has drop {} 28 | 29 | const ENotAuthorized: u64 = 1; 30 | 31 | 32 | #[test] 33 | fun test_publisher() { 34 | let ctx = &mut tx_context::dummy(); 35 | let publisher = package::test_claim(USE_PUBLISHER {}, ctx); 36 | // ANCHOR: use_publisher 37 | // Checks if the type is from the same module, hence the `Publisher` has the 38 | // authority over it. 39 | assert!(publisher.from_module()); 40 | 41 | // Checks if the type is from the same package, hence the `Publisher` has the 42 | // authority over it. 43 | assert!(publisher.from_package()); 44 | // ANCHOR_END: use_publisher 45 | std::unit_test::destroy(publisher); 46 | } 47 | 48 | // ANCHOR: publisher_as_admin 49 | /// Some action in the application gated by the Publisher object. 50 | public fun admin_action(cap: &Publisher, /* app objects... */ param: u64) { 51 | assert!(cap.from_module(), ENotAuthorized); 52 | 53 | // perform application-specific action 54 | } 55 | // ANCHOR_END: publisher_as_admin 56 | -------------------------------------------------------------------------------- /book/appendix/transfer-functions.md: -------------------------------------------------------------------------------- 1 | # Appendix C: Transfer Functions 2 | 3 | ## Transfer Functions Comparison 4 | 5 | | Function | Public Function | End State | Permissions | 6 | | ------------------------- | ----------------------- | ------------- | ------------------------- | 7 | | [`transfer`][transfer] | `public_transfer` | Address Owned | Full | 8 | | [`share_object`][share] | `public_share_object` | Shared | Ref, Mut Ref, Delete | 9 | | [`freeze_object`][freeze] | `public_freeze_object` | Frozen | Ref | 10 | | [`party_transfer`][party] | `public_party_transfer` | Party | [See Party table](#party) | 11 | 12 | ## States Comparison 13 | 14 | | State | Description | 15 | | ------------- | --------------------------------------------------------- | 16 | | Address Owned | Object can be accessed fully by an address (or an object) | 17 | | Shared | Object can be referenced and deleted by anyone | 18 | | Frozen | Object can be accessed via immutable reference | 19 | | Party | Depends on the Party settings ([see Party table](#party)) | 20 | 21 | ## Party 22 | 23 | | Function | Description | 24 | | -------------- | -------------------------------------------- | 25 | | `single_owner` | Object has same permissions as Address Owned | 26 | 27 | [transfer]: https://docs.sui.io/references/framework/sui_sui/transfer#sui_transfer_transfer 28 | [share]: https://docs.sui.io/references/framework/sui_sui/transfer#sui_transfer_share_object 29 | [freeze]: https://docs.sui.io/references/framework/sui_sui/transfer#sui_transfer_freeze_object 30 | [party]: https://docs.sui.io/references/framework/sui_sui/transfer#sui_transfer_party_transfer 31 | -------------------------------------------------------------------------------- /packages/samples/sources/move-basics/assert-and-abort.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | module book::assert_abort; 5 | 6 | #[test, expected_failure(abort_code = 1, location=Self)] 7 | fun test_abort() { 8 | 9 | // ANCHOR: abort 10 | let user_has_access = false; 11 | 12 | // abort with a predefined constant if `user_has_access` is false 13 | if (!user_has_access) { 14 | abort 1 15 | }; 16 | // ANCHOR_END: abort 17 | } 18 | 19 | #[test] 20 | fun show_assert() { 21 | let user_has_access = true; 22 | // ANCHOR: assert 23 | // aborts if `user_has_access` is `false` with abort code 0 24 | assert!(user_has_access, 0); 25 | 26 | // expands to: 27 | if (!user_has_access) { 28 | abort 0 29 | }; 30 | // ANCHOR_END: assert 31 | } 32 | 33 | // ANCHOR: error_const 34 | /// Error code for when the user has no access. 35 | const ENoAccess: u64 = 0; 36 | /// Trying to access a field that does not exist. 37 | const ENoField: u64 = 1; 38 | 39 | /// Updates a record. 40 | public fun update_record(/* ... , */ user_has_access: bool, field_exists: bool) { 41 | // asserts are way more readable now 42 | assert!(user_has_access, ENoAccess); 43 | assert!(field_exists, ENoField); 44 | 45 | /* ... */ 46 | } 47 | // ANCHOR_END: error_const 48 | 49 | public struct User { is_authorized: bool, value: u64 } 50 | 51 | // ANCHOR: error_attribute 52 | #[error] 53 | const ENotAuthorized: vector = b"The user is not authorized to perform this action"; 54 | 55 | #[error] 56 | const EValueTooLow: vector = b"The value is too low, it should be at least 10"; 57 | 58 | /// Performs an action on behalf of the user. 59 | public fun update_value(user: &mut User, value: u64) { 60 | assert!(user.is_authorized, ENotAuthorized); 61 | assert!(value >= 10, EValueTooLow); 62 | 63 | user.value = value; 64 | } 65 | // ANCHOR_END: error_attribute 66 | } 67 | -------------------------------------------------------------------------------- /reference/abilities/object.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Sui Object | Reference' 3 | --- 4 | 5 | # Sui Objects 6 | 7 | For Sui, `key` is used to signify an _object_. Objects the only way to store data in Sui--allowing 8 | the data to persist between transactions. 9 | 10 | For more details, see the Sui documentation on 11 | 12 | - [The Object Model](https://docs.sui.io/concepts/object-model) 13 | - [Move Rules for Objects](https://docs.sui.io/concepts/sui-move-concepts#global-unique) 14 | - [Transferring Objects](https://docs.sui.io/concepts/transfers) 15 | 16 | ## Object Rules 17 | 18 | An object is a [`struct`](../structs.md) with the [`key`](../abilities.md#key) ability. The first 19 | field of the struct must be `id: sui::object::UID`. This 32-byte field (a strongly typed wrapper 20 | around an [`address`](../primitive-types/address.md)) is then used to uniquely identify the object. 21 | 22 | Note that since `sui::object::UID` has only the `store` ability (it does not have `copy` or `drop`), 23 | no object has `copy` or `drop`. 24 | 25 | ## Transfer Rules 26 | 27 | Objects can be have their ownership changed and transferred in the `sui::transfer` module. Many 28 | functions in the module have "public" and "private" variant, where the "private" variant can only be 29 | called inside of the module that defines the object's type. The "public" variants can be called only 30 | if the object has `store`. 31 | 32 | For example if we had two objects `A` and `B` defined in the module `my_module`: 33 | 34 | ```move 35 | module a::my_module; 36 | 37 | public struct A has key { 38 | id: sui::object::UID, 39 | } 40 | 41 | public struct B has key, store { 42 | id: sui::object::UID, 43 | } 44 | ``` 45 | 46 | `A` can only be transferred using the `sui::transfer::transfer` inside of `a::my_module`, while `B` 47 | can be transferred anywhere using `sui::transfer::public_transfer`. These rules are enforced by a 48 | custom type system (bytecode verifier) rule in Sui. 49 | -------------------------------------------------------------------------------- /site/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids", 15 | "typecheck": "tsc" 16 | }, 17 | "dependencies": { 18 | "@docusaurus/core": "3.8.1", 19 | "@docusaurus/plugin-client-redirects": "^3.8.1", 20 | "@docusaurus/plugin-google-gtag": "^3.8.1", 21 | "@docusaurus/preset-classic": "3.8.1", 22 | "@docusaurus/theme-classic": "^3.8.1", 23 | "@docusaurus/theme-common": "^3.8.1", 24 | "@easyops-cn/docusaurus-search-local": "^0.51.0", 25 | "@mdx-js/react": "^3.0.0", 26 | "clsx": "^2.0.0", 27 | "copy-text-to-clipboard": "^3.2.0", 28 | "html2canvas": "^1.4.1", 29 | "prism-react-renderer": "^2.3.0", 30 | "prismjs": "^1.30.0", 31 | "react": "^19.2.1", 32 | "react-dom": "^19.2.1", 33 | "remark-code-import": "^1.2.0", 34 | "yaml": "^2.8.0" 35 | }, 36 | "devDependencies": { 37 | "@docusaurus/module-type-aliases": "3.8.1", 38 | "@docusaurus/tsconfig": "3.8.1", 39 | "@docusaurus/types": "3.8.1", 40 | "typescript": "~5.6.2" 41 | }, 42 | "browserslist": { 43 | "production": [ 44 | ">0.5%", 45 | "not dead", 46 | "not op_mini all" 47 | ], 48 | "development": [ 49 | "last 3 chrome version", 50 | "last 3 firefox version", 51 | "last 5 safari version" 52 | ] 53 | }, 54 | "engines": { 55 | "node": ">=18.0" 56 | }, 57 | "packageManager": "pnpm@9.15.2+sha512.93e57b0126f0df74ce6bff29680394c0ba54ec47246b9cf321f0121d8d9bb03f750a705f24edc3c1180853afd7c2c3b94196d0a3d53d3e069d9e2793ef11f321" 58 | } 59 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/dynamic-object-fields.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #[allow(unused_variable, unused_use)] 5 | // ANCHOR: usage 6 | module book::dynamic_object_field; 7 | 8 | use std::string::String; 9 | 10 | // there are two common aliases for the long module name: `dof` and 11 | // `ofield`. Both are commonly used and met in different projects. 12 | use sui::dynamic_object_field as dof; 13 | use sui::dynamic_field as df; 14 | 15 | /// The `Character` that we will use for the example 16 | public struct Character has key { id: UID } 17 | 18 | /// Metadata that doesn't have the `key` ability 19 | public struct Metadata has store, drop { name: String } 20 | 21 | /// Accessory that has the `key` and `store` abilities. 22 | public struct Accessory has key, store { id: UID } 23 | 24 | #[test] 25 | fun equip_accessory() { 26 | let ctx = &mut tx_context::dummy(); 27 | let mut character = Character { id: object::new(ctx) }; 28 | 29 | // Create an accessory and attach it to the character 30 | let hat = Accessory { id: object::new(ctx) }; 31 | 32 | // Add the hat to the character. Just like with `dynamic_fields` 33 | dof::add(&mut character.id, b"hat_key", hat); 34 | 35 | // However for non-key structs we can only use `dynamic_field` 36 | df::add(&mut character.id, b"metadata_key", Metadata { 37 | name: b"John".to_string() 38 | }); 39 | 40 | // Borrow the hat from the character 41 | let hat_id = dof::id(&character.id, b"hat_key").extract(); // Option 42 | let hat_ref: &Accessory = dof::borrow(&character.id, b"hat_key"); 43 | let hat_mut: &mut Accessory = dof::borrow_mut(&mut character.id, b"hat_key"); 44 | let hat: Accessory = dof::remove(&mut character.id, b"hat_key"); 45 | 46 | // Clean up, Metadata is an orphan now. 47 | std::unit_test::destroy(hat); 48 | std::unit_test::destroy(character); 49 | } 50 | // ANCHOR_END: usage 51 | -------------------------------------------------------------------------------- /packages/samples/sources/storage/transfer-to-object.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // ANCHOR: main 5 | module book::receiving; 6 | 7 | use sui::derived_object; 8 | use sui::transfer::Receiving; // not imported by default! 9 | 10 | /// Base derivation object to create derived `PostBox`-es. 11 | public struct PostOffice has key { id: UID } 12 | 13 | /// Object with derived UID which receives objects sent to an address. 14 | public struct PostBox has key { id: UID, owner: address } 15 | 16 | /// Transfer functionality. Anyone can come to the PostOffice and send to a specific 17 | /// recipient's PostBox. Items can be received from the `PostBox` by the recipient. 18 | public fun send(office: &PostOffice, parcel: T, recipient: address) { 19 | let postbox = derived_object::derive_address(office.id.to_inner(), recipient); 20 | transfer::public_transfer(parcel, postbox) 21 | } 22 | 23 | /// Receive the parcel. Requires the sender to be the owner of the `PostBox`! 24 | public fun receive( 25 | box: &mut PostBox, 26 | to_receive: Receiving, 27 | ctx: &TxContext 28 | ): T { 29 | assert!(box.owner == ctx.sender()); 30 | 31 | // Receive `to_receive` from `PostBox`. 32 | let parcel = transfer::public_receive(&mut box.id, to_receive); 33 | parcel 34 | } 35 | 36 | /// If user hasn't claimed their `PostBox` yet, create it. 37 | /// Note: this is not a requirement for transferring assets! 38 | /// Parcels can be sent even to unregistered post boxes, see `send` implementation. 39 | public fun register_address(office: &mut PostOffice, ctx: &mut TxContext) { 40 | transfer::share_object(PostBox { 41 | id: derived_object::claim(&mut office.id, ctx.sender()), 42 | owner: ctx.sender() 43 | }) 44 | } 45 | 46 | // Create a PostOffice on module publish. 47 | fun init(ctx: &mut TxContext) { 48 | transfer::share_object(PostOffice { id: object::new(ctx) }); 49 | } 50 | // ANCHOR_END: main 51 | -------------------------------------------------------------------------------- /packages/samples/sources/move-basics/struct.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #[allow(unused_variable, unused_field)] 5 | module book::struct_syntax; 6 | 7 | use std::string::String; 8 | 9 | // ANCHOR: def 10 | /// A struct representing an artist. 11 | public struct Artist { 12 | /// The name of the artist. 13 | name: String, 14 | } 15 | 16 | /// A struct representing a music record. 17 | public struct Record { 18 | /// The title of the record. 19 | title: String, 20 | /// The artist of the record. Uses the `Artist` type. 21 | artist: Artist, 22 | /// The year the record was released. 23 | year: u16, 24 | /// Whether the record is a debut album. 25 | is_debut: bool, 26 | /// The edition of the record. 27 | edition: Option, 28 | } 29 | // ANCHOR_END: def 30 | 31 | #[test_only] 32 | use std::unit_test::assert_eq; 33 | 34 | #[test] fun test_pack_unpack() { 35 | 36 | // ANCHOR: pack 37 | let mut artist = Artist { 38 | name: b"The Beatles".to_string() 39 | }; 40 | // ANCHOR_END: pack 41 | 42 | // ANCHOR: access 43 | // Access the `name` field of the `Artist` struct. 44 | let artist_name = artist.name; 45 | 46 | // Access a field of the `Artist` struct. 47 | assert_eq!(artist.name, b"The Beatles".to_string()); 48 | 49 | // Mutate the `name` field of the `Artist` struct. 50 | artist.name = b"Led Zeppelin".to_string(); 51 | 52 | // Check that the `name` field has been mutated. 53 | assert_eq!(artist.name, b"Led Zeppelin".to_string()); 54 | // ANCHOR_END: access 55 | 56 | // ANCHOR: unpack 57 | // Unpack the `Artist` struct and create a new variable `name` 58 | // with the value of the `name` field. 59 | let Artist { name } = artist; 60 | // ANCHOR_END: unpack 61 | 62 | let artist = Artist { 63 | name: b"The Beatles".to_string() 64 | }; 65 | 66 | // ANCHOR: unpack_ignore 67 | // Unpack the `Artist` struct and ignore the `name` field. 68 | let Artist { name: _ } = artist; 69 | // ANCHOR_END: unpack_ignore 70 | } 71 | -------------------------------------------------------------------------------- /site/src/plugins/mdbook-anchor-code.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import fs from 'fs'; 5 | import path from 'path'; 6 | import { visit } from 'unist-util-visit'; 7 | import type { Plugin } from 'unified'; 8 | import type { Root } from 'mdast'; 9 | 10 | interface Options { 11 | rootDir?: string; 12 | } 13 | 14 | const plugin: Plugin<[Options?], Root> = ({ rootDir = process.cwd() } = {}) => { 15 | return (tree, file) => { 16 | visit(tree, 'code', (node) => { 17 | if (!node.meta) return; 18 | 19 | const match = node.meta.match(/file=(\S+)/); 20 | if (!match) return; 21 | 22 | const anchorMatch = node.meta.match(/anchor=(\S+)/); 23 | if (!anchorMatch) return; 24 | 25 | let [filePathWithAnchor] = match.slice(1); 26 | let [anchor] = anchorMatch.slice(1); 27 | 28 | const absPath = path.resolve(rootDir, filePathWithAnchor); 29 | if (!fs.existsSync(absPath)) { 30 | throw new Error(`File not found: ${absPath}`); 31 | } 32 | 33 | let content = fs.readFileSync(absPath, 'utf-8'); 34 | 35 | if (anchor) { 36 | const startMarker = new RegExp(`//\\s*ANCHOR:\\s*${anchor}`); 37 | const endMarker = new RegExp(`//\\s*ANCHOR_END:\\s*${anchor}`); 38 | 39 | const lines = content.split('\n'); 40 | const start = lines.findIndex((line) => startMarker.test(line)); 41 | if (start === -1) { 42 | throw new Error(`Anchor "${anchor}" not found in ${absPath}`); 43 | } 44 | 45 | const end = lines.findIndex((line, i) => i > start && endMarker.test(line)); 46 | if (end === -1) { 47 | throw new Error(`No end anchor for "${anchor}" in ${absPath}`); 48 | } 49 | 50 | content = lines 51 | .slice(start + 1, end) 52 | .filter((e) => !e.includes('// ANCHOR_END') && !e.includes('// ANCHOR')) 53 | .join('\n'); 54 | } 55 | 56 | node.value = node.value + content; 57 | }); 58 | }; 59 | }; 60 | 61 | export default plugin; 62 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/epoch-and-time.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #[allow(unused_variable)] 5 | module book::epoch_and_time { 6 | 7 | // ANCHOR: epoch 8 | public fun current_epoch(ctx: &TxContext) { 9 | let epoch = ctx.epoch(); 10 | // ... 11 | } 12 | // ANCHOR_END: epoch 13 | 14 | // ANCHOR: epoch_start 15 | public fun current_epoch_start(ctx: &TxContext) { 16 | let epoch_start = ctx.epoch_timestamp_ms(); 17 | // ... 18 | } 19 | // ANCHOR_END: epoch_start 20 | 21 | // ANCHOR: clock 22 | use sui::clock::Clock; 23 | 24 | /// Clock needs to be passed as an immutable reference. 25 | public fun current_time(clock: &Clock) { 26 | let time = clock.timestamp_ms(); 27 | // ... 28 | } 29 | // ANCHOR_END: clock 30 | 31 | // ANCHOR: test 32 | #[test_only] 33 | use sui::clock; 34 | #[test_only] 35 | use std::unit_test::assert_eq; 36 | 37 | #[test] 38 | fun use_clock_in_test() { 39 | // Get `ctx` and create `Clock` for testing 40 | let ctx = &mut tx_context::dummy(); 41 | let mut clock = clock::create_for_testing(ctx); 42 | assert_eq!(clock.timestamp_ms(), 0); 43 | 44 | // Add a value to the timestamp stored in `Clock` 45 | clock.increment_for_testing(2_000_000_000); 46 | assert_eq!(clock.timestamp_ms(), 2_000_000_000); 47 | 48 | // Set the timestamp, but the time set must be no less than the value stored in `Clock` 49 | clock.set_for_testing(3_000_000_000); 50 | assert_eq!(clock.timestamp_ms(), 3_000_000_000); 51 | 52 | // The following setting will fail because the time set must be at least the timestamp stored in `Clock` 53 | // clock.set_for_testing(1_000_000_000); 54 | // assert_eq!(clock.timestamp_ms(), 1_000_000_000); 55 | 56 | // If need a shared `Clock` for testing, you can set it through this function 57 | // clock.share_for_testing(); 58 | 59 | // `Clock` does not have a `drop` capability, so it needs to be destroyed manually at the end of the test 60 | clock.destroy_for_testing(); 61 | } 62 | // ANCHOR_END: test 63 | 64 | } 65 | -------------------------------------------------------------------------------- /book/programmability/events.md: -------------------------------------------------------------------------------- 1 | # Events 2 | 3 | Events are a way to notify off-chain listeners about on-chain events. They are used to emit 4 | additional information about the transaction that is not stored - and, hence, can't be accessed - 5 | on-chain. Events are emitted by the `sui::event` module located in the 6 | [Sui Framework](./sui-framework). 7 | 8 | > Any custom type with the [copy](./../move-basics/copy-ability) and 9 | > [drop](./../move-basics/drop-ability) abilities can be emitted as an event. Sui Verifier requires 10 | > the type to be internal to the module. 11 | 12 | ```move 13 | module sui::event; 14 | 15 | /// Emit a custom Move event, sending the data off-chain. 16 | /// 17 | /// Used for creating custom indexes and tracking on-chain 18 | /// activity in a way that suits a specific application the most. 19 | /// 20 | /// The type `T` is the main way to index the event, and can contain 21 | /// phantom parameters, eg `emit(MyEvent)`. 22 | public native fun emit(event: T); 23 | ``` 24 | 25 | ## Emitting Events 26 | 27 | Events are emitted using the `emit` function in the `sui::event` module. The function takes a single 28 | argument - the event to be emitted. The event data is passed by value, 29 | 30 | ```move file=packages/samples/sources/programmability/events.move anchor=emit 31 | 32 | ``` 33 | 34 | The Sui Verifier requires the type passed to the `emit` function to be _internal to the module_. So 35 | emitting a type from another module will result in a compilation error. Primitive types, although 36 | they match the _copy_ and _drop_ requirement, are not allowed to be emitted as events. 37 | 38 | ## Event Structure 39 | 40 | Events are a part of the transaction result and are stored in the _transaction effects_. As such, 41 | they natively have the `sender` field which is the address which sent the transaction. So adding a 42 | "sender" field to the event is not necessary. Similarly, event metadata contains the timestamp. But 43 | it is important to note that the timestamp is relative to the node and may vary a little from node 44 | to node. 45 | 46 | 47 | -------------------------------------------------------------------------------- /book/move-basics/address.md: -------------------------------------------------------------------------------- 1 | # Address Type 2 | 3 | 20 | 21 | Move uses a special type called [address](./../concepts/address) to represent addresses. It is a 22 | 32-byte value that can represent any address on the blockchain. Addresses can be written in two 23 | forms: hexadecimal addresses prefixed with 0x and named addresses. 24 | 25 | ```move file=packages/samples/sources/move-basics/address.move anchor=address_literal 26 | 27 | ``` 28 | 29 | An address literal starts with the `@` symbol followed by a hexadecimal number or an identifier. The 30 | hexadecimal number is interpreted as a 32 byte value. The identifier is looked up in the 31 | [Move.toml](./../concepts/manifest) file and replaced with the corresponding address by the 32 | compiler. If the identifier is not found in the Move.toml file, the compiler will throw an error. 33 | 34 | ## Conversion 35 | 36 | Sui Framework offers a set of helper functions to work with addresses. Given that the address type 37 | is a 32 byte value, it can be converted to a `u256` type and vice versa. It can also be converted to 38 | and from a `vector` type. 39 | 40 | Example: Convert an address to a `u256` type and back. 41 | 42 | ```move file=packages/samples/sources/move-basics/address.move anchor=to_u256 43 | 44 | ``` 45 | 46 | Example: Convert an address to a `vector` type and back. 47 | 48 | ```move file=packages/samples/sources/move-basics/address.move anchor=to_bytes 49 | 50 | ``` 51 | 52 | Example: Convert an address into a string. 53 | 54 | ```move file=packages/samples/sources/move-basics/address.move anchor=to_string 55 | 56 | ``` 57 | 58 | ## Further Reading 59 | 60 | - [Address](./../../reference/primitive-types/address) in the Move Reference. 61 | - [sui::address](https://docs.sui.io/references/framework/sui/address) module documentation. 62 | -------------------------------------------------------------------------------- /book/before-we-begin/install-sui.md: -------------------------------------------------------------------------------- 1 | # Install Sui 2 | 3 | Move is a compiled language, so you need to install a compiler to be able to write and run Move 4 | programs. The compiler is included into the Sui binary, which can be installed or downloaded using 5 | one of the methods below. 6 | 7 | ## Installing via suiup 8 | 9 | The best way to install Sui is by using [`suiup`](https://github.com/MystenLabs/suiup). It provides a simple way to install binaries and to manage different versions of binaries for 10 | different environments (e.g. `testnet` and `mainnet`). 11 | 12 | Installation instructions for `suiup` can be found 13 | [in the repository README](https://github.com/MystenLabs/suiup). 14 | 15 | To install Sui, run the following command: 16 | 17 | ```bash 18 | suiup install sui 19 | ``` 20 | 21 | ## Download Binary 22 | 23 | You can download the latest Sui binary from the 24 | [releases page](https://github.com/MystenLabs/sui/releases). The binary is available for macOS, 25 | Linux and Windows. For education purposes and development, we recommend using the `mainnet` version. 26 | 27 | ## Install Using Homebrew (MacOS) 28 | 29 | You can install Sui using the [Homebrew](https://brew.sh/) package manager. 30 | 31 | ```bash 32 | brew install sui 33 | ``` 34 | 35 | ## Install Using Chocolatey (Windows) 36 | 37 | You can install Sui using the [Chocolatey](https://chocolatey.org/install) package manager for 38 | Windows. 39 | 40 | ```bash 41 | choco install sui 42 | ``` 43 | 44 | ## Build Using Cargo (MacOS, Linux) 45 | 46 | You can install and build Sui locally by using the Cargo package manager (requires Rust) 47 | 48 | ```bash 49 | cargo install --git https://github.com/MystenLabs/sui.git sui --branch mainnet 50 | ``` 51 | 52 | Change the branch target here to `testnet` or `devnet` if you are targeting one of those. 53 | 54 | Make sure that your system has the latest Rust versions with the command below. 55 | 56 | ```bash 57 | rustup update stable 58 | ``` 59 | 60 | ## Troubleshooting 61 | 62 | For troubleshooting the installation process, please refer to the 63 | [Install Sui](https://docs.sui.io/guides/developer/getting-started/sui-install) Guide. 64 | -------------------------------------------------------------------------------- /reference/control-flow/conditionals.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Conditional Expressions | Reference' 3 | description: '' 4 | --- 5 | 6 | # Conditional `if` Expressions 7 | 8 | An `if` expression specifies that some code should only be evaluated if a certain condition is true. 9 | For example: 10 | 11 | ```move 12 | if (x > 5) x = x - 5 13 | ``` 14 | 15 | The condition must be an expression of type `bool`. 16 | 17 | An `if` expression can optionally include an `else` clause to specify another expression to evaluate 18 | when the condition is false. 19 | 20 | ```move 21 | if (y <= 10) y = y + 1 else y = 10 22 | ``` 23 | 24 | Either the "true" branch or the "false" branch will be evaluated, but not both. Either branch can be 25 | a single expression or an expression block. 26 | 27 | The conditional expressions may produce values so that the `if` expression has a result. 28 | 29 | ```move 30 | let z = if (x < 100) x else 100; 31 | ``` 32 | 33 | If the `else` clause is not specified, the false branch defaults to the unit value. The following 34 | are equivalent: 35 | 36 | ```move 37 | if (condition) true_branch // implied default: else () 38 | if (condition) true_branch else () 39 | ``` 40 | 41 | The expressions in the true and false branches must have compatible types. For example: 42 | 43 | ```move 44 | // x and y must be u64 integers 45 | let maximum: u64 = if (x > y) x else y; 46 | 47 | // highlight-error-start 48 | // ERROR! branches different types 49 | let z = if (maximum < 10) 10u8 else 100u64; 50 | 51 | // ERROR! branches different types, as default false-branch is () not u64 52 | let y = if (maximum >= 10) maximum; 53 | // highlight-error-end 54 | ``` 55 | 56 | Commonly, `if` expressions are used in conjunction with 57 | [expression blocks](./../variables#expression-blocks). 58 | 59 | ```move 60 | let maximum = if (x > y) x else y; 61 | if (maximum < 10) { 62 | x = x + 10; 63 | y = y + 10; 64 | } else if (x >= 10 && y >= 10) { 65 | x = x - 10; 66 | y = y - 10; 67 | } 68 | ``` 69 | 70 | ## Grammar for Conditionals 71 | 72 | > _if-expression_ → **if (** _expression_ **)** _expression_ _else-clause__opt_ > 73 | > _else-clause_ → **else** _expression_ 74 | -------------------------------------------------------------------------------- /packages/samples/sources/move-basics/string.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #[allow(unused_variable)] 5 | // ANCHOR: custom 6 | module book::custom_string; 7 | 8 | /// Anyone can implement a custom string-like type by wrapping a vector. 9 | public struct MyString { 10 | bytes: vector, 11 | } 12 | 13 | /// Implement a `from_bytes` function to convert a vector of bytes to a string. 14 | public fun from_bytes(bytes: vector): MyString { 15 | MyString { bytes } 16 | } 17 | 18 | /// Implement a `bytes` function to convert a string to a vector of bytes. 19 | public fun bytes(self: &MyString): &vector { 20 | &self.bytes 21 | } 22 | // ANCHOR_END: custom 23 | 24 | // use std::ascii::String; 25 | 26 | #[allow(unused_variable)] 27 | #[test] 28 | fun using_strings() { 29 | // ANCHOR: ascii 30 | // the module is `std::ascii` and the type is `String` 31 | use std::ascii::{Self, String}; 32 | 33 | // strings can be created using the `string` function 34 | // type declaration is not necessary, we put it here for clarity 35 | let hey: String = ascii::string(b"Hey"); 36 | 37 | // there is a handy alias `.to_ascii_string()` on the `vector` type 38 | let hey = b"Hey".to_ascii_string(); 39 | 40 | // ANCHOR_END: ascii 41 | } 42 | 43 | #[test] fun using_strings_utf8() { 44 | // ANCHOR: utf8 45 | // the module is `std::string` and the type is `String` 46 | use std::string::{Self, String}; 47 | 48 | // strings are normally created using the `utf8` function 49 | // type declaration is not necessary, we put it here for clarity 50 | let hello: String = string::utf8(b"Hello"); 51 | 52 | // The `.to_string()` alias on the `vector` is more convenient 53 | let hello = b"Hello".to_string(); 54 | // ANCHOR_END: utf8 55 | } 56 | 57 | #[test] fun safe_strings() { 58 | // ANCHOR: safe_utf8 59 | // this is a valid UTF-8 string 60 | let hello = b"Hello".try_to_string(); 61 | 62 | assert!(hello.is_some()); // abort if the value is not valid UTF-8 63 | 64 | // this is not a valid UTF-8 string 65 | let invalid = b"\xFF".try_to_string(); 66 | 67 | assert!(invalid.is_none()); // abort if the value is valid UTF-8 68 | // ANCHOR_END: safe_utf8 69 | } 70 | -------------------------------------------------------------------------------- /book/move-basics/comments.md: -------------------------------------------------------------------------------- 1 | # Comments 2 | 3 | 14 | 15 | Comments are a way to add notes or document your code. They are ignored by the compiler and don't 16 | result in Move bytecode. You can use comments to explain what your code does, add notes to yourself 17 | or other developers, temporarily remove a part of your code, or generate documentation. There are 18 | three types of comments in Move: line comments, block comments, and doc comments. 19 | 20 | ## Line Comment 21 | 22 | You can use a double slash `//` to comment out the rest of the line. Everything after `//` will be 23 | ignored by the compiler. 24 | 25 | ```move file=packages/samples/sources/move-basics/comments-line.move anchor=main 26 | 27 | ``` 28 | 29 | ## Block Comment 30 | 31 | Block comments are used to comment out a block of code. They start with `/*` and end with `*/`. 32 | Everything between `/*` and `*/` will be ignored by the compiler. You can use block comments to 33 | comment out a single line or multiple lines. You can even use them to comment out a part of a line. 34 | 35 | ```move file=packages/samples/sources/move-basics/comments-block.move anchor=main 36 | 37 | ``` 38 | 39 | This example is a bit extreme, but it shows all the ways that you can use block comments. 40 | 41 | ## Doc Comment 42 | 43 | Documentation comments are special comments that are used to generate documentation for your code. 44 | They are similar to block comments but start with three slashes `///` and are placed before the 45 | definition of the item they document. 46 | 47 | ```move file=packages/samples/sources/move-basics/comments-doc.move anchor=main 48 | 49 | ``` 50 | 51 | ## Whitespace 52 | 53 | Unlike some languages, whitespace (spaces, tabs, and newlines) have no impact on the meaning of the 54 | program. 55 | 56 | 57 | -------------------------------------------------------------------------------- /book/programmability/fast-path.md: -------------------------------------------------------------------------------- 1 | # Fast Path 2 | 3 | Due to the object model and the data organization model of Sui, some operations can be performed in 4 | a more efficient and parallelized way. This is called the **fast path**. Transaction that touches 5 | shared state requires consensus because it can be accessed by multiple parties at the same time. 6 | However, if the transaction only touches the private state (owned objects), there is no need for 7 | consensus. This is the fast path. 8 | 9 | We have a favorite example for this: a coffee machine and a coffee cup. The coffee machine placed in 10 | the office is a shared resource - everyone can use it, but there can be only one user at a time. The 11 | coffee cup, on the other hand, is a private resource - it belongs to a specific person, and only 12 | that person can use it. To make coffee, one needs to use the coffee machine and wait if there's 13 | someone else using it. However, once the coffee is made and poured into the cup, the person can take 14 | the cup and drink the coffee without waiting for anyone else. 15 | 16 | The same principle applies to Sui. If a transaction only touches the private state (the cup with 17 | coffee), it can be executed without consensus. If it touches the shared state (the coffee machine), 18 | it requires consensus. This is the fast path. 19 | 20 | ## Frozen objects 21 | 22 | Consensus is only required for mutating the shared state. If the object is immutable, it is treated 23 | as a "constant" and can be accessed in parallel. Frozen objects can be used to share unchangeable 24 | data between multiple parties without requiring consensus. 25 | 26 | ## In Practice 27 | 28 | ```move file=packages/samples/sources/programmability/fast-path.move anchor=main 29 | 30 | ``` 31 | 32 | ## Special Case: Clock 33 | 34 | The `Clock` object with the reserved address `0x6` is a special case of a shared object which cannot 35 | be passed by a mutable reference in a regular transaction. An attempt to do so will not succeed, and 36 | the transaction will be rejected. Because of this limitation, the `Clock` object can only be 37 | accessed immutably, which allows executing transactions in parallel without consensus. 38 | 39 | 40 | -------------------------------------------------------------------------------- /book/concepts/address.md: -------------------------------------------------------------------------------- 1 | # Address 2 | 3 | 27 | 28 | Address is a unique identifier of a location on the blockchain. It is used to identify 29 | [packages](./packages), [accounts](./what-is-an-account), and [objects](./../object/object-model). 30 | Address has a fixed size of 32 bytes and is usually represented as a hexadecimal string prefixed 31 | with `0x`. Addresses are case insensitive. 32 | 33 | ```move 34 | 0xe51ff5cd221a81c3d6e22b9e670ddf99004d71de4f769b0312b68c7c4872e2f1 35 | ``` 36 | 37 | The address above is an example of a valid address. It is 64 characters long (32 bytes) and prefixed 38 | with `0x`. 39 | 40 | Sui also has reserved addresses that are used to identify standard packages and objects. Reserved 41 | addresses are typically simple values that are easy to remember and type. For example, the address 42 | of the Standard Library is `0x1`. Addresses, shorter than 32 bytes, are padded with zeros to the 43 | left. 44 | 45 | ```move 46 | 0x1 = 0x0000000000000000000000000000000000000000000000000000000000000001 47 | ``` 48 | 49 | Here are some examples of reserved addresses: 50 | 51 | - `0x1` - address of the Sui Standard Library (alias `std`) 52 | - `0x2` - address of the Sui Framework (alias `sui`) 53 | - `0x6` - address of the system `Clock` object 54 | 55 | > You can find all reserved addresses in the [Appendix B](../appendix/reserved-addresses). 56 | 57 | ## Further Reading 58 | 59 | - [Address type](../move-basics/address) in Move 60 | - [sui::address module](https://docs.sui.io/references/framework/sui/address) 61 | -------------------------------------------------------------------------------- /book/move-basics/vector.md: -------------------------------------------------------------------------------- 1 | # Vector 2 | 3 | Vectors are a native way to store collections of elements in Move. They are similar to arrays in 4 | other programming languages, but with a few differences. In this section, we introduce the `vector` 5 | type and its operations. 6 | 7 | ## Vector syntax 8 | 9 | The `vector` type is written using the `vector` keyword followed by the type of the elements in 10 | angle brackets. The type of the elements can be any valid Move type, including other vectors. 11 | 12 | Move has a vector literal syntax that allows you to create vectors using the `vector` keyword 13 | followed by square brackets containing the elements (or no elements for an empty vector). 14 | 15 | ```move file=packages/samples/sources/move-basics/vector.move anchor=literal 16 | 17 | ``` 18 | 19 | The `vector` type is a built-in type in Move, and does not need to be imported from a module. 20 | Vector operations are defined in the `std::vector` module, which is implicitly imported 21 | and can be used directly without explicit `use` import. 22 | 23 | ## Vector operations 24 | 25 | The standard library provides methods to manipulate vectors. The following are some of the most 26 | commonly used operations: 27 | 28 | - `push_back`: Adds an element to the end of the vector. 29 | - `pop_back`: Removes the last element from the vector. 30 | - `length`: Returns the number of elements in the vector. 31 | - `is_empty`: Returns true if the vector is empty. 32 | - `remove`: Removes an element at a given index. 33 | 34 | ```move file=packages/samples/sources/move-basics/vector.move anchor=methods 35 | 36 | ``` 37 | 38 | ## Destroying a Vector of non-droppable types 39 | 40 | A vector of non-droppable types cannot be discarded. If you define a vector of types without the 41 | `drop` ability, the vector value cannot be ignored. If the vector is empty, the compiler requires an 42 | explicit call to the `destroy_empty` function. 43 | 44 | ```move file=packages/samples/sources/move-basics/vector.move anchor=no_drop 45 | 46 | ``` 47 | 48 | The `destroy_empty` function will fail at runtime if you call it on a non-empty vector. 49 | 50 | ## Further Reading 51 | 52 | - [Vector](./../../reference/primitive-types/vector) in the Move Reference. 53 | - [std::vector](https://docs.sui.io/references/framework/std/vector) module documentation. 54 | -------------------------------------------------------------------------------- /packages/samples/sources/move-basics/references.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // ANCHOR: main 5 | module book::references; 6 | // ANCHOR: header_new 7 | /// Error code for when the card is empty. 8 | const ENoUses: u64 = 0; 9 | /// Error code for when the card is not empty. 10 | const EHasUses: u64 = 1; 11 | 12 | /// Number of uses for a metro pass card. 13 | const USES: u8 = 3; 14 | 15 | /// A metro pass card 16 | public struct Card { uses: u8 } 17 | 18 | /// Purchase a metro pass card. 19 | public fun purchase(/* pass a Coin */): Card { 20 | Card { uses: USES } 21 | } 22 | // ANCHOR_END: header_new 23 | 24 | // ANCHOR: immutable 25 | /// Show the metro pass card to the inspector. 26 | public fun is_valid(card: &Card): bool { 27 | card.uses > 0 28 | } 29 | // ANCHOR_END: immutable 30 | 31 | // ANCHOR: mutable 32 | /// Use the metro pass card at the turnstile to enter the metro. 33 | public fun enter_metro(card: &mut Card) { 34 | assert!(card.uses > 0, ENoUses); 35 | card.uses = card.uses - 1; 36 | } 37 | // ANCHOR_END: mutable 38 | 39 | // ANCHOR: move 40 | /// Recycle the metro pass card. 41 | public fun recycle(card: Card) { 42 | assert!(card.uses == 0, EHasUses); 43 | let Card { uses: _ } = card; 44 | } 45 | // ANCHOR_END: move 46 | 47 | // ANCHOR: test 48 | #[test] 49 | fun test_card() { 50 | // declaring variable as mutable because we modify it 51 | let mut card = purchase(); 52 | 53 | enter_metro(&mut card); 54 | 55 | assert!(is_valid(&card)); // read the card! 56 | 57 | enter_metro(&mut card); // modify the card but don't move it 58 | enter_metro(&mut card); // modify the card but don't move it 59 | 60 | recycle(card); // move the card out of the scope 61 | } 62 | // ANCHOR_END: test 63 | 64 | // ANCHOR: move_2024 65 | #[test] 66 | fun test_card_2024() { 67 | // declaring variable as mutable because we modify it 68 | let mut card = purchase(); 69 | 70 | card.enter_metro(); // modify the card but don't move it 71 | assert!(card.is_valid()); // read the card! 72 | 73 | card.enter_metro(); // modify the card but don't move it 74 | card.enter_metro(); // modify the card but don't move it 75 | 76 | card.recycle(); // move the card out of the scope 77 | } 78 | // ANCHOR_END: move_2024 79 | // ANCHOR_END: main 80 | -------------------------------------------------------------------------------- /site/src/theme/CodeBlock/Buttons/CopyButton/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useState, useRef, useEffect, type ReactNode } from 'react'; 2 | import clsx from 'clsx'; 3 | import copy from 'copy-text-to-clipboard'; 4 | import { translate } from '@docusaurus/Translate'; 5 | import { useCodeBlockContext } from '@docusaurus/theme-common/internal'; 6 | import Button from '@theme/CodeBlock/Buttons/Button'; 7 | import type { Props } from '@theme/CodeBlock/Buttons/CopyButton'; 8 | import IconCopy from '@theme/Icon/Copy'; 9 | import IconSuccess from '@theme/Icon/Success'; 10 | 11 | import styles from './styles.module.css'; 12 | 13 | function title() { 14 | return translate({ 15 | id: 'theme.CodeBlock.copy', 16 | message: 'Copy', 17 | description: 'The copy button label on code blocks', 18 | }); 19 | } 20 | 21 | function ariaLabel(isCopied: boolean) { 22 | return isCopied 23 | ? translate({ 24 | id: 'theme.CodeBlock.copied', 25 | message: 'Copied', 26 | description: 'The copied button label on code blocks', 27 | }) 28 | : translate({ 29 | id: 'theme.CodeBlock.copyButtonAriaLabel', 30 | message: 'Copy code to clipboard', 31 | description: 'The ARIA label for copy code blocks button', 32 | }); 33 | } 34 | 35 | function useCopyButton() { 36 | const { 37 | metadata: { code }, 38 | } = useCodeBlockContext(); 39 | const [isCopied, setIsCopied] = useState(false); 40 | const copyTimeout = useRef(undefined); 41 | 42 | const copyCode = useCallback(() => { 43 | copy(code); 44 | setIsCopied(true); 45 | copyTimeout.current = window.setTimeout(() => { 46 | setIsCopied(false); 47 | }, 1000); 48 | }, [code]); 49 | 50 | useEffect(() => () => window.clearTimeout(copyTimeout.current), []); 51 | 52 | return { copyCode, isCopied }; 53 | } 54 | 55 | export default function CopyButton({ className }: Props): ReactNode { 56 | const { copyCode, isCopied } = useCopyButton(); 57 | 58 | return ( 59 | 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /book/storage/store-ability.md: -------------------------------------------------------------------------------- 1 | # Ability: Store 2 | 3 | The [`key` ability][key-ability] requires all fields to have `store`, which defines what the `store` 4 | ability means: it is the ability to serve as a field of an Object. A struct with 5 | [`copy`][copy-ability] or [`drop`][drop-ability] but without `store` can never be _stored_. A type 6 | with `key` but without `store` cannot be wrapped - used as a field—in another object, and is 7 | constrained to always remain at the top level. 8 | 9 | ## Definition 10 | 11 | The `store` ability allows a type to be used as a field in a struct with the `key` ability. 12 | 13 | ```move 14 | // hidden-block-start 15 | use std::string::String; 16 | 17 | // hidden-block-end 18 | /// Extra metadata with `store`; all fields must have `store` as well! 19 | public struct Metadata has store { 20 | bio: String, 21 | } 22 | 23 | /// An object for a single user record. 24 | public struct User has key { 25 | id: UID, 26 | name: String, // String has `store` 27 | age: u8, // All integers have `store` 28 | metadata: Metadata, // Another type with the `store` ability 29 | } 30 | ``` 31 | 32 | ## Relation to `copy` and `drop` 33 | 34 | All three non-`key` abilities can be used in any combination. 35 | 36 | ## Relation to `key` 37 | 38 | An object with the `store` ability can be _stored_ in other objects. 39 | 40 | > While not a language or verifier feature, `store` acts as a _public_ modifier on a struct, 41 | > allowing calling _public_ [transfer functions](./storage-functions.md) which do not have an 42 | > [internal constraint](./internal-constraint.md). 43 | 44 | ## Types with the `store` Ability 45 | 46 | All native types (except references) in Move have the `store` ability. This includes: 47 | 48 | - [bool](./../move-basics/primitive-types.md#booleans) 49 | - [unsigned integers](./../move-basics/primitive-types.md#integer-types) 50 | - [vector](./../move-basics/vector.md) 51 | - [address](./../move-basics/address.md) 52 | 53 | All of the types defined in the standard library have the `store` ability as well. This includes: 54 | 55 | - [Option](./../move-basics/option.md) 56 | - [String](./../move-basics/string.md) and [ASCII String](./../move-basics/string.md) 57 | - [TypeName](./../move-basics/type-reflection.md) 58 | 59 | ## Further Reading 60 | 61 | - [Type Abilities](./../../reference/abilities) in the Move Reference. 62 | 63 | [key-ability]: ./key-ability.md 64 | [drop-ability]: ./../move-basics/drop-ability.md 65 | [copy-ability]: ./../move-basics/copy-ability.md 66 | -------------------------------------------------------------------------------- /packages/samples/sources/move-basics/expression.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #[allow(unused_variable)] 5 | module book::expression; 6 | 7 | #[test] 8 | fun expression_examples() { 9 | 10 | // ANCHOR: empty 11 | // variable `a` has no value; 12 | let a; 13 | // ANCHOR_END: empty 14 | 15 | // ANCHOR: literals 16 | let b = true; // true is a literal 17 | let n = 1000; // 1000 is a literal 18 | let h = 0x0A; // 0x0A is a literal 19 | let v = b"hello"; // b"hello" is a byte vector literal 20 | let x = x"0A"; // x"0A" is a byte vector literal 21 | let c = vector[1, 2, 3]; // vector[] is a vector literal 22 | // ANCHOR_END: literals 23 | 24 | // ANCHOR: operators 25 | let sum = 1 + 2; // 1 + 2 is an expression 26 | let sum = (1 + 2); // the same expression with parentheses 27 | let is_true = true && false; // true && false is an expression 28 | let is_true = (true && false); // the same expression with parentheses 29 | // ANCHOR_END: operators 30 | 31 | // ANCHOR: block 32 | // block with an empty expression, however, the compiler will 33 | // insert an empty expression automatically: `let none = { () }` 34 | // let none = {}; 35 | 36 | // block with let statements and an expression. 37 | let sum = { 38 | let a = 1; 39 | let b = 2; 40 | a + b // last expression is the value of the block 41 | }; 42 | 43 | // block is an expression, so it can be used in an expression and 44 | // doesn't have to be assigned to a variable. 45 | { 46 | let a = 1; 47 | let b = 2; 48 | a + b; // not returned - semicolon. 49 | // compiler automatically inserts an empty expression `()` 50 | }; 51 | // ANCHOR_END: block 52 | } 53 | 54 | // ANCHOR: fun_call 55 | fun add(a: u8, b: u8): u8 { 56 | a + b 57 | } 58 | 59 | #[test] 60 | fun some_other() { 61 | let sum = add(1, 2); // not returned due to the semicolon. 62 | // compiler automatically inserts an empty expression `()` as return value of the block 63 | } 64 | // ANCHOR_END: fun_call 65 | 66 | 67 | #[test] fun control_flow() { 68 | 69 | let expr = false; 70 | let expr1 = false; 71 | let expr2 = false; 72 | let bool_expr = false; 73 | 74 | // ANCHOR: control_flow 75 | // if is an expression, so it returns a value; if there are 2 branches, 76 | // the types of the branches must match. 77 | if (bool_expr) expr1 else expr2; 78 | 79 | // while is an expression, but it returns `()`. 80 | while (bool_expr) { expr; }; 81 | 82 | // loop is an expression, but returns `()` as well. 83 | loop { expr; break }; 84 | // ANCHOR_END: control_flow 85 | } 86 | -------------------------------------------------------------------------------- /book/storage/internal-constraint.md: -------------------------------------------------------------------------------- 1 | # Sui Verifier: Internal Constraint 2 | 3 | The Sui Bytecode Verifier enforces a set of rules on Move bytecode to ensure the safety of critical 4 | storage operations. One of these rules is the _internal constraint_. It requires that the caller of 5 | a function with a type parameter `T` must be the _defining module_ of that type. In other words, T 6 | must be _internal_ to the module making the call. 7 | 8 | This rule is not (yet) part of the Move language itself, which can make it feel opaque. Still, it’s 9 | an important rule to understand, especially when working with storage-related operations on Sui. 10 | 11 | Let’s look at an example from the [Sui Framework][sui-framework]. The emit function in the 12 | [`sui::event`][event] module requires its type parameter `T` to be _internal_ to the caller: 13 | 14 | ```move 15 | // An actual example of a function that enforces `internal` on `T`. 16 | module sui::event; 17 | 18 | // Sui Verifier will emit an error at compilation if this function is 19 | // called from a module that does not define `T`. 20 | public native fun emit(event: T); 21 | ``` 22 | 23 | Here’s a correct call to `emit`. The type `A` is defined inside the module `exercise_internal`, so 24 | it’s internal and valid: 25 | 26 | ```move 27 | // Defines type `A`. 28 | module book::exercise_internal; 29 | 30 | use sui::event; 31 | 32 | /// Type defined in this module, so it's internal here. 33 | public struct A has copy, drop {} 34 | 35 | // This works because `A` is defined locally. 36 | public fun call_internal() { 37 | event::emit(A {}) 38 | } 39 | ``` 40 | 41 | But if you try to call `emit` with a type defined elsewhere, the verifier rejects it. For example, 42 | this function, when added to the same module, fails because it tries to use the `TypeName` type from 43 | the [Standard Library][move-stdlib]: 44 | 45 | ```move 46 | // This one fails! 47 | public fun call_foreign_fail() { 48 | use std::type_name; 49 | 50 | event::emit(type_name::get()); 51 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Invalid event. 52 | // Error: `sui::event::emit` must be called with a type 53 | // defined in the current module. 54 | } 55 | ``` 56 | 57 | Internal constraints only apply to certain functions in the [Sui Framework][sui-framework]. We’ll 58 | return to this concept several times throughout the book. 59 | 60 | [sui-framework]: ./../programmability/sui-framework.md 61 | [move-stdlib]: ./../move-basics/standard-library.md 62 | [event]: ./../programmability/events.md 63 | [reflection]: ./../move-basics/type-reflection.md 64 | -------------------------------------------------------------------------------- /packages/samples/sources/programmability/display.move: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | 5 | #[allow(unused_field)] 6 | // ANCHOR: hero 7 | module book::arena; 8 | 9 | use std::string::String; 10 | use sui::package; 11 | use sui::display; 12 | 13 | /// The One Time Witness to claim the `Publisher` object. 14 | public struct ARENA has drop {} 15 | 16 | /// Some object which will be displayed. 17 | public struct Hero has key { 18 | id: UID, 19 | class: String, 20 | level: u64, 21 | } 22 | 23 | /// In the module initializer we create the `Publisher` object, and then 24 | /// the Display for the `Hero` type. 25 | fun init(otw: ARENA, ctx: &mut TxContext) { 26 | let publisher = package::claim(otw, ctx); 27 | let mut display = display::new(&publisher, ctx); 28 | 29 | display.add( 30 | b"name".to_string(), 31 | b"{class} (lvl. {level})".to_string() 32 | ); 33 | 34 | display.add( 35 | b"description".to_string(), 36 | b"One of the greatest heroes of all time. Join us!".to_string() 37 | ); 38 | 39 | display.add( 40 | b"link".to_string(), 41 | b"https://example.com/hero/{id}".to_string() 42 | ); 43 | 44 | display.add( 45 | b"image_url".to_string(), 46 | b"https://example.com/hero/{class}.jpg".to_string() 47 | ); 48 | 49 | // Update the display with the new data. 50 | // Must be called to apply changes. 51 | display.update_version(); 52 | 53 | transfer::public_transfer(publisher, ctx.sender()); 54 | transfer::public_transfer(display, ctx.sender()); 55 | } 56 | // ANCHOR_END: hero 57 | 58 | // ANCHOR: background 59 | /// An attempt to standardize the object structure for display. 60 | public struct CounterWithDisplay has key { 61 | id: UID, 62 | /// If this field is present it will be displayed in the UI as `name`. 63 | name: String, 64 | /// If this field is present it will be displayed in the UI as `description`. 65 | description: String, 66 | // ... 67 | image: String, 68 | /// Actual fields of the object. 69 | counter: u64, 70 | // ... 71 | } 72 | // ANCHOR_END: background 73 | 74 | // ANCHOR: nested 75 | /// Some common metadata for objects. 76 | public struct Metadata has store { 77 | name: String, 78 | description: String, 79 | published_at: u64 80 | } 81 | 82 | /// The type with nested Metadata field. 83 | public struct LittlePony has key, store { 84 | id: UID, 85 | image_url: String, 86 | metadata: Metadata 87 | } 88 | // ANCHOR_END: nested 89 | -------------------------------------------------------------------------------- /book/move-basics/constants.md: -------------------------------------------------------------------------------- 1 | # Constants 2 | 3 | 20 | 21 | Constants are immutable values that are defined at the module level. They often serve as a way to 22 | give names to static values that are used throughout a module. For example, if there's a default 23 | price for a product, you might define a constant for it. Constants are stored in the module's 24 | bytecode, and each time they are used, the value is copied. 25 | 26 | ```move file=packages/samples/sources/move-basics/constants-shop-price.move anchor=shop_price 27 | 28 | ``` 29 | 30 | ## Naming Convention 31 | 32 | Constants must start with a capital letter - this is enforced at the compiler level. For constants 33 | used as a value, the convention is to use all uppercase letters and underscores between words, which 34 | makes constants stand out from other identifiers in the code. An exception is made for 35 | [error constants](./assert-and-abort#error-constants), which are written in ECamelCase. 36 | 37 | ```move file=packages/samples/sources/move-basics/constants-naming.move anchor=naming 38 | 39 | ``` 40 | 41 | ## Constants are Immutable 42 | 43 | Constants can't be changed and assigned new values. As part of the package bytecode, they are 44 | inherently immutable. 45 | 46 | ```move 47 | module book::immutable_constants; 48 | 49 | const ITEM_PRICE: u64 = 100; 50 | 51 | // emits an error 52 | fun change_price() { 53 | ITEM_PRICE = 200; 54 | } 55 | ``` 56 | 57 | ## Using Config Pattern 58 | 59 | A common use case for an application is to define a set of constants that are used throughout the 60 | codebase. But due to constants being private to the module, they can't be accessed from other 61 | modules. One way to solve this is to define a "config" module that exports the constants. 62 | 63 | ```move file=packages/samples/sources/move-basics/constants-config.move anchor=config 64 | 65 | ``` 66 | 67 | This way other modules can import and read the constants, and the update process is simplified. If 68 | the constants need to be changed, only the config module needs to be updated during the package 69 | upgrade. 70 | 71 | ## Links 72 | 73 | - [Constants](./../../reference/constants) in the Move Reference 74 | - [Coding conventions for constants](./../guides/code-quality-checklist#regular-constant-are-all_caps) 75 | -------------------------------------------------------------------------------- /book/object/object-model.md: -------------------------------------------------------------------------------- 1 | # What is an Object? 2 | 3 | The Object Model in Sui can be viewed as a high-level abstraction representing digital assets as 4 | _objects_. These objects have their own type and associated behaviors, a unique identifier, and 5 | support native storage operations like _transfer_ and _share_. Designed to be intuitive and easy to 6 | use, the Object Model enables a wide range of use cases to be implemented with ease. 7 | 8 | Objects in Sui have the following properties: 9 | 10 | - **Type:** Every object has a type, defining the structure and behavior of the object. Objects of 11 | different types cannot be mixed or used interchangeably, ensuring objects are used correctly 12 | according to their type system. 13 | 14 | - **Unique ID:** Each object has a unique identifier, distinguishing it from other objects. This ID 15 | is generated upon the object's creation and is immutable. It's used to track and identify objects 16 | within the system. 17 | 18 | 19 | 20 | - **Owner:** Every object is associated with an owner, who has control over changes to the object. 21 | Ownership on Sui can be exclusive to an account, shared across the network, or frozen, allowing 22 | read-only access without modification or transfer capabilities. We will discuss ownership in more 23 | detail in the following sections. 24 | 25 | Note that ownership does not control the confidentiality of an object — it is always 26 | possible to read the contents of an on-chain object from outside of Move. You should never store 27 | unencrypted secrets inside of objects. 28 | 29 | - **Data:** Objects encapsulate their data, simplifying management and manipulation. The data 30 | structure and operations are defined by the object's type. 31 | 32 | - **Version:** The transition from accounts to objects is facilitated by object versioning. 33 | Traditionally, blockchains use a _nonce_ to prevent replay attacks. In Sui, the object's version 34 | acts as a nonce, preventing replay attacks for each object. 35 | 36 | - **Digest:** Every object has a digest, which is a hash of the object's data. The digest is used to 37 | cryptographically verify the integrity of the object's data and ensures that it has not been 38 | tampered with. The digest is calculated when the object is created and is updated whenever the 39 | object's data changes. 40 | 41 | ## Summary 42 | 43 | - Objects in Sui are high-level abstractions representing digital assets. 44 | - Objects have a type, unique ID, owner, data, version, and digest. 45 | - The Object Model simplifies asset management and enables a wide range of use cases. 46 | 47 | ## Further Reading 48 | 49 | - [Object Model](https://docs.sui.io/concepts/object-model) in Sui Documentation. 50 | -------------------------------------------------------------------------------- /book/programmability/wrapper-type-pattern.md: -------------------------------------------------------------------------------- 1 | # Pattern: Wrapper type 2 | 3 | Sometimes, there’s a need to create a new type that behaves similarly to an existing type but with 4 | certain modifications or restrictions. For example, you might want to create a 5 | [collection type](./collections) that behaves like a vector but doesn’t allow modifying the elements 6 | after they’ve been inserted. The wrapper type pattern is an effective way to achieve this. 7 | 8 | ## Definition 9 | 10 | The wrapper type pattern is a design pattern in which you create a new type that wraps an existing 11 | type. The wrapper type is distinct from the original but can be converted to and from it. 12 | 13 | Often, it is implemented as a positional struct with a single field. 14 | 15 | ```move file=packages/samples/sources/programmability/wrapper-type-pattern.move anchor=main 16 | 17 | ``` 18 | 19 | ## Common Practices 20 | 21 | In cases where the goal is to extend the behavior of an existing type, it is common to provide 22 | accessors for the wrapped type. This approach allows users to access the underlying type directly 23 | when needed. For example, in the following code, we provide the `inner()`, `inner_mut()`, and 24 | `into_inner()` methods for the Stack type. 25 | 26 | ```move file=packages/samples/sources/programmability/wrapper-type-pattern.move anchor=common 27 | 28 | ``` 29 | 30 | ## Advantages 31 | 32 | The wrapper type pattern offers several benefits: 33 | 34 | - Custom Functions: It allows you to define custom functions for an existing type. 35 | - Robust Function Signatures: It constrains function signatures to the new type, thereby making the 36 | code more robust. 37 | - Improved Readability: It often increases the readability of the code by providing a more 38 | descriptive type name. 39 | 40 | ## Disadvantages 41 | 42 | The wrapper type pattern is powerful in two scenarios—when you want to limit the behavior of an 43 | existing type while providing a custom interface to the same data structure, and when you want to 44 | extend the behavior of an existing type. However, it does have some limitations: 45 | 46 | - Verbosity: It can be verbose to implement, especially if you want to expose all the methods of the 47 | wrapped type. 48 | - Sparse Implementation: The implementation can be quite minimal, as it often just forwards calls to 49 | the wrapped type. 50 | 51 | ## Next Steps 52 | 53 | The wrapper type pattern is very useful, particularly when used in conjunction with collection 54 | types, as demonstrated in the previous section. In the next section, we will cover 55 | [Dynamic Fields](./dynamic-fields) — an important primitive that enables 56 | [Dynamic Collections](./dynamic-collections), a way to store large collections of data in a more 57 | flexible, albeit more expensive, way. 58 | -------------------------------------------------------------------------------- /book/before-we-begin/ide-support.md: -------------------------------------------------------------------------------- 1 | # Set Up Your IDE 2 | 3 | There are two most popular IDEs for Move development: VSCode and IntelliJ IDEA. Both of them provide 4 | basic features like syntax highlighting and error messages, though they differ in their additional 5 | features. Whatever IDE you choose, you'll need to use the terminal to run the 6 | [Move CLI](./install-sui.md). 7 | 8 | > **IntelliJ Plugin does not support Move 2024 edition, some syntax won't get highlighted.** 9 | 10 | ## VSCode 11 | 12 | - [VSCode](https://code.visualstudio.com/) is a free and open source IDE from Microsoft. 13 | - [Move (Extension)](https://marketplace.visualstudio.com/items?itemName=mysten.move) is a language 14 | server extension for Move maintained by [Mysten Labs](https://mystenlabs.com). 15 | - [Move Formatter](https://marketplace.visualstudio.com/items?itemName=mysten.prettier-move) - code 16 | formatter for Move, developed and maintained by [Mysten Labs](https://mystenlabs.com). 17 | - [Move Syntax](https://marketplace.visualstudio.com/items?itemName=damirka.move-syntax) a simple 18 | syntax highlighting extension for Move by [Damir Shamanaev](https://github.com/damirka/). 19 | 20 | ## IntelliJ IDEA 21 | 22 | - [IntelliJ IDEA](https://www.jetbrains.com/idea/) is a commercial IDE from JetBrains. 23 | - [Move Language Plugin](https://plugins.jetbrains.com/plugin/23301-sui-move-language) provides a 24 | Move on Sui language extension for IntelliJ IDEA by [MoveFuns](https://movefuns.org/). 25 | 26 | ## Emacs 27 | 28 | - [Emacs](https://www.gnu.org/software/emacs/) is a free and open source text editor. 29 | - [move-mode](https://github.com/amnn/move-mode) is a Move mode for Emacs by 30 | [Ashok Menon](https://github.com/amnn). 31 | 32 | ## Zed 33 | 34 | - [Zed](https://zed.dev/) is a next-generation code editor designed for high-performance 35 | collaboration with humans and AI. 36 | - [Move](https://github.com/Tzal3x/move-zed-extension) is a language server extension for Move 37 | maintained by [Tzal3x](https://github.com/Tzal3x). 38 | 39 | ## Github Codespaces 40 | 41 | The Web-based IDE from Github can be run right in the browser and provides almost a full-featured 42 | VSCode experience. 43 | 44 | - [Github Codespaces](https://github.com/features/codespaces) 45 | - [Move Syntax](https://marketplace.visualstudio.com/items?itemName=damirka.move-syntax) is also 46 | available in the extensions marketplace. 47 | - [Move Formatter](https://marketplace.visualstudio.com/items?itemName=mysten.prettier-move) is also 48 | available in the extensions marketplace. 49 | 50 | ## Other (CLI) 51 | 52 | Some of the tools listed above have CLI-supported versions. 53 | 54 | - [prettier-plugin-move](https://www.npmjs.com/package/@mysten/prettier-plugin-move) contains the 55 | TypeScript package for the Prettier@v3 plugin as well as the binary to run it in a terminal 56 | -------------------------------------------------------------------------------- /book/guides/building-against-limits.md: -------------------------------------------------------------------------------- 1 | # Building Against Limits 2 | 3 | To guarantee the safety and security of the network, Sui has certain limits and restrictions. These 4 | limits are in place to prevent abuse and to ensure that the network remains stable and efficient. 5 | This guide provides an overview of these limits and restrictions, and how to build your application 6 | to work within them. 7 | 8 | The limits are defined in the protocol configuration and are enforced by the network. If any of the 9 | limits are exceeded, the transaction will either be rejected or aborted. The limits, being a part of 10 | the protocol, can only be changed through a network upgrade. 11 | 12 | ## Transaction Size 13 | 14 | The size of a transaction is limited to 128KB. This includes the size of the transaction payload, 15 | the size of the transaction signature, and the size of the transaction metadata. If a transaction 16 | exceeds this limit, it will be rejected by the network. 17 | 18 | ## Object Size 19 | 20 | The size of an object is limited to 256KB. This includes the size of the object data. If an object 21 | exceeds this limit, it will be rejected by the network. While a single object cannot bypass this 22 | limit, for more extensive storage options, one could use a combination of a base object with other 23 | attached to it using dynamic fields (eg Bag). 24 | 25 | ## Single Pure Argument Size 26 | 27 | The size of a single pure argument is limited to 16KB. A transaction argument bigger than this limit 28 | will result in execution failure. So in order to create a vector of more than ~500 addresses (given 29 | that a single address is 32 bytes), it needs to be joined dynamically either in Transaction Block or 30 | in a Move function. Standard functions like `vector::append()` can join two vectors of ~16KB 31 | resulting in a ~32KB of data as a single value. 32 | 33 | ## Maximum Number of Objects (and Dynamic Fields) Created 34 | 35 | The maximum number of objects that can be created in a single transaction is 2048. If a transaction 36 | attempts to create more than 2048 objects, it will be rejected by the network. This also affects 37 | [dynamic fields](./../programmability/dynamic-fields.md), as both the key and the value are objects. 38 | So the maximum number of [dynamic fields](./../programmability/dynamic-fields.md) that can be 39 | created in a single transaction is 1000. The limitation applies to dynamic object fields as well. 40 | 41 | ## Maximum Number of Dynamic Fields Accessed 42 | 43 | The maximum number of dynamic fields that can be accessed in a single transaction is 1000. If a 44 | transaction attempts to access more than 1000 dynamic fields, it will be rejected by the network. 45 | 46 | ## Maximum Number of Events 47 | 48 | The maximum number of events that can be emitted in a single transaction is 1024. If a transaction 49 | attempts to emit more than 1024 events, it will be aborted. 50 | -------------------------------------------------------------------------------- /book/concepts/packages.md: -------------------------------------------------------------------------------- 1 | # Package 2 | 3 | 18 | 19 | Move is a language for writing smart contracts - programs that are stored and run on the blockchain. 20 | A single program is organized into a package. A package is published on the blockchain and is 21 | identified by an [address](./address). A published package can be interacted with by sending 22 | [transactions](./what-is-a-transaction) calling its functions. It can also act as a dependency for 23 | other packages. 24 | 25 | > To create a new package, use the `sui move new` command. To learn more about the command, run 26 | > `sui move new --help`. 27 | 28 | Package consists of modules - separate scopes that contain functions, types, and other items. 29 | 30 | ``` 31 | package 0x... 32 | module a 33 | struct A1 34 | fun hello_world() 35 | module b 36 | struct B1 37 | fun hello_package() 38 | ``` 39 | 40 | ## Package Structure 41 | 42 | Locally, a package is a directory with a `Move.toml` file and a `sources` directory. The `Move.toml` 43 | file - called the "package manifest" - contains metadata about the package, and the `sources` 44 | directory contains the source code for the modules. Package usually looks like this: 45 | 46 | ``` 47 | sources/ 48 | my_module.move 49 | another_module.move 50 | ... 51 | tests/ 52 | ... 53 | examples/ 54 | using_my_module.move 55 | Move.toml 56 | ``` 57 | 58 | The `tests` directory is optional and contains tests for the package. Code placed into the `tests` 59 | directory is not published on-chain and is only available in tests. The `examples` directory can be 60 | used for code examples, and is also not published on-chain. 61 | 62 | ## Published Package 63 | 64 | During development, package doesn't have an address and it needs to be set to `0x0`. Once a package 65 | is published, it gets a single unique [address](./address) on the blockchain containing its modules' 66 | bytecode. A published package becomes _immutable_ and can be interacted with by sending 67 | transactions. 68 | 69 | ``` 70 | 0x... 71 | my_module: 72 | another_module: 73 | ``` 74 | 75 | ## Links 76 | 77 | - [Package Manifest](./manifest) 78 | - [Address](./address) 79 | - [Packages](./../../reference/packages) in the Move Reference. 80 | -------------------------------------------------------------------------------- /book/move-basics/abilities-introduction.md: -------------------------------------------------------------------------------- 1 | # Abilities: Introduction 2 | 3 | Move has a unique type system which allows customizing _type abilities_. 4 | [In the previous section](./struct), we introduced the `struct` definition and how to use it. 5 | However, the instances of the `Artist` and `Record` structs had to be unpacked for the code to 6 | compile. This is default behavior of a struct without _abilities_. 7 | 8 | > Throughout the book you will see chapters with name `Ability: `, where `` is the name 9 | > of the ability. These chapters will cover the ability in detail, how it works, and how to use it 10 | > in Move. 11 | 12 | ## What are Abilities? 13 | 14 | Abilities are a way to allow certain behaviors for a type. They are a part of the struct declaration 15 | and define which behaviors are allowed for the instances of the struct. 16 | 17 | ## Abilities Syntax 18 | 19 | Abilities are set in the struct definition using the `has` keyword followed by a list of abilities. 20 | The abilities are separated by commas. Move supports 4 abilities: `copy`, `drop`, `key`, and 21 | `store`. Each ability defines a specific behavior for the struct instances. 22 | 23 | ```move 24 | /// This struct has the `copy` and `drop` abilities. 25 | public struct VeryAble has copy, drop { 26 | // field: Type1, 27 | // field2: Type2, 28 | // ... 29 | } 30 | ``` 31 | 32 | ## Overview 33 | 34 | A quick overview of the abilities: 35 | 36 | > All of the built-in types except [references](references) have `copy`, `drop`, and `store` 37 | > abilities. References have `copy` and `drop`. 38 | 39 | - `copy` - allows the struct to be _copied_. Explained in the [Ability: Copy](./copy-ability) 40 | chapter. 41 | - `drop` - allows the struct to be _dropped_ or _discarded_. Explained in the 42 | [Ability: Drop](./drop-ability) chapter. 43 | - `key` - allows the struct to be used as a _key_ in a storage. Explained in the 44 | [Ability: Key](./../storage/key-ability) chapter. 45 | - `store` - allows the struct to be _stored_ in structs that have the _key_ ability. Explained in 46 | the [Ability: Store](./../storage/store-ability) chapter. 47 | 48 | While it is important to briefly mention them here, we will go into more detail about each ability 49 | in the following chapters and give proper context on how to use them. 50 | 51 | ## No Abilities 52 | 53 | A struct without abilities cannot be discarded, copied, or stored in storage. We call such a struct 54 | a _Hot Potato_. A lighthearted name, but it is a good way to remember that a struct without 55 | abilities is like a hot potato - it can only be passed around and requires special handling. The Hot 56 | Potato is one of the most powerful patterns in Move, and we go into more detail about it in the 57 | [Hot Potato Pattern](./../programmability/hot-potato-pattern) chapter. 58 | 59 | ## Further Reading 60 | 61 | - [Type Abilities](./../../reference/abilities) in the Move Reference. 62 | -------------------------------------------------------------------------------- /site/src/plugins/yaml-sidebar.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Mysten Labs, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as yaml from 'yaml'; 5 | import fs from 'fs'; 6 | import type { SidebarsConfig } from '@docusaurus/plugin-content-docs'; 7 | import type { SidebarItemConfig } from '@docusaurus/plugin-content-docs/lib/sidebars/types.js'; 8 | 9 | type ExtendedSidebarItemConfig = SidebarItemConfig & { 10 | enumerate?: boolean; 11 | }; 12 | 13 | /** 14 | * Loads a sidebar from a YAML file and returns a SidebarsConfig object. 15 | * Docusaurus will error out if the sidebar is not valid. 16 | * 17 | * @param yamlPath - The path to the YAML file. 18 | * @returns A SidebarsConfig object. 19 | */ 20 | export function loadSidebarsFromYaml(yamlPath: string): SidebarsConfig { 21 | const sidebars: SidebarsConfig = {}; 22 | 23 | // Read all YAML files in the directory 24 | const yamlContent = fs.readFileSync(yamlPath, 'utf8'); 25 | const sidebarConfig = yaml.parse(yamlContent); 26 | 27 | // Enumerate or keep config as is. 28 | Object.entries(sidebarConfig).forEach(([key, value]) => { 29 | sidebars[key] = processSidebar(value as ExtendedSidebarItemConfig[]); 30 | }); 31 | 32 | return sidebars; 33 | } 34 | 35 | /** 36 | * Enumerate the sidebar items. 37 | * Supports custom `enumerate` tag. 38 | * 39 | * @param sidebar - The sidebar to enumerate. 40 | * @param parentIndex - The index of the parent item (for recursive enumeration). 41 | * @returns The enumerated sidebar. 42 | */ 43 | export function processSidebar( 44 | sidebar: ExtendedSidebarItemConfig[], 45 | parentIndex?: number, 46 | parentEnumerate: boolean = true, 47 | ): SidebarItemConfig[] { 48 | let index = 0; 49 | 50 | return sidebar.map((item) => { 51 | // plain autogenerated items 52 | if (typeof item === 'string') { 53 | return item; 54 | } 55 | 56 | let enumerate = (item.enumerate == false ? false : true) && parentEnumerate; 57 | 'enumerate' in item && delete item.enumerate; // strip illegal tags 58 | 59 | // default to doc if type not specified 60 | if (item.type === undefined) { 61 | item.type = 'doc'; 62 | } 63 | 64 | // enumerate category header if it has a label and link 65 | if (enumerate && item.type === 'category' && item.label && item.link) { 66 | index++; 67 | item.label = `${parentIndex ? `${parentIndex}.` : ''}${index}. ${item.label}`; 68 | } 69 | 70 | // enumerate category items 71 | // if category has no enumeration, items are not children but top level items 72 | if (item.type === 'category' && item.items) { 73 | item.items = processSidebar(item.items as ExtendedSidebarItemConfig[], index, enumerate); 74 | } 75 | 76 | if (enumerate && item.type === 'doc' && item.label) { 77 | index++; 78 | item.label = `${parentIndex ? `${parentIndex}.` : ''}${index}. ${item.label}`; 79 | } 80 | 81 | return item; 82 | }); 83 | } 84 | -------------------------------------------------------------------------------- /book/move-basics/expression.md: -------------------------------------------------------------------------------- 1 | # Expression 2 | 3 | In programming languages, an expression is a unit of code that returns a value. In Move, almost 4 | everything is an expression, with the sole exception of the `let` statement, which is a declaration. 5 | In this section, we cover the types of expressions and introduce the concept of scope. 6 | 7 | > Expressions are sequenced with semicolons `;`. If there's "no expression" after the semicolon, the 8 | > compiler will insert a `unit ()`, which represents an empty expression. 9 | 10 | ## Literals 11 | 12 | In the [Primitive types](./primitive-types) section, we introduced the basic types of Move. And to 13 | illustrate them, we used literals. A literal is a notation for representing a fixed value in source 14 | code. Literals can be used to initialize variables or directly pass fixed values as arguments to 15 | functions. Move has the following literals: 16 | 17 | - Boolean values: `true` and `false` 18 | - Integer values: `0`, `1`, `123123` 19 | - Hexadecimal values: Numbers prefixed with 0x to represent integers, such as `0x0`, `0x1`, `0x123` 20 | - Byte vector values: Prefixed with `b`, such as `b"bytes_vector"` 21 | - Byte values: Hexadecimal literals prefixed with `x`, such as `x"0A"` 22 | 23 | ```move file=packages/samples/sources/move-basics/expression.move anchor=literals 24 | 25 | ``` 26 | 27 | ## Operators 28 | 29 | Arithmetic, logical, and bitwise operators are used to perform operations on values. Since these 30 | operations produce values, they are considered expressions. 31 | 32 | ```move file=packages/samples/sources/move-basics/expression.move anchor=operators 33 | 34 | ``` 35 | 36 | ## Blocks 37 | 38 | A block is a sequence of statements and expressions enclosed in curly braces `{}`. It returns the 39 | value of the last expression in the block (note that this final expression must not have an ending 40 | semicolon). A block is an expression, so it can be used anywhere an expression is expected. 41 | 42 | ```move file=packages/samples/sources/move-basics/expression.move anchor=block 43 | 44 | ``` 45 | 46 | ## Function Calls 47 | 48 | We go into detail about functions in the [Functions](./function) section. However, we have already 49 | used function calls in previous sections, so it's worth mentioning them here. A function call is an 50 | expression that calls a function and returns the value of the last expression in the function body, 51 | provided the last expression does not have a terminating semi-colon. 52 | 53 | ```move file=packages/samples/sources/move-basics/expression.move anchor=fun_call 54 | 55 | ``` 56 | 57 | ## Control Flow Expressions 58 | 59 | Control flow expressions are used to control the flow of the program. They are also expressions, so 60 | they return a value. We cover control flow expressions in the [Control Flow](./control-flow) 61 | section. Here's a very brief overview: 62 | 63 | ```move file=packages/samples/sources/move-basics/expression.move anchor=control_flow 64 | 65 | ``` 66 | -------------------------------------------------------------------------------- /book/move-basics/type-reflection.md: -------------------------------------------------------------------------------- 1 | # Type Reflection 2 | 3 | In programming languages, _reflection_ is the ability of a program to examine and modify its own 4 | structure and behavior. Move supports a limited form of reflection that lets you inspect the type of 5 | a value at runtime. This is handy when you need to store type information in a homogeneous 6 | collection, or when you want to check if a type comes from a particular package. 7 | 8 | Type reflection is implemented in the [Standard Library](./standard-library) module 9 | [`std::type_name`][type-name-stdlib]. It provides a set of functions, main of which are 10 | `with_defining_ids` and `with_original_ids`. 11 | 12 | ```move 13 | let defining_type_name: TypeName = type_name::with_defining_ids(); 14 | let original_type_name: TypeName = type_name::with_original_ids(); 15 | 16 | // Returns only "ID" of the package. 17 | let defining_package: address = type_name::defining_id(); 18 | let original_package: address = type_name::original_id(); 19 | ``` 20 | 21 | ## Defining IDs vs. Original IDs 22 | 23 | It is important to understand the difference between _defining ID_ and _original ID_. 24 | 25 | - Original ID is the first published ID of the package (before the first upgrade). 26 | - Defining ID is the package ID which introduced the reflected type, this property becomes crucial 27 | when new types are introduced in package upgrades. 28 | 29 | For example, suppose the first version of a package was published at `0xA` and introduced the type 30 | `Version1`. Later, in an upgrade, the package moved to address `0xB` and introduced a new type 31 | `Version2`. For `Version1`, the defining ID and original ID are the same. For `Version2`, however, 32 | they differ: the original ID is `0xA`, while the defining ID is `0xB`. 33 | 34 | ```move 35 | // Note: values `0xA` and `0xB` are used for illustration purposes only! 36 | // Don't attempt to run this code, as it will inevitably fail. 37 | module book::upgrade; 38 | 39 | // Introduced in initial version. 40 | // Defining ID: 0xA 41 | // Original ID: 0xA 42 | // 43 | // With Defining IDs: 0xA::upgrade::Version1 44 | // With Original IDs: 0xA::upgrade::Version1 45 | public struct Version1 has drop {} 46 | 47 | // Introduced in a package upgrade. 48 | // Defining ID: 0xB 49 | // highlight-important 50 | // Original ID: 0xA 51 | // 52 | // With Defining IDs: 0xB::upgrade::Version2 53 | // highlight-important 54 | // With Original IDs: 0xA::upgrade::Version2 55 | public struct Version2 has drop {} 56 | ``` 57 | 58 | ## In practice 59 | 60 | The module is straightforward, and operations allowed on the result are limited to getting a string 61 | representation and extracting the module and address of the type. 62 | 63 | ```move file=packages/samples/sources/move-basics/type-reflection.move anchor=main 64 | 65 | ``` 66 | 67 | ## Further Reading 68 | 69 | - [std::type_name][type-name-stdlib] module documentation. 70 | 71 | [type-name-stdlib]: https://docs.sui.io/references/framework/std/type_name 72 | -------------------------------------------------------------------------------- /book/storage/transfer-to-object.md: -------------------------------------------------------------------------------- 1 | # Receiving as Object 2 | 3 | [Address owned](./storage-functions.md#transfer) Object state supports two types of owners: an 4 | account and another Object. If an object was transferred to another object, Sui provides a way to 5 | _receive_ this object through its owner's [`UID`][uid]. 6 | 7 | > This feature is also known as _"Transfer to Object"_ or TTO. 8 | 9 | ## Definition 10 | 11 | Receiving functionality is implemented in the [`sui::transfer`][transfer] module. It consists of a 12 | special type `Receiving` which is instantiated through a special transaction argument, and the 13 | `receive` function which takes a [`UID`][uid] of the parent. 14 | 15 | > Currently, `T` in the `transfer::receive` is a subject to [Internal Constraint][internal]. Public 16 | > version of `receive` is called `public_receive`, and like other [storage functions][storage-funs] 17 | > it requires `T` to have [`store`][store]. 18 | 19 | ```move 20 | module sui::transfer; 21 | 22 | // An ephemeral wrapper around `Receiving` argument. Provided as a special input 23 | // in a Transaction Block. 24 | // Note: this type should be explicitly imported to be used! 25 | public struct Receiving has drop { 26 | id: ID, 27 | version: u64, 28 | } 29 | 30 | /// Receive `T` from parent `UID` through special type `Receiving`. 31 | public fun receive(parent: &mut UID, to_receive: Receiving): T; 32 | ``` 33 | 34 | Due to the `UID` type requirement, receiving cannot be performed on an arbitrary object that does 35 | not provide access or special receiving implementation. This feature should be used be used with 36 | caution and in a controlled setting. 37 | 38 | ## Example 39 | 40 | As an illustration for _transfer_ and _receive_ consider an example: `PostOffice` allows registering 41 | Post Boxes and sending to accounts' post boxes. 42 | 43 | ```move file=packages/samples/sources/storage/transfer-to-object.move anchor=main 44 | 45 | ``` 46 | 47 | ## Use Cases 48 | 49 | Transferring to objects is a powerful feature which allows objects to act as owners of other 50 | objects. One of the reasons to use it is the extra authorization performed upon receiving, eg the 51 | `PostOffice` in the example above could charge a receiving fee. 52 | 53 | - Allows parallel execution of transfers to multiple objects without referencing them in the 54 | transaction; 55 | - Parent objects can also be transferred, acting as a container; 56 | - PostBox-like applications, where user gets assets only after activating their account; 57 | - Account abstraction-like applications where an object is mocking an account. 58 | 59 | ## Links 60 | 61 | - [Transfer to Object](https://docs.sui.io/concepts/transfers/transfer-to-object) in Sui 62 | Documentation 63 | - [`sui::transfer`][transfer] module documentation 64 | 65 | [transfer]: https://docs.sui.io/references/framework/sui_sui/transfer 66 | [key]: ./key-ability.md 67 | [store]: ./store-ability.md 68 | [uid]: ./uid-and-id.md 69 | [internal]: ./internal-constraint.md 70 | -------------------------------------------------------------------------------- /book/programmability/publisher.md: -------------------------------------------------------------------------------- 1 | # Publisher Authority 2 | 3 | In application design and development, it is often needed to prove publisher authority. This is 4 | especially important in the context of digital assets, where the publisher may enable or disable 5 | certain features for their assets. The Publisher Object is an object, defined in the 6 | [Sui Framework](./sui-framework), that allows the publisher to prove their _authority over a type_. 7 | 8 | ## Definition 9 | 10 | The Publisher object is defined in the `sui::package` module of the Sui Framework. It is a very 11 | simple, non-generic object that can be initialized once per module (and multiple times per package) 12 | and is used to prove the authority of the publisher over a type. To claim a Publisher object, the 13 | publisher must present a [One Time Witness](./one-time-witness) to the `package::claim` function. 14 | 15 | ```move 16 | module sui::package; 17 | 18 | public struct Publisher has key, store { 19 | id: UID, 20 | package: String, 21 | module_name: String, 22 | } 23 | ``` 24 | 25 | > If you're not familiar with the One Time Witness, you can read more about it 26 | > [here](./one-time-witness). 27 | 28 | Here's a simple example of claiming a `Publisher` object in a module: 29 | 30 | ```move file=packages/samples/sources/programmability/publisher.move anchor=publisher 31 | 32 | ``` 33 | 34 | ## Usage 35 | 36 | The Publisher object has two functions associated with it which are used to prove the publisher's 37 | authority over a type: 38 | 39 | ```move file=packages/samples/sources/programmability/publisher.move anchor=use_publisher 40 | 41 | ``` 42 | 43 | ## Publisher as Admin Role 44 | 45 | For small applications or simple use cases, the Publisher object can be used as an admin 46 | [capability](./capability). While in the broader context, the Publisher object has control over 47 | system configurations, it can also be used to manage the application's state. 48 | 49 | ```move file=packages/samples/sources/programmability/publisher.move anchor=publisher_as_admin 50 | 51 | ``` 52 | 53 | However, Publisher misses some native properties of [Capabilities](./capability), such as type 54 | safety and expressiveness. The signature for the `admin_action` is not very explicit, can be called 55 | by anyone else. And due to `Publisher` object being standard, there is now a risk of unauthorized 56 | access if the `from_module` check is not performed. So it's important to be cautious when using the 57 | `Publisher` object as an admin role. 58 | 59 | ## Role on Sui 60 | 61 | Publisher is required for certain features on Sui. [Object Display](./display) can be created only 62 | by the Publisher, and TransferPolicy - an important component of the Kiosk system - also requires 63 | the Publisher object to prove ownership of the type. 64 | 65 | ## Next Steps 66 | 67 | In the next chapter we will cover the first feature that requires the Publisher object - Object 68 | Display - a way to describe objects for clients, and standardize metadata. A must-have for 69 | user-friendly applications. 70 | -------------------------------------------------------------------------------- /book/move-basics/copy-ability.md: -------------------------------------------------------------------------------- 1 | # Abilities: Copy 2 | 3 | In Move, the _copy_ ability on a type indicates that the instance or the value of the type can be 4 | copied, or duplicated. While this behavior is provided by default when working with numbers or other 5 | primitive types, it is not the default for custom types. Move is designed to express digital assets 6 | and resources, and controlling the ability to duplicate resources is a key principle of the resource 7 | model. However, the Move type system allows you to add the _copy_ ability to custom types: 8 | 9 | ```move file=packages/samples/sources/move-basics/copy-ability.move anchor=copyable 10 | 11 | ``` 12 | 13 | In the example above, we define a custom type `Copyable` with the _copy_ ability. This means that 14 | instances of `Copyable` can be copied, both implicitly and explicitly. 15 | 16 | ```move file=packages/samples/sources/move-basics/copy-ability.move anchor=copyable_test 17 | 18 | ``` 19 | 20 | In the example above, `a` is copied to `b` implicitly, and then explicitly copied to `c` using the 21 | dereference operator. If `Copyable` did not have the _copy_ ability, the code would not compile, and 22 | the Move compiler would raise an error. 23 | 24 | > Note: In Move, destructuring with empty brackets is often used to consume unused variables, 25 | > especially for types without the drop ability. This prevents compiler errors from values going out 26 | > of scope without explicit use. Also, Move requires the type name in destructuring (e.g., 27 | > `Copyable` in `let Copyable {} = a;`) because it enforces strict typing and ownership rules. 28 | 29 | ## Copying and Drop 30 | 31 | The `copy` ability is closely related to the [`drop` ability](./drop-ability). If a type has the 32 | _copy_ ability, it is very likely that it should have `drop` too. This is because the _drop_ ability 33 | is required to clean up resources when the instance is no longer needed. If a type only has _copy_, 34 | managing its instances gets more complicated, as the instances must be explicitly used or consumed. 35 | 36 | ```move file=packages/samples/sources/move-basics/copy-ability.move anchor=copy_drop 37 | 38 | ``` 39 | 40 | All of the primitive types in Move behave as if they have the _copy_ and _drop_ abilities. This 41 | means that they can be copied and dropped, and the Move compiler will handle the memory management 42 | for them. 43 | 44 | ## Types with the `copy` Ability 45 | 46 | All native types in Move have the `copy` ability. This includes: 47 | 48 | - [bool](./../move-basics/primitive-types#booleans) 49 | - [unsigned integers](./../move-basics/primitive-types#integer-types) 50 | - [vector](./../move-basics/vector) 51 | - [address](./../move-basics/address) 52 | 53 | All of the types defined in the standard library have the `copy` ability as well. This includes: 54 | 55 | - [Option](./../move-basics/option) 56 | - [String](./../move-basics/string) 57 | - [TypeName](./../move-basics/type-reflection) 58 | 59 | ## Further Reading 60 | 61 | - [Type Abilities](./../../reference/abilities) in the Move Reference. 62 | --------------------------------------------------------------------------------