├── 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 ;
7 | }
8 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/constants-naming.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_const)]
5 | module book::naming;
6 |
7 | // ANCHOR: naming
8 | /// Price of the item used at the shop.
9 | const ITEM_PRICE: u64 = 100;
10 |
11 | /// Error constant.
12 | const EItemNotFound: u64 = 1;
13 | // ANCHOR_END: naming
14 |
--------------------------------------------------------------------------------
/site/src/theme/Icon/Copy/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { type ReactNode } from 'react';
2 | import type { Props } from '@theme/Icon/Copy';
3 |
4 | /**
5 | * Replace default icon with FontAwesome icon.
6 | */
7 | export default function IconCopy(props: Props): ReactNode {
8 | return (
9 |
10 |
11 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/constants.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | module book::constants;
5 |
6 | const MAX: u64 = 100;
7 |
8 | // however you can pass constant outside using a function
9 | public fun max(): u64 {
10 | MAX
11 | }
12 |
13 | // or using
14 | public fun is_max(num: u64): bool {
15 | num == MAX
16 | }
17 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/function_use.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_variable, unused_function)]
5 | // ANCHOR: use_math
6 | module book::use_math;
7 |
8 | use book::math;
9 |
10 | fun call_add() {
11 | // function is called via the path
12 | let sum = math::add(1, 2);
13 | }
14 | // ANCHOR_END: use_math
15 |
--------------------------------------------------------------------------------
/book/before-we-begin/move-2024.md:
--------------------------------------------------------------------------------
1 | # Move 2024
2 |
3 | Move 2024 is the current edition of the Move language maintained by Mysten Labs. All of the examples
4 | in this book are written in Move 2024. If you're used to the pre-2024 version of Move, refer
5 | to the [Move 2024 Migration Guide](./../guides/2024-migration-guide.md) to learn about the changes
6 | and improvements in the new edition.
7 |
8 |
9 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/importing-modules-external.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_use)]
5 | // ANCHOR: external
6 | module book::imports;
7 |
8 | use std::string; // std = 0x1, string is a module in the standard library
9 | use sui::coin; // sui = 0x2, coin is a module in the Sui Framework
10 | // ANCHOR_END: external
11 |
--------------------------------------------------------------------------------
/reference/TODO:
--------------------------------------------------------------------------------
1 | # TODO
2 |
3 | ## Long term
4 |
5 | - Grammar examples aren't readable
6 | - We don't describe the associativity of conditionals or other control flow constructions and {}
7 | - We don't describe identifier rules in a single place
8 | - We don't describe rules for namespaces and uses
9 | - attributes/annotations in general
10 | - describe paths/places more like the compiler thinks about them in 2024
11 |
--------------------------------------------------------------------------------
/book/appendix/acknowledgements.md:
--------------------------------------------------------------------------------
1 | # Appendix F: Acknowledgements
2 |
3 | [The Rust Book](https://doc.rust-lang.org/book) has been a great inspiration for this book. I am
4 | personally grateful to the authors of the book, Steve Klabnik and Carol Nichols, for their work, as
5 | I have learned a lot from it. This book is a small tribute to their work and an attempt to bring a
6 | similar learning experience to the Move community.
7 |
--------------------------------------------------------------------------------
/book/before-we-begin/index.md:
--------------------------------------------------------------------------------
1 | # Before We Begin
2 |
3 | Move requires an environment to run and develop applications, and in this small chapter we will
4 | cover the prerequisites for the Move language: how to set up your IDE, how to install the compiler
5 | and what is Move 2024. If you are already familiar with these topics or have a CLI installed, you
6 | can skip this chapter and proceed to [the next one](../your-first-move/hello-world.md).
7 |
--------------------------------------------------------------------------------
/packages/samples/sources/programmability/transaction-context.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_variable)]
5 | module book::transaction_context;
6 |
7 | // ANCHOR: reading
8 | public fun some_action(ctx: &TxContext) {
9 | let me = ctx.sender();
10 | let epoch = ctx.epoch();
11 | let digest = ctx.digest();
12 | // ...
13 | }
14 | // ANCHOR_END: reading
15 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/importing-modules.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_use)]
5 | // ANCHOR: module_one
6 | module book::module_one;
7 |
8 | /// Struct defined in the same module.
9 | public struct Character has drop {}
10 |
11 | /// Simple function that creates a new `Character` instance.
12 | public fun new(): Character { Character {} }
13 | // ANCHOR_END: module_one
14 |
--------------------------------------------------------------------------------
/site/src/theme/CodeInline/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { type ReactNode } from 'react';
2 | import type { Props } from '@theme/CodeInline';
3 |
4 | // Simple component used to render inline code blocks
5 | // its purpose is to be swizzled and customized
6 | // MDX 1 used to have a inlineCode comp, see https://mdxjs.com/migrating/v2/
7 | export default function CodeInline(props: Props): ReactNode {
8 | return ;
9 | }
10 |
--------------------------------------------------------------------------------
/book/concepts/index.md:
--------------------------------------------------------------------------------
1 | # Concepts
2 |
3 | In this chapter you will learn about the basic concepts of Sui and Move. You will learn what is a
4 | package, how to interact with it, what is an account and a transaction, and how data is stored on
5 | Sui. While this chapter is not a complete reference, and you should refer to the
6 | [Sui Documentation](https://docs.sui.io) for that, it will give you a good understanding of the
7 | basic concepts required to write Move programs on Sui.
8 |
--------------------------------------------------------------------------------
/packages/hello_world/sources/hello_world.move:
--------------------------------------------------------------------------------
1 | // ANCHOR: source
2 | /// The module `hello_world` under named address `hello_world`.
3 | /// The named address is set in the `Move.toml`.
4 | module hello_world::hello_world;
5 |
6 | // Imports the `String` type from the Standard Library
7 | use std::string::String;
8 |
9 | /// Returns the "Hello World!" as a `String`.
10 | public fun hello_world(): String {
11 | b"Hello, World!".to_string()
12 | }
13 | // ANCHOR_END: source
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/importing-modules-two.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_use)]
5 | // ANCHOR: module_two
6 | module book::module_two;
7 |
8 | use book::module_one; // importing module_one from the same package
9 |
10 | /// Calls the `new` function from the `module_one` module.
11 | public fun create_and_ignore() {
12 | let _ = module_one::new();
13 | }
14 | // ANCHOR_END: module_two
15 |
--------------------------------------------------------------------------------
/packages/samples/sources/programmability/module-initializer-2.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // ANCHOR: other
5 | // In the same package as the `shop` module
6 | module book::bank;
7 |
8 | public struct Bank has key {
9 | id: UID,
10 | /* ... */
11 | }
12 |
13 | fun init(ctx: &mut TxContext) {
14 | transfer::share_object(Bank {
15 | id: object::new(ctx)
16 | });
17 | }
18 | // ANCHOR_END: other
19 |
--------------------------------------------------------------------------------
/packages/samples/sources/your-first-move/hello_world.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | module book::hello_world;
5 |
6 | use std::string::String;
7 |
8 | public fun hello_world(): String {
9 | b"Hello, World!".to_string()
10 | }
11 |
12 | #[test_only]
13 | use std::unit_test::assert_eq;
14 |
15 | #[test]
16 | fun test_is_hello_world() {
17 | let expected = b"Hello, World!".to_string();
18 | assert_eq!(hello_world(), expected);
19 | }
20 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/importing-modules-self.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_use)]
5 | // ANCHOR: self
6 | module book::self_imports;
7 |
8 | // imports the `Character` struct, and the `module_one` module
9 | use book::module_one::{Self, Character};
10 |
11 | /// Calls the `new` function from the `module_one` module.
12 | public fun create_character(): Character {
13 | module_one::new()
14 | }
15 | // ANCHOR_END: self
16 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/comments-line.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_function, unused_variable)]
5 | // ANCHOR: main
6 | module book::comments_line;
7 |
8 | // let's add a note to everything!
9 | fun some_function_with_numbers() {
10 | let a = 10;
11 | // let b = 10 this line is commented and won't be executed
12 | let b = 5; // here comment is placed after code
13 | a + b; // result is 15, not 10!
14 | }
15 | // ANCHOR_END: main
16 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/importing-modules-conflict-resolution.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_use)]
5 | // ANCHOR: conflict
6 | module book::conflict_resolution;
7 |
8 | // `as` can be placed after any import, including group imports
9 | use book::module_one::{Self as mod, Character as Char};
10 |
11 | /// Calls the `new` function from the `module_one` module.
12 | public fun create(): Char {
13 | mod::new()
14 | }
15 | // ANCHOR_END: conflict
16 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/importing-modules-grouped.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_use)]
5 | // ANCHOR: grouped
6 | module book::grouped_imports;
7 |
8 | // imports the `new` function and the `Character` struct from
9 | // the `module_one` module
10 | use book::module_one::{new, Character};
11 |
12 | /// Calls the `new` function from the `module_one` module.
13 | public fun create_character(): Character {
14 | new()
15 | }
16 | // ANCHOR_END: grouped
17 |
--------------------------------------------------------------------------------
/book/appendix/publications.md:
--------------------------------------------------------------------------------
1 | # Appendix D: Publications
2 |
3 | This section lists publications related to Move and Sui.
4 |
5 | - [The Move Borrow Checker](https://arxiv.org/abs/2205.05181) by Sam Blackshear, John Mitchell, Todd
6 | Nowacki, Shaz Qadeer.
7 | - [Resources: A Safe Language Abstraction for Money](https://arxiv.org/abs/2004.05106) by Sam
8 | Blackshear, David L. Dill, Shaz Qadeer, Clark W. Barrett, John C. Mitchell, Oded Padon, Yoni
9 | Zohar.
10 | - [Robust Safety for Move](https://arxiv.org/abs/2110.05043) by Marco Patrignani, Sam Blackshear
11 |
--------------------------------------------------------------------------------
/book/storage/index.md:
--------------------------------------------------------------------------------
1 | # Using Objects
2 |
3 | In the [Object Model][object-model] chapter, we introduced the shift in the Move language from an
4 | account-based model to an object-based one. This chapter takes a closer look at that model. You’ll
5 | learn how objects work and how to put them to use in your Sui applications.
6 |
7 | If you haven’t read the [Object Model][object-model] chapter yet, we recommend starting there before
8 | continuing.
9 |
10 | [object-model]: ./../object
11 |
12 |
13 |
--------------------------------------------------------------------------------
/book/programmability/index.md:
--------------------------------------------------------------------------------
1 | # Advanced Programmability
2 |
3 | In previous chapters we've covered [the basics of Move](./../move-basics) and
4 | [Sui Storage Model](./../storage). Now it's time to dive deeper into the advanced topics of Sui
5 | programmability.
6 |
7 | This chapter introduces more complex concepts, practices and features of Move and Sui that are
8 | essential for building more sophisticated applications. It is intended for developers who are
9 | already familiar with the basics of Move and Sui, and are looking to expand their knowledge and
10 | skills.
11 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/comments-block.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_function)]
5 | // ANCHOR: main
6 | module book::comments_block;
7 |
8 | fun /* you can comment everywhere */ go_wild() {
9 | /* here
10 | there
11 | everywhere */ let a = 10;
12 | let b = /* even here */ 10; /* and again */
13 | a + b;
14 | }
15 | /* you can use it to remove certain expressions or definitions
16 | fun empty_commented_out() {
17 |
18 | }
19 | */
20 | // ANCHOR_END: main
21 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/constants-config.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // ANCHOR: config
5 | module book::config;
6 |
7 | const ITEM_PRICE: u64 = 100;
8 | const TAX_RATE: u64 = 10;
9 | const SHIPPING_COST: u64 = 5;
10 |
11 | /// Returns the price of an item.
12 | public fun item_price(): u64 { ITEM_PRICE }
13 | /// Returns the tax rate.
14 | public fun tax_rate(): u64 { TAX_RATE }
15 | /// Returns the shipping cost.
16 | public fun shipping_cost(): u64 { SHIPPING_COST }
17 | // ANCHOR_END: config
18 |
--------------------------------------------------------------------------------
/book/move-basics/index.md:
--------------------------------------------------------------------------------
1 | # Move Basics
2 |
3 | This chapter is all about the basic syntax of the Move language. It covers the basics of the
4 | language, such as types, modules, functions, and control flow. It focuses on the language without a
5 | storage model or a blockchain, and explains the essential concepts of the language. To learn
6 | features specific to Sui, such as storage functions and abilities, refer to the
7 | [Using Objects](./../storage/) chapter, however, it is recommended to start with this chapter first.
8 |
9 |
10 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/module-members.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_function, unused_const, unused_use)]
5 | // ANCHOR: members
6 | module book::my_module_with_members;
7 |
8 | // import
9 | use book::my_module;
10 |
11 | // a constant
12 | const CONST: u8 = 0;
13 |
14 | // a struct
15 | public struct Struct {}
16 |
17 | // method alias
18 | public use fun function as Struct.struct_fun;
19 |
20 | // function
21 | fun function(_: &Struct) { /* function body */ }
22 | // ANCHOR_END: members
23 |
--------------------------------------------------------------------------------
/packages/samples/sources/programmability/collections.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_variable, unused_field)]
5 | // ANCHOR: vector
6 | module book::collections_vector;
7 |
8 | use std::string::String;
9 |
10 | /// The Book that can be sold by a `BookStore`
11 | public struct Book has key, store {
12 | id: UID,
13 | name: String
14 | }
15 |
16 | /// The BookStore that sells `Book`s
17 | public struct BookStore has key, store {
18 | id: UID,
19 | books: vector
20 | }
21 | // ANCHOR_END: vector
22 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/importing-modules-members.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_use)]
5 | // ANCHOR: members
6 | module book::more_imports;
7 |
8 | use book::module_one::new; // imports the `new` function from the `module_one` module
9 | use book::module_one::Character; // importing the `Character` struct from the `module_one` module
10 |
11 | /// Calls the `new` function from the `module_one` module.
12 | public fun create_character(): Character {
13 | new()
14 | }
15 | // ANCHOR_END: members
16 |
--------------------------------------------------------------------------------
/packages/samples/sources/programmability/capability-4.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | module book::cap_vs_addr;
5 |
6 | public struct User has key, store { id: UID }
7 |
8 | // ANCHOR: with_capability
9 | /// Grants the owner the right to create new users in the system.
10 | public struct AdminCap {}
11 |
12 | /// Creates a new user in the system. Requires the `AdminCap` capability to be
13 | /// passed as the first argument.
14 | public fun new(_: &AdminCap, ctx: &mut TxContext): User {
15 | User { id: object::new(ctx) }
16 | }
17 | // ANCHOR_END: with_capability
18 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/comments-doc.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_function, unused_const, unused_variable, unused_field)]
5 | // ANCHOR: main
6 | /// Module has documentation!
7 | module book::comments_doc;
8 |
9 | /// This is a 0x0 address constant!
10 | const AN_ADDRESS: address = @0x0;
11 |
12 | /// This is a struct!
13 | public struct AStruct {
14 | /// This is a field of a struct!
15 | a_field: u8,
16 | }
17 |
18 | /// This function does something!
19 | /// And it's documented!
20 | fun do_something() {}
21 | // ANCHOR_END: main
22 |
--------------------------------------------------------------------------------
/packages/samples/sources/your-first-move/hello_world_debug.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | module book::hello_world_debug;
5 |
6 | use std::string::String;
7 | use std::debug;
8 |
9 | public fun hello_world(): String {
10 | let result = b"Hello, World!".to_string();
11 | debug::print(&result);
12 | result
13 | }
14 |
15 | #[test_only]
16 | use std::unit_test::assert_eq;
17 |
18 | #[test]
19 | fun test_is_hello_world() {
20 | let expected = b"Hello, World!".to_string();
21 | let actual = hello_world();
22 |
23 | assert_eq!(actual, expected);
24 | }
25 |
--------------------------------------------------------------------------------
/book/index.md:
--------------------------------------------------------------------------------
1 | # The Move Book
2 |
3 |
4 |
5 | This is The Move Book - a comprehensive guide to the Move programming language and the Sui
6 | blockchain. The book is intended for developers who are interested in learning about Move and
7 | building on Sui.
8 |
9 |
10 |
11 | The book is in active development and a work in progress. If you have any feedback or suggestions,
12 | feel free to open an issue or a pull request on the
13 | [GitHub repository](https://github.com/MystenLabs/move-book).
14 |
15 |
16 |
17 | > If you're looking for The Move Reference, you can find it [here](/reference).
18 |
--------------------------------------------------------------------------------
/packages/samples/sources/programmability/capability-2.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // ANCHOR: admin_cap
5 | module book::admin_cap;
6 |
7 | /// The capability granting the admin privileges in the system.
8 | /// Created only once in the `init` function.
9 | public struct AdminCap has key { id: UID }
10 |
11 | /// Create the AdminCap object on package publish and transfer it to the
12 | /// package owner.
13 | fun init(ctx: &mut TxContext) {
14 | transfer::transfer(
15 | AdminCap { id: object::new(ctx) },
16 | ctx.sender()
17 | )
18 | }
19 | // ANCHOR_END: admin_cap
20 |
--------------------------------------------------------------------------------
/book/404.md:
--------------------------------------------------------------------------------
1 | # Page not Found
2 |
3 | You're looking for a page that doesn't exist, or has been moved. Please check the URL and try again.
4 |
5 | > Here are the links you may be looking for:
6 | >
7 | > - [The Move Book](/) - the main page of the book
8 | > - [The Move Reference](/reference) - the Move Language Reference
9 |
10 | Recently we updated the structure of the book and some pages have been moved or renamed. If you're
11 | looking for the old version of the book, please, see the
12 | ["archive" branch in the repository](https://github.com/MystenLabs/move-book/tree/archive). Though
13 | we highly recommend using [the latest version of the book](/).
14 |
--------------------------------------------------------------------------------
/packages/samples/sources/programmability/collections-4.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_use, lint(collection_equality))]
5 | module book::collections_compare_vec_set;
6 |
7 | use sui::vec_set;
8 |
9 | #[test_only]
10 | use std::unit_test::assert_eq;
11 |
12 | #[test, expected_failure]
13 | fun test_compare() {
14 | // ANCHOR: vec_set_comparison
15 | let mut set1 = vec_set::empty();
16 | set1.insert(1);
17 | set1.insert(2);
18 |
19 | let mut set2 = vec_set::empty();
20 | set2.insert(2);
21 | set2.insert(1);
22 |
23 | assert_eq!(set1, set2); // aborts!
24 | // ANCHOR_END: vec_set_comparison
25 | }
26 |
--------------------------------------------------------------------------------
/site/src/theme/Icon/Image/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { type ReactNode } from 'react';
2 | import type { Props } from '@theme/Icon/Copy';
3 |
4 | /**
5 | * Replace default icon with FontAwesome icon.
6 | */
7 | export default function IconImage(props: Props): ReactNode {
8 | return (
9 |
10 |
11 |
12 | //
13 | //
17 | //
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/reference/primitive-types.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Primitive Types | Reference'
3 | description: ''
4 | ---
5 |
6 | # Primitive Types
7 |
8 | The primitive types are the basic building blocks of the language.
9 |
10 | These primitive types can be used on their own or can be used to build more complex,
11 | user-defined types, e.g. in a [`struct`](./structs).
12 |
13 | - [Integers](./primitive-types/integers)
14 | - [Bool](./primitive-types/bool)
15 | - [Address](./primitive-types/address)
16 | - [Vector](./primitive-types/vector)
17 |
18 | These primitive types are used in conjunction with other types
19 |
20 | - [References](./primitive-types/references)
21 | - [Tuples and Unit](./primitive-types/tuples)
22 |
--------------------------------------------------------------------------------
/packages/samples/sources/programmability/capability-3.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | module book::addr_vs_cap;
5 |
6 | public struct User has key, store { id: UID }
7 |
8 | // ANCHOR: with_address
9 | /// Error code for unauthorized access.
10 | const ENotAuthorized: u64 = 0;
11 |
12 | /// The application admin address.
13 | const APPLICATION_ADMIN: address = @0xa11ce;
14 |
15 | /// Creates a new user in the system. Requires the sender to be the application
16 | /// admin.
17 | public fun new(ctx: &mut TxContext): User {
18 | assert!(ctx.sender() == APPLICATION_ADMIN, ENotAuthorized);
19 | User { id: object::new(ctx) }
20 | }
21 | // ANCHOR_END: with_address
22 |
23 |
--------------------------------------------------------------------------------
/book/object/index.md:
--------------------------------------------------------------------------------
1 | # Object Model
2 |
3 | This chapter describes the Object Model of Sui. It focuses on the theory and concepts behind the
4 | Object Model, preparing you for a practical dive into Sui Storage operations and resource ownership.
5 | For convenience and easier lookup, we split the chapter into several sections, each covering a
6 | specific aspect of the Object Model.
7 |
8 |
9 |
10 | In no way should this chapter be considered a comprehensive guide to the Object Model. It is only a
11 | high-level overview of the concepts and principles behind the Object Model.
12 |
13 | For a more detailed description, refer to the
14 | [Sui Documentation](https://docs.sui.io/concepts/object-model).
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/samples/sources/your-first-move/hello_world_docs.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | /// This module contains a function that returns a string "Hello, World!".
5 | module book::hello_world_docs;
6 |
7 | use std::string::String;
8 |
9 | /// As the name says: returns a string "Hello, World!".
10 | public fun hello_world(): String {
11 | b"Hello, World!".to_string()
12 | }
13 |
14 | #[test_only]
15 | use std::unit_test::assert_eq;
16 |
17 | #[test]
18 | /// This is a test for the `hello_world` function.
19 | fun test_is_hello_world() {
20 | let expected = b"Hello, World!".to_string();
21 | let actual = hello_world();
22 |
23 | assert_eq!(actual, expected);
24 | }
25 |
--------------------------------------------------------------------------------
/book/appendix/reserved-addresses.md:
--------------------------------------------------------------------------------
1 | # Appendix B: Reserved Addresses
2 |
3 | Reserved addresses are special addresses that have a specific purpose on Sui. They stay the same
4 | between environments and are used for specific native operations.
5 |
6 | - `0x1` - address of the [Standard Library](./../move-basics/standard-library.md) (alias `std`)
7 | - `0x2` - address of the [Sui Framework](./../programmability/sui-framework.md) (alias `sui`)
8 | - `0x5` - address of the `SuiSystem` object
9 | - `0x6` - address of the system [`Clock` object](./../programmability/epoch-and-time.md)
10 | - `0x8` - address of the system `Random` object
11 | - `0xc` - address of the system `CoinRegistry` object
12 | - `0x403` - address of the `DenyList` system object
13 |
--------------------------------------------------------------------------------
/reference/control-flow.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Control Flow | Reference'
3 | description: ''
4 | ---
5 |
6 | # Control Flow
7 |
8 | Move offers multiple constructs for control flow based on
9 | [boolean expressions](./primitive-types/bool), including common programming constructs such as `if`
10 | expressions and `while` and `for` loops, along with advanced control flow structures including
11 | labels for loops and escapable named blocks. It also supports more complex constructs based on
12 | structural pattern matching.
13 |
14 | - [Conditional Expressions](./control-flow/conditionals)
15 | - [Pattern Matching](./control-flow/pattern-matching)
16 | - [Loops](./control-flow/loops)
17 | - [Labeled Control FLow](./control-flow/labeled-control-flow)
18 |
--------------------------------------------------------------------------------
/packages/reference/sources/abilities.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_field)]
5 | module ref::abilities {
6 |
7 | // ANCHOR: annotating_datatypes
8 | public struct Ignorable has drop { f: u64 }
9 | public struct Pair has copy, drop, store { x: u64, y: u64 }
10 | public struct MyVec(vector) has copy, drop, store;
11 |
12 | public enum IgnorableEnum has drop { Variant }
13 | public enum PairEnum has copy, drop, store { Variant }
14 | public enum MyVecEnum { Variant } has copy, drop, store;
15 | // ANCHOR_END: annotating_datatypes
16 |
17 | // ANCHOR: conditional_abilities
18 | // public struct Cup has copy, drop, store, key { item: T }
19 | // ANCHOR_END: conditional_abilities
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/reference/index.md:
--------------------------------------------------------------------------------
1 | # The Move Reference
2 |
3 | Welcome to Move, a next generation language for secure asset programming. Its primary use case is in
4 | blockchain environments, where Move programs are used to construct state changes. Move allows
5 | developers to write programs that flexibly manage and transfer assets, while providing the security
6 | and protections against attacks on those assets. However, Move has been developed with use cases in
7 | mind outside a blockchain context as well.
8 |
9 | Move takes its cue from [Rust](https://www.rust-lang.org/) by using resource types with move (hence
10 | the name) semantics as an explicit representation of digital assets, such as currency.
11 |
12 |
13 |
--------------------------------------------------------------------------------
/site/src/theme/ColorModeToggle/styles.module.css:
--------------------------------------------------------------------------------
1 | .toggle {
2 | width: 2rem;
3 | height: 2rem;
4 | }
5 |
6 | .toggleButton {
7 | -webkit-tap-highlight-color: transparent;
8 | align-items: center;
9 | display: flex;
10 | justify-content: center;
11 | width: 100%;
12 | height: 100%;
13 | border-radius: 50%;
14 | transition: background var(--ifm-transition-fast);
15 | }
16 |
17 | .toggleButton:hover {
18 | background: var(--ifm-color-emphasis-200);
19 | }
20 |
21 | .toggleIcon {
22 | display: none;
23 | }
24 |
25 | [data-theme-choice='system'] .systemToggleIcon,
26 | [data-theme-choice='light'] .lightToggleIcon,
27 | [data-theme-choice='dark'] .darkToggleIcon {
28 | display: initial;
29 | }
30 |
31 | .toggleButtonDisabled {
32 | cursor: not-allowed;
33 | }
34 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/drop-ability.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // ANCHOR: main
5 | module book::drop_ability;
6 |
7 | /// This struct has the `drop` ability.
8 | public struct IgnoreMe has drop {
9 | a: u8,
10 | b: u8,
11 | }
12 |
13 | /// This struct does not have the `drop` ability.
14 | public struct NoDrop {}
15 |
16 | #[test]
17 | // Create an instance of the `IgnoreMe` struct and ignore it.
18 | // Even though we constructed the instance, we don't need to unpack it.
19 | fun test_ignore() {
20 | let no_drop = NoDrop {};
21 | let _ = IgnoreMe { a: 1, b: 2 }; // no need to unpack
22 |
23 | // The value must be unpacked for the code to compile.
24 | let NoDrop {} = no_drop; // OK
25 | }
26 | // ANCHOR_END: main
27 |
--------------------------------------------------------------------------------
/.github/actions/diffs/action.yml:
--------------------------------------------------------------------------------
1 | name: Detect Changes
2 | description: Defines variables indicating the parts of the code that changed
3 | outputs:
4 | isDoc:
5 | description: True when changes happened to some documentation
6 | value: "${{ steps.diff.outputs.isDoc }}"
7 | isMove:
8 | description: True when changes happened to the Move code
9 | value: "${{ steps.diff.outputs.isMove }}"
10 |
11 | runs:
12 | using: composite
13 | steps:
14 | - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # Pin v4.1.1
15 | - name: Detect Changes
16 | uses: dorny/paths-filter@v2.10.2
17 | id: diff
18 | with:
19 | filters: |
20 | isDoc:
21 | - 'src/'
22 | - '.github/workflows/docs.yml'
23 | isMove:
24 | - 'samples/'
25 | - 'postcard/'
26 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/constants-shop-price.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // ANCHOR: shop_price
5 | module book::shop_price;
6 |
7 | use sui::{coin::Coin, sui::SUI};
8 |
9 | /// Trying to purchase an item at an incorrect price.
10 | const EWrongPrice: u64 = 0;
11 |
12 | /// The price of an item in the shop.
13 | const ITEM_PRICE: u64 = 100;
14 | /// The owner of the shop, an address.
15 | const SHOP_OWNER: address = @0xa11ce;
16 |
17 | /// An item sold in the shop.
18 | public struct Item {}
19 |
20 | /// Purchase an item from the shop.
21 | public fun purchase(coin: Coin): Item {
22 | assert!(coin.value() == ITEM_PRICE, EWrongPrice);
23 |
24 | transfer::public_transfer(coin, SHOP_OWNER);
25 |
26 | Item {}
27 | }
28 | // ANCHOR_END: shop_price
29 |
--------------------------------------------------------------------------------
/site/src/theme/CodeBlock/Buttons/styles.module.css:
--------------------------------------------------------------------------------
1 | .buttonGroup {
2 | display: flex;
3 | column-gap: 0.2rem;
4 | position: absolute;
5 | /* rtl:ignore */
6 | right: calc(var(--ifm-pre-padding) / 2);
7 | top: calc(var(--ifm-pre-padding) / 2);
8 | }
9 |
10 | .buttonGroup button {
11 | display: flex;
12 | align-items: center;
13 | background: var(--prism-background-color);
14 | color: var(--prism-color);
15 | border: 1px solid var(--ifm-color-emphasis-300);
16 | border-radius: var(--ifm-global-radius);
17 | padding: 0.4rem;
18 | line-height: 0;
19 | transition: opacity var(--ifm-transition-fast) ease-in-out;
20 | opacity: 0;
21 | }
22 |
23 | .buttonGroup button:focus-visible,
24 | .buttonGroup button:hover {
25 | opacity: 1 !important;
26 | }
27 |
28 | :global(.theme-code-block:hover) .buttonGroup button {
29 | opacity: 0.4;
30 | }
31 |
--------------------------------------------------------------------------------
/packages/reference/Move.lock:
--------------------------------------------------------------------------------
1 | # @generated by Move, please check-in and do not edit manually.
2 |
3 | [move]
4 | version = 2
5 | manifest_digest = "868EC315260CC0A203EABE09C39C72CFDDB66DE119BDF7E24CE5EAABE30EFCC1"
6 | deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082"
7 | dependencies = [
8 | { name = "Sui" },
9 | ]
10 |
11 | [[move.package]]
12 | name = "MoveStdlib"
13 | source = { git = "https://github.com/MystenLabs/sui.git", rev = "main", subdir = "crates/sui-framework/packages/move-stdlib" }
14 |
15 | [[move.package]]
16 | name = "Sui"
17 | source = { git = "https://github.com/MystenLabs/sui.git", rev = "main", subdir = "crates/sui-framework/packages/sui-framework" }
18 |
19 | dependencies = [
20 | { name = "MoveStdlib" },
21 | ]
22 |
23 | [move.toolchain-version]
24 | compiler-version = "1.27.0"
25 | edition = "2024.alpha"
26 | flavor = "sui"
27 |
--------------------------------------------------------------------------------
/packages/hello_world/Move.lock:
--------------------------------------------------------------------------------
1 | # @generated by Move, please check-in and do not edit manually.
2 |
3 | [move]
4 | version = 1
5 | manifest_digest = "60F2000F4D6DAD240EF371DB3BC521F7BD4C8B814BC59CA473B852B77FDBE53C"
6 | deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082"
7 | dependencies = [
8 | { name = "Sui" },
9 | ]
10 |
11 | [[move.package]]
12 | name = "MoveStdlib"
13 | source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/testnet", subdir = "crates/sui-framework/packages/move-stdlib" }
14 |
15 | [[move.package]]
16 | name = "Sui"
17 | source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/testnet", subdir = "crates/sui-framework/packages/sui-framework" }
18 |
19 | dependencies = [
20 | { name = "MoveStdlib" },
21 | ]
22 |
23 | [move.toolchain-version]
24 | compiler-version = "1.23.0"
25 | edition = "legacy"
26 | flavor = "sui"
27 |
--------------------------------------------------------------------------------
/packages/samples/sources/programmability/collections-3.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_field, unused_variable, unused_use)]
5 | // ANCHOR: vec_map
6 | module book::collections_vec_map;
7 |
8 | use std::string::String;
9 | use sui::vec_map::{Self, VecMap};
10 |
11 | public struct Metadata has drop {
12 | name: String,
13 | /// `VecMap` used in the struct definition
14 | attributes: VecMap
15 | }
16 |
17 | #[test]
18 | fun vec_map_playground() {
19 | let mut map = vec_map::empty(); // create an empty map
20 |
21 | map.insert(2, b"two".to_string()); // add a key-value pair to the map
22 | map.insert(3, b"three".to_string());
23 |
24 | assert!(map.contains(&2)); // check if a key is in the map
25 |
26 | map.remove(&2); // remove a key-value pair from the map
27 | }
28 | // ANCHOR_END: vec_map
29 |
--------------------------------------------------------------------------------
/packages/samples/sources/programmability/one-time-witness.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_variable, unused_mut_parameter)]
5 | // ANCHOR: definition
6 | module book::one_time;
7 |
8 | /// The OTW for the `book::one_time` module.
9 | /// Only `drop`, no fields, no generics, all uppercase.
10 | public struct ONE_TIME has drop {}
11 |
12 | /// Receive the instance of `ONE_TIME` as the first argument.
13 | fun init(otw: ONE_TIME, ctx: &mut TxContext) {
14 | // do something with the OTW
15 | }
16 | // ANCHOR_END: definition
17 |
18 | // ANCHOR: usage
19 | use sui::types;
20 |
21 | const ENotOneTimeWitness: u64 = 1;
22 |
23 | /// Takes an OTW as an argument, aborts if the type is not OTW.
24 | public fun takes_witness(otw: T) {
25 | assert!(types::is_one_time_witness(&otw), ENotOneTimeWitness);
26 | }
27 | // ANCHOR_END: usage
28 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/copy-ability.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_variable)]
5 | module book::copy_ability;
6 |
7 | // ANCHOR: copyable
8 | public struct Copyable has copy {}
9 | // ANCHOR_END: copyable
10 |
11 | #[test] fun test_copy() {
12 |
13 | // ANCHOR: copyable_test
14 | let a = Copyable {}; // allowed because the Copyable struct has the `copy` ability
15 | let b = a; // `a` is copied to `b`
16 | let c = *&b; // explicit copy via dereference operator
17 |
18 | // Copyable doesn't have the `drop` ability, so every instance (a, b, and c) must
19 | // be used or explicitly destructured. The `drop` ability is explained below.
20 | let Copyable {} = a;
21 | let Copyable {} = b;
22 | let Copyable {} = c;
23 | // ANCHOR_END: copyable_test
24 | }
25 |
26 | // ANCHOR: copy_drop
27 | public struct Value has copy, drop {}
28 | // ANCHOR_END: copy_drop
29 |
--------------------------------------------------------------------------------
/site/src/theme/CodeBlock/Buttons/CopyButton/styles.module.css:
--------------------------------------------------------------------------------
1 | :global(.theme-code-block:hover) .copyButtonCopied {
2 | opacity: 1 !important;
3 | }
4 |
5 | .copyButtonIcons {
6 | position: relative;
7 | width: 1.125rem;
8 | height: 1.125rem;
9 | }
10 |
11 | .copyButtonIcon,
12 | .copyButtonSuccessIcon {
13 | position: absolute;
14 | top: 0;
15 | left: 0;
16 | fill: currentColor;
17 | opacity: inherit;
18 | width: inherit;
19 | height: inherit;
20 | transition: all var(--ifm-transition-fast) ease;
21 | }
22 |
23 | .copyButtonSuccessIcon {
24 | top: 50%;
25 | left: 50%;
26 | transform: translate(-50%, -50%) scale(0.33);
27 | opacity: 0;
28 | color: #00d600;
29 | }
30 |
31 | .copyButtonCopied .copyButtonIcon {
32 | transform: scale(0.33);
33 | opacity: 0;
34 | }
35 |
36 | .copyButtonCopied .copyButtonSuccessIcon {
37 | transform: translate(-50%, -50%) scale(1);
38 | opacity: 1;
39 | transition-delay: 0.075s;
40 | }
41 |
--------------------------------------------------------------------------------
/packages/samples/sources/programmability/module-initializer.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // ANCHOR: main
5 | module book::shop;
6 |
7 | /// The Capability which grants the Shop owner the right to manage
8 | /// the shop.
9 | public struct ShopOwnerCap has key, store { id: UID }
10 |
11 | /// The singular Shop itself, created in the `init` function.
12 | public struct Shop has key {
13 | id: UID,
14 | /* ... */
15 | }
16 |
17 | // Called only once, upon module publication. It must be
18 | // private to prevent external invocation.
19 | fun init(ctx: &mut TxContext) {
20 | // Transfers the ShopOwnerCap to the sender (publisher).
21 | transfer::transfer(ShopOwnerCap {
22 | id: object::new(ctx)
23 | }, ctx.sender());
24 |
25 | // Shares the Shop object.
26 | transfer::share_object(Shop {
27 | id: object::new(ctx)
28 | });
29 | }
30 | // ANCHOR_END: main
31 |
--------------------------------------------------------------------------------
/site/src/theme/CodeBlock/Buttons/RenderButton/styles.module.css:
--------------------------------------------------------------------------------
1 | :global(.theme-code-block:hover) .copyButtonCopied {
2 | opacity: 1 !important;
3 | }
4 |
5 | .copyButtonIcons {
6 | position: relative;
7 | width: 1.125rem;
8 | height: 1.125rem;
9 | }
10 |
11 | .copyButtonIcon,
12 | .copyButtonSuccessIcon {
13 | position: absolute;
14 | top: 0;
15 | left: 0;
16 | fill: currentColor;
17 | opacity: inherit;
18 | width: inherit;
19 | height: inherit;
20 | transition: all var(--ifm-transition-fast) ease;
21 | }
22 |
23 | .copyButtonSuccessIcon {
24 | top: 50%;
25 | left: 50%;
26 | transform: translate(-50%, -50%) scale(0.33);
27 | opacity: 0;
28 | color: #00d600;
29 | }
30 |
31 | .copyButtonCopied .copyButtonIcon {
32 | transform: scale(0.33);
33 | opacity: 0;
34 | }
35 |
36 | .copyButtonCopied .copyButtonSuccessIcon {
37 | transform: translate(-50%, -50%) scale(1);
38 | opacity: 1;
39 | transition-delay: 0.075s;
40 | }
41 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/struct-methods-3.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // ANCHOR: hero_to_bytes
5 | // TODO: better example (external module...)
6 | module book::hero_to_bytes;
7 |
8 | // Alias for the `bcs::to_bytes` method. Imported aliases should be defined
9 | // in the top of the module.
10 | // public use fun bcs::to_bytes as Hero.to_bytes;
11 |
12 | /// A struct representing a hero.
13 | public struct Hero has drop {
14 | health: u8,
15 | mana: u8,
16 | }
17 |
18 | /// Create a new Hero.
19 | public fun new(): Hero { Hero { health: 100, mana: 100 } }
20 |
21 | // #[test_only]
22 | // use std::unit_test::assert_eq;
23 |
24 | #[test]
25 | // Test the methods of the `Hero` struct.
26 | fun test_hero_serialize() {
27 | // let mut hero = new();
28 | // let serialized = hero.to_bytes();
29 | // assert_eq!(serialized.length(), 3);
30 | }
31 | // ANCHOR_END: hero_to_bytes
32 |
--------------------------------------------------------------------------------
/site/README.md:
--------------------------------------------------------------------------------
1 | # Website
2 |
3 | This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
4 |
5 | ## Installation
6 |
7 | ```bash
8 | yarn
9 | ```
10 |
11 | ## Local Development
12 |
13 | ```bash
14 | yarn start
15 | ```
16 |
17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
18 |
19 | ## Build
20 |
21 | ```bash
22 | yarn build
23 | ```
24 |
25 | This command generates static content into the `build` directory and can be served using any static contents hosting service.
26 |
27 | ## Deployment
28 |
29 | Using SSH:
30 |
31 | ```bash
32 | USE_SSH=true yarn deploy
33 | ```
34 |
35 | Not using SSH:
36 |
37 | ```bash
38 | GIT_USER= yarn deploy
39 | ```
40 |
41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
42 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/module.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // ANCHOR: address_literal
5 | module 0x0::address_literal { /* ... */ }
6 | module book::named_address { /* ... */ }
7 | // ANCHOR_END: address_literal
8 |
9 | #[allow(unused_function, unused_const, unused_use)]
10 | // ANCHOR: members
11 | module book::my_block_module_with_members {
12 | // import
13 | use book::my_module;
14 |
15 | // a constant
16 | const CONST: u8 = 0;
17 |
18 | // a struct
19 | public struct Struct {}
20 |
21 | // method alias
22 | public use fun function as Struct.struct_fun;
23 |
24 | // function
25 | fun function(_: &Struct) { /* function body */ }
26 | }
27 |
28 | // module block allows multiple module definitions in the
29 | // same file but this is not a recommended practice
30 | module book::another_module_in_the_file {
31 | // ...
32 | }
33 | // ANCHOR_END: members
34 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Run tests for Move packages
2 | permissions:
3 | contents: read
4 |
5 | # Set the VERSION variable to use when downloading the binary
6 | # Currently, requires explicit setup, ideally it should be fetched
7 | # automatically
8 | # env:
9 | # VERSION: 'v1.24.1'
10 |
11 | on:
12 | pull_request:
13 |
14 | jobs:
15 | download-binary:
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Download Sui
20 | uses: jaxxstorm/action-install-gh-release@v1.12.0
21 | with:
22 | repo: MystenLabs/sui
23 | platform: ubuntu
24 | version: main
25 | cache: enable
26 |
27 | # Run the tests in every directory using the latest mainnet binary
28 | - run: sui move test --path packages/samples
29 | - run: sui move test --path packages/reference
30 | - run: sui move test --path packages/todo_list
31 | - run: sui move test --path packages/hello_world
32 |
--------------------------------------------------------------------------------
/packages/samples/sources/README.md:
--------------------------------------------------------------------------------
1 | # Managing Samples
2 |
3 | For every page in the book (under the `src/` directory), there is a `samples/` directory which contains the code samples for that page. The `samples/` directory is organized in the same way as the `src/` directory, with the same directory structure and file names.
4 |
5 | ## Rules
6 |
7 | 1. There's one Move file per page in the book.
8 | 2. The file name is the same as the page name (or similar for keywords).
9 | 3. The file can hold multiple modules.
10 | 4. The modules are named after the sub-sections of the page.
11 | 5. Anchors should be used to point to the specific code snippets in the Move file.
12 |
13 | ## Example
14 |
15 | For example, the `src/basic-syntax/address.md` page has a corresponding `samples/guides/address.move` file. The file contains the code samples for the page, organized in modules named after the sub-sections of the page.
16 |
17 | ```bash
18 | samples/
19 | basic-syntax/
20 | address.move
21 | ```
22 |
--------------------------------------------------------------------------------
/site/src/theme/CodeBlock/Buttons/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { type ReactNode } from 'react';
2 | import clsx from 'clsx';
3 | import BrowserOnly from '@docusaurus/BrowserOnly';
4 |
5 | import CopyButton from './CopyButton';
6 | import WordWrapButton from './WordWrapButton';
7 | import RenderButton from './RenderButton';
8 | import type { Props } from '@theme/CodeBlock/Buttons';
9 |
10 | import styles from './styles.module.css';
11 |
12 | // Code block buttons are not server-rendered on purpose
13 | // Adding them to the initial HTML is useless and expensive (due to JSX SVG)
14 | // They are hidden by default and require React to become interactive
15 | export default function CodeBlockButtons({ className }: Props): ReactNode {
16 | return (
17 |
18 | {() => (
19 |
20 |
21 |
22 |
23 |
24 | )}
25 |
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/site/src/theme/prism-include-languages.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import siteConfig from '@generated/docusaurus.config';
5 | export default function prismIncludeLanguages(PrismObject) {
6 | const {
7 | themeConfig: { prism },
8 | } = siteConfig;
9 | const { additionalLanguages } = prism;
10 | // Prism components work on the Prism instance on the window, while prism-
11 | // react-renderer uses its own Prism instance. We temporarily mount the
12 | // instance onto window, import components to enhance it, then remove it to
13 | // avoid polluting global namespace.
14 | // You can mutate PrismObject: registering plugins, deleting languages... As
15 | // long as you don't re-assign it
16 | globalThis.Prism = PrismObject;
17 | additionalLanguages.forEach((lang) => {
18 | // eslint-disable-next-line global-require, import/no-dynamic-require
19 | require(`prismjs/components/prism-${lang}`);
20 | });
21 | require('./prism-move');
22 | delete globalThis.Prism;
23 | }
24 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Build Docusaurus Site and Deploy to GitHub Pages
2 |
3 | on:
4 | push:
5 | branches: ["main"]
6 |
7 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
8 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
9 | concurrency:
10 | group: "pages"
11 | cancel-in-progress: false
12 |
13 | jobs:
14 | deploy:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v4
18 | - uses: pnpm/action-setup@v4
19 | with:
20 | cache: 'pnpm'
21 | - name: Install dependencies
22 | run: pnpm i
23 | working-directory: ./site
24 | - name: Build website
25 | run: pnpm build
26 | working-directory: ./site
27 | - name: Deploy to GitHub Pages
28 | uses: peaceiris/actions-gh-pages@v3
29 | with:
30 | github_token: ${{ secrets.GITHUB_TOKEN }}
31 | publish_dir: ./site/build
32 | cname: move-book.com
33 |
--------------------------------------------------------------------------------
/packages/samples/sources/programmability/collections-2.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_variable, unused_field, unused_use)]
5 | // ANCHOR: vec_set
6 | module book::collections_vec_set;
7 |
8 | use sui::vec_set::{Self, VecSet};
9 |
10 | public struct App has drop {
11 | /// `VecSet` used in the struct definition
12 | subscribers: VecSet
13 | }
14 |
15 | #[test_only]
16 | use std::unit_test::assert_eq;
17 |
18 | #[test]
19 | fun vec_set_playground() {
20 | let set = vec_set::empty(); // create an empty set
21 | let mut set = vec_set::singleton(1); // create a set with a single item
22 |
23 | set.insert(2); // add an item to the set
24 | set.insert(3);
25 |
26 | assert!(set.contains(&1)); // check if an item is in the set
27 | assert!(set.length() == 3); // get the number of items in the set
28 | assert!(!set.is_empty()); // check if the set is empty
29 |
30 | set.remove(&2); // remove an item from the set
31 | }
32 | // ANCHOR_END: vec_set
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # The Move Book
2 |
3 | This is the repository for [the Move Book](https://move-book.com) and
4 | [Move Language Reference](https://move-book.com/reference).
5 |
6 | ## Structure
7 |
8 | - Two books are placed in the `book` and `reference` directories. The `book` directory contains the
9 | main book, and the `reference` directory contains the reference book.
10 | - The `packages` directory contains the code samples used in both books.
11 | - The `site` directory contains [docusaurus](docusaurus.io) configuration and custom plugins for it.
12 |
13 | ## Running the Books Locally
14 |
15 | ### Prerequisites
16 |
17 | - NodeJS
18 | - `pnpm` (installation is: `npm i -g pnpm`)
19 |
20 | ### Local Server
21 |
22 | > All commands can be run from the root.
23 |
24 | ```bash
25 | pnpm start
26 | ```
27 |
28 | _The book will be available at `http://localhost:3000`._
29 |
30 | ### Production Build Test
31 |
32 | ```bash
33 | pnpm build
34 | pnpm serve
35 | ```
36 |
37 | ## Archive
38 |
39 | For the archive of the old version of the book, see the `archive` branch.
40 |
--------------------------------------------------------------------------------
/packages/samples/sources/programmability/events.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // ANCHOR: emit
5 | module book::events;
6 |
7 | use sui::coin::Coin;
8 | use sui::sui::SUI;
9 | use sui::event;
10 |
11 | /// The item that can be purchased.
12 | public struct Item has key { id: UID }
13 |
14 | /// Event emitted when an item is purchased. Contains the ID of the item and
15 | /// the price for which it was purchased.
16 | public struct ItemPurchased has copy, drop {
17 | item: ID,
18 | price: u64
19 | }
20 |
21 | /// A marketplace function which performs the purchase of an item.
22 | public fun purchase(coin: Coin, ctx: &mut TxContext) {
23 | let item = Item { id: object::new(ctx) };
24 |
25 | // Create an instance of `ItemPurchased` and pass it to `event::emit`.
26 | event::emit(ItemPurchased {
27 | item: object::id(&item),
28 | price: coin.value()
29 | });
30 |
31 | // Omitting the rest of the implementation to keep the example simple.
32 | abort
33 | }
34 | // ANCHOR_END: emit
35 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/struct-methods.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // ANCHOR: hero
5 | module book::hero;
6 |
7 | /// A struct representing a hero.
8 | public struct Hero has drop {
9 | health: u8,
10 | mana: u8,
11 | }
12 |
13 | /// Create a new Hero.
14 | public fun new(): Hero { Hero { health: 100, mana: 100 } }
15 |
16 | /// A method which casts a spell, consuming mana.
17 | public fun heal_spell(hero: &mut Hero) {
18 | hero.health = hero.health + 10;
19 | hero.mana = hero.mana - 10;
20 | }
21 |
22 | /// A method which returns the health of the hero.
23 | public fun health(hero: &Hero): u8 { hero.health }
24 |
25 | /// A method which returns the mana of the hero.
26 | public fun mana(hero: &Hero): u8 { hero.mana }
27 |
28 | #[test_only]
29 | use std::unit_test::assert_eq;
30 |
31 | #[test]
32 | // Test the methods of the `Hero` struct.
33 | fun test_methods() {
34 | let mut hero = new();
35 | hero.heal_spell();
36 |
37 | assert_eq!(hero.health(), 110);
38 | assert_eq!(hero.mana(), 90);
39 | }
40 | // ANCHOR_END: hero
41 |
--------------------------------------------------------------------------------
/site/src/theme/prism-atom-one-dark.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { themes as prismThemes } from 'prism-react-renderer';
5 | import { Language, PrismThemeEntry } from 'prism-react-renderer';
6 |
7 | // Re-export PrismTheme from prism-react-renderer
8 | export type PrismTheme = {
9 | plain: PrismThemeEntry;
10 | styles: Array<{
11 | types: string[];
12 | style: PrismThemeEntry;
13 | languages?: Language[];
14 | }>;
15 | };
16 |
17 | const baseTheme = prismThemes.oneDark;
18 |
19 | baseTheme.styles.push({
20 | types: ['comment'],
21 | style: { color: '#5C6370' },
22 | });
23 |
24 | baseTheme.styles.push({
25 | types: ['entity'],
26 | style: { color: '#E5C07B' },
27 | });
28 |
29 | baseTheme.styles.push({
30 | types: ['const-name'],
31 | style: { color: '#D19A66' },
32 | });
33 |
34 | baseTheme.styles.push({
35 | types: ['error-const'],
36 | style: { color: '#E06C75' },
37 | });
38 |
39 | baseTheme.styles.push({
40 | types: ['support'],
41 | style: { color: '#56B6C2' },
42 | });
43 |
44 | export default baseTheme as PrismTheme;
45 |
--------------------------------------------------------------------------------
/site/src/theme/prism-atom-one-light.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { themes as prismThemes } from 'prism-react-renderer';
5 | import { Language, PrismThemeEntry } from 'prism-react-renderer';
6 |
7 | // Re-export PrismTheme from prism-react-renderer
8 | export type PrismTheme = {
9 | plain: PrismThemeEntry;
10 | styles: Array<{
11 | types: string[];
12 | style: PrismThemeEntry;
13 | languages?: Language[];
14 | }>;
15 | };
16 |
17 | const baseTheme = prismThemes.oneLight;
18 |
19 | baseTheme.styles.push({
20 | types: ['comment'],
21 | style: { color: '#A0A1A7' },
22 | });
23 |
24 | baseTheme.styles.push({
25 | types: ['entity'],
26 | style: { color: '#C18401' },
27 | });
28 |
29 | baseTheme.styles.push({
30 | types: ['const-name'],
31 | style: { color: '#383A42' },
32 | });
33 |
34 | baseTheme.styles.push({
35 | types: ['error-const'],
36 | style: { color: '#E45649' },
37 | });
38 |
39 | baseTheme.styles.push({
40 | types: ['support'],
41 | style: { color: '#0184BC' },
42 | });
43 |
44 | export default baseTheme as PrismTheme;
45 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/address.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_variable)]
5 | module book::address;
6 |
7 | #[test] fun address_literal() {
8 |
9 | // ANCHOR: address_literal
10 | // address literal
11 | let value: address = @0x1;
12 |
13 | // named address registered in Move.toml
14 | let value = @std;
15 | let other = @sui;
16 | // ANCHOR_END: address_literal
17 |
18 | }
19 |
20 | #[test] fun address_u256() {
21 | // ANCHOR: to_u256
22 | use sui::address;
23 |
24 | let addr_as_u256: u256 = address::to_u256(@0x1);
25 | let addr = address::from_u256(addr_as_u256);
26 | // ANCHOR_END: to_u256
27 | }
28 |
29 | #[test] fun address_string() {
30 |
31 | // ANCHOR: to_string
32 | use sui::address;
33 | use std::string::String;
34 |
35 | let addr_as_string: String = address::to_string(@0x1);
36 | // ANCHOR_END: to_string
37 | }
38 |
39 | #[test] fun address_bytes() {
40 |
41 | // ANCHOR: to_bytes
42 | use sui::address;
43 |
44 | let addr_as_u8: vector = address::to_bytes(@0x1);
45 | let addr = address::from_bytes(addr_as_u8);
46 | // ANCHOR_END: to_bytes
47 | }
48 |
--------------------------------------------------------------------------------
/packages/todo_list/Move.lock:
--------------------------------------------------------------------------------
1 | # @generated by Move, please check-in and do not edit manually.
2 |
3 | [move]
4 | version = 1
5 | manifest_digest = "24B0736FDF137898506F036355120F1D37F9E66CD81E764CABDD1A4A70BCAC10"
6 | deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082"
7 | dependencies = [
8 | { name = "Sui" },
9 | ]
10 |
11 | [[move.package]]
12 | name = "MoveStdlib"
13 | source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/devnet", subdir = "crates/sui-framework/packages/move-stdlib" }
14 |
15 | [[move.package]]
16 | name = "Sui"
17 | source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/devnet", subdir = "crates/sui-framework/packages/sui-framework" }
18 |
19 | dependencies = [
20 | { name = "MoveStdlib" },
21 | ]
22 |
23 | [move.toolchain-version]
24 | compiler-version = "1.24.0"
25 | edition = "2024.beta"
26 | flavor = "sui"
27 |
28 | [env]
29 |
30 | [env.devnet]
31 | chain-id = "69a65b6d"
32 | original-published-id = "0x0088c084c17d08974f8eb7872df57ae28ef1c5513433a351cd2a91cecf3f7cda"
33 | latest-published-id = "0x0088c084c17d08974f8eb7872df57ae28ef1c5513433a351cd2a91cecf3f7cda"
34 | published-version = "1"
35 |
--------------------------------------------------------------------------------
/packages/todo_list/sources/todo_list.move:
--------------------------------------------------------------------------------
1 | // ANCHOR: all
2 | /// Module: todo_list
3 | module todo_list::todo_list;
4 |
5 | use std::string::String;
6 |
7 | /// List of todos. Can be managed by the owner and shared with others.
8 | public struct TodoList has key, store {
9 | id: UID,
10 | items: vector
11 | }
12 |
13 | /// Create a new todo list.
14 | public fun new(ctx: &mut TxContext): TodoList {
15 | let list = TodoList {
16 | id: object::new(ctx),
17 | items: vector[]
18 | };
19 |
20 | (list)
21 | }
22 |
23 | /// Add a new todo item to the list.
24 | public fun add(list: &mut TodoList, item: String) {
25 | list.items.push_back(item);
26 | }
27 |
28 | /// Remove a todo item from the list by index.
29 | public fun remove(list: &mut TodoList, index: u64): String {
30 | list.items.remove(index)
31 | }
32 |
33 | /// Delete the list and the capability to manage it.
34 | public fun delete(list: TodoList) {
35 | let TodoList { id, items: _ } = list;
36 | id.delete();
37 | }
38 |
39 | /// Get the number of items in the list.
40 | public fun length(list: &TodoList): u64 {
41 | list.items.length()
42 | }
43 | // ANCHOR_END: all
44 |
--------------------------------------------------------------------------------
/site/static/favicon.svg:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/primitive-types.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | module book::primitive_types {
5 |
6 | #[test, allow(unused_variable, unused_let_mut)]
7 | fun test_primitive_types() {
8 |
9 | // ANCHOR: variables_and_assignment
10 | let x: bool = true;
11 | let mut y: u8 = 42;
12 | // ANCHOR_END: variables_and_assignment
13 |
14 | // ANCHOR: shadowing
15 | let x: u8 = 42;
16 | let x: u16 = 42;
17 | // ANCHOR_END: shadowing
18 |
19 | // ANCHOR: boolean
20 | let x = true;
21 | let y = false;
22 | // ANCHOR_END: boolean
23 |
24 | // ANCHOR: integers
25 | let x: u8 = 42;
26 | let y: u16 = 42;
27 | // ...
28 | let z: u256 = 42;
29 | // ANCHOR_END: integers
30 |
31 | // ANCHOR: integer_explicit_type
32 | // Both are equivalent
33 | let x: u8 = 42;
34 | let x = 42u8;
35 | // ANCHOR_END: integer_explicit_type
36 |
37 | // ANCHOR: cast_as
38 | let x: u8 = 42;
39 | let y: u16 = x as u16;
40 | let z = 2 * (x as u16); // ambiguous, requires parentheses
41 | // ANCHOR_END: cast_as
42 |
43 | // ANCHOR: overflow
44 | let x: u8 = 255;
45 | let y: u8 = 255;
46 | let z: u16 = (x as u16) + ((y as u16) * 2);
47 | // ANCHOR_END: overflow
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/enum-and-match-2.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // ANCHOR: enum_test
5 | // Note, that the module has changed!
6 | module book::segment_tests;
7 |
8 | use book::segment;
9 |
10 | #[test]
11 | fun test_full_enum_cycle() {
12 | use std::unit_test::assert_eq;
13 |
14 | // Create a vector of different Segment variants.
15 | let segments = vector[
16 | segment::new_empty(),
17 | segment::new_string(b"hello".to_string()),
18 | segment::new_special(b" ", 0), // plaintext
19 | segment::new_string(b"move".to_string()),
20 | segment::new_special(b"21", 1), // hex
21 | ];
22 |
23 | // Aggregate all segments into the final string using `vector::fold!` macro.
24 | let result = segments.fold!(b"".to_string(), |mut acc, segment| {
25 | // Do not append empty, only `Special` and `String`.
26 | if (!segment.is_empty()) {
27 | acc.append(segment.to_string());
28 | };
29 | acc
30 | });
31 |
32 | // Check that the result is what's expected.
33 | assert_eq!(result, b"hello move!".to_string());
34 | }
35 | // ANCHOR_END: enum_test
36 |
--------------------------------------------------------------------------------
/packages/samples/sources/move-basics/type-reflection.move:
--------------------------------------------------------------------------------
1 | // Copyright (c) Mysten Labs, Inc.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #[allow(unused_variable)]
5 | // ANCHOR: main
6 | module book::type_reflection;
7 |
8 | use std::ascii::String;
9 | use std::type_name::{Self, TypeName};
10 |
11 | /// A function that returns the name of the type `T` and its module and address.
12 | public fun do_i_know_you(): (String, String, String) {
13 | let type_name: TypeName = type_name::with_defining_ids();
14 |
15 | // there's a way to borrow
16 | let str: &String = type_name.as_string();
17 |
18 | let module_name: String = type_name.module_string();
19 | let address_str: String = type_name.address_string();
20 |
21 | // and a way to consume the value
22 | let str = type_name.into_string();
23 |
24 | (str, module_name, address_str)
25 | }
26 |
27 | #[test_only]
28 | public struct MyType {}
29 |
30 | #[test_only]
31 | use std::unit_test::assert_eq;
32 |
33 | #[test]
34 | fun test_type_reflection() {
35 | let (type_name, module_name, _address_str) = do_i_know_you();
36 |
37 | assert_eq!(module_name, b"type_reflection".to_ascii_string());
38 | }
39 | // ANCHOR_END: main
40 |
--------------------------------------------------------------------------------
/site/src/theme/CodeBlock/Buttons/WordWrapButton/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { type ReactNode } from 'react';
2 | import clsx from 'clsx';
3 | import { translate } from '@docusaurus/Translate';
4 | import { useCodeBlockContext } from '@docusaurus/theme-common/internal';
5 | import Button from '@theme/CodeBlock/Buttons/Button';
6 | import type { Props } from '@theme/CodeBlock/Buttons/WordWrapButton';
7 | import IconWordWrap from '@theme/Icon/WordWrap';
8 |
9 | import styles from './styles.module.css';
10 |
11 | export default function WordWrapButton({ className }: Props): ReactNode {
12 | const { wordWrap } = useCodeBlockContext();
13 |
14 | const canShowButton = wordWrap.isEnabled || wordWrap.isCodeScrollable;
15 | if (!canShowButton) {
16 | return false;
17 | }
18 |
19 | const title = translate({
20 | id: 'theme.CodeBlock.wordWrapToggle',
21 | message: 'Toggle word wrap',
22 | description: 'The title attribute for toggle word wrapping button of code block lines',
23 | });
24 |
25 | return (
26 | wordWrap.toggle()}
28 | className={clsx(className, wordWrap.isEnabled && styles.wordWrapButtonEnabled)}
29 | aria-label={title}
30 | title={title}
31 | >
32 |
33 |
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 |
25 | {previous && (
26 |
29 |
30 | {previous.title} {' '}
31 | >
32 | }
33 | permalink={previous.permalink}
34 | />
35 | )}
36 | {next && (
37 |
40 | {next.title} {' '}
41 |
42 | >
43 | }
44 | permalink={next.permalink}
45 | isNext
46 | />
47 | )}
48 |
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 |
65 |
66 |
67 |
68 |
69 |
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 |
--------------------------------------------------------------------------------