This is the abridged developer documentation for Aptos Documentation # Build the Future of Web3 on Aptos > Everything you need to build a best-in-class Web3 experience. import { Card, CardGrid, Tabs, TabItem } from '@astrojs/starlight/components'; import ListCard from '~/components/ListCard.astro'; - [Keyless](/build/guides/aptos-keyless) - [Passkeys](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-66.md) - [On-chain Randomness](/build/smart-contracts/randomness) - [Gas and Storage Fees](/network/blockchain/gas-txn-fee) - [Parallel Execution](/network/blockchain/execution) - [Fee Payer](/build/sdks/ts-sdk/building-transactions/sponsoring-transactions) - [Aptos CLI](/build/cli) - [VSCode Extension](/build/smart-contracts/move-vscode-extension) - [Indexer API](/build/indexer/indexer-api) - [Official SDKs](/build/sdks) - [Testnet Faucet](/network/faucet) - [Faucet API](/build/apis/faucet-api) - [Apply for a Grant](https://aptosfoundation.org/grants) - [Aptos Learn](https://learn.aptoslabs.com) - [Ecosystem Projects](https://aptosfoundation.org/ecosystem/projects) - [Developer Discussions](https://github.com/aptos-labs/aptos-developer-discussions/discussions) - [Discussion Forum](https://forum.aptosfoundation.org) - [Discord](https://discord.gg/aptosnetwork) - [Telegram](https://t.me/aptos) # Aptos Model Context Protocol (MCP) > Learn how to use the Aptos MCP server to build applications with AI tools like Cursor and Claude Code import { CardGrid, LinkCard } from '@astrojs/starlight/components'; The Aptos Model Context Protocol (MCP) is a server that provides a set of tools, prompts, and resources to help developers build applications on the Aptos blockchain. It is designed to be used with AI tools like Cursor, Claude Code, and others that support the Model Context Protocol. ## Getting Started ### Prerequisites - [node and npm](https://nodejs.org/en) - Build Bot Api Key ### Generate a Build Bot Api Key To be able to make Geomi actions like managing API keys, etc., follow these instructions to generate a new Bot API Key to use with the MCP. - Go to https://geomi.dev/ - Click on your name in the bottom left corner - Click on "Bot Keys" - Click on the "Create Bot Key" button - Copy the Bot Key and paste it into the MCP configuration file as an env arg: `APTOS_BOT_KEY=` ### Supported Interfaces We've provided guides for Cursor and Claude Code to help you integrate the Aptos MCP into your development environment. If you're using a different AI tool, follow the steps for your favorite AI tool, and refer to the documentation for Cursor or Claude Code for examples. # Setting up Aptos MCP with Claude Code > Step-by-step guide to configure and use Aptos MCP with Claude Code for blockchain development 1. Install the `claude-code` package ```bash npm install -g @anthropic-ai/claude-code ``` 2. Locate where Claude Code stores its configuration, usually on Mac it is at `~/.claude.json` 3. Edit the `mcpServers` object in the `json` file with ```json { "mcpServers": { "aptos-mcp": { "command": "npx", "args": ["-y", "@aptos-labs/aptos-mcp"], "type": "stdio", "env": { "APTOS_BOT_KEY": "" } } } } ``` 4. Obtain your `APTOS_BOT_KEY`: - Visit [Geomi](https://geomi.dev/) and log in with your account. - Navigate to the API Keys section and create a new key. - Copy the generated key for use in the next step. 5. Make sure to update the `APTOS_BOT_KEY` with the key you generated in the previous step. 6. Navigate to your project ```bash cd your-awesome-project ``` 7. In a new terminal window type: ```bash claude ``` 8. You can now use Claude Code to interact with the Aptos MCP. Prompt the agent with `what aptos mcp version are you using?` to verify the connection. The agent should reply with something like: ```text I'm using Aptos MCP version 0.0.2. ``` # Setting up Aptos MCP with Cursor > Complete guide to integrate Aptos MCP with Cursor IDE for enhanced blockchain development workflows 1. Open the Cursor IDE 2. On the project root folder, create a `.cursor` folder 3. In the `.cursor` folder, create a `mcp.json` file 4. Paste this content ```json { "mcpServers": { "aptos-mcp": { "command": "npx", "args": ["-y", "@aptos-labs/aptos-mcp"], "env": { "APTOS_BOT_KEY": "" } } } } ``` 5. Obtain your `APTOS_BOT_KEY`: - Visit [Geomi](https://geomi.dev/) and log in with your account. - Navigate to the API Keys section and generate a new key. - Copy the generated key for use in the next step. 6. Make sure to update the `APTOS_BOT_KEY` in the `mcp.json` file with the key you just generated. ### Verify Cursor runs your MCP 1. Open Cursor Settings: `cursor -> settings -> cursor settings` 2. Head to the `MCP` or `Tools & Integrations` section 3. Make sure it is enabled and showing a green color indicator
image 4. Click the “refresh” icon to update the MCP. 5. Make sure the Cursor AI window dropdown is set to `Agent`
image (1) 6. Prompt the agent with `what aptos mcp version are you using?` to verify the connection. The agent should reply with something like:

![Screenshot 2025-06-26 at 3 54 44PM](https://github.com/user-attachments/assets/4ead13c6-1697-40e1-b4e7-0fbf7dd5f281) # Aptos Improvement Proposals (AIPs) > Learn about Aptos Improvement Proposals - how the community proposes changes and improvements to the Aptos protocol Aptos Improvement Proposals (AIPs) are a way for the Aptos community to propose changes, improvements, and new features to the Aptos protocol. AIPs are designed to be a collaborative process that allows anyone in the community to contribute ideas and feedback. AIPs are documented in the [AIPs repository](https://github.com/aptos-foundation/AIPs) and are administered by the Aptos Foundation. Each AIP is assigned a unique number and goes through a rigorous review process before it is accepted or rejected. ## What do AIPs cover? AIPs can cover a wide range of topics, including: - Node protocol changes - Mempool changes, consensus changes, etc. - Framework (smart contract) changes - New modules, new functions, etc. - Governance changes - Changes to the way the Aptos Foundation operates, changes to the way AIPs are processed, etc. ## What is this section of the docs mostly about? This section of the docs is mostly about AIPs that are relevant to developers and providing FAQs and quick information about them. # AIP-115: Stateless Accounts > Learn about AIP-115 which introduces stateless accounts that operate without explicitly created Account resources [AIP-115](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-115.md) covers stateless accounts. ## General FAQ ### What is a Stateless Account? A Stateless Account is a new behavior for Aptos accounts that allows them to operate without requiring an explicitly created `0x1::account::Account` resource. Instead, these accounts use default behaviors until an action necessitates the creation of the resource. This change simplifies account management and reduces unnecessary resource creation, making it easier for developers and users to interact with the Aptos blockchain. ### How is it different from a regular account? Technically, there is no separate account type. All accounts are the same under the hood. The difference is that accounts without a resource behave in a "stateless" manner using default values. The account resource is only created on-demand when needed. ### How does it work? When an account signs its first transaction sequence number transaction, it will not have the `0x1::account::Account` resource created. Instead, it will create the `0x1::account::Account` resource only when an action that requires to increment the sequence number. For an orderless transaction, the account resource is not needed at all, and the account resource will not be created. ## Technical Details FAQ ### What is the default auth\_key for Stateless Accounts? If the `0x1::account::Account` resource does not exist, the auth\_key defaults to the account address itself. This allows the account to sign and submit transactions without needing a resource. ### What is the sequence number of a Stateless Account? It defaults to `0` if the account resource does not exist. In the future, with Orderless Transactions, the sequence number may be eliminated entirely. ### When is the account resource automatically created? The resource is created when an action that requires on-chain state, such as: - Rotating the authentication key - Using capabilities or features that rely on the account resource such as sequence number - Explicitly calling functions that access fields in the account resource ### Does creating the account resource incur extra gas cost? Yes. The creation of the resource is deferred, and the corresponding gas and storage fees are only charged at the moment of actual creation, not beforehand. ### Any behavior change to account module at the Move level? `0x1::account::exists_at` always returns true, as all on-chain account addresses are considered valid and treated as existing by default. There is no move function in the module to check whether the underlying account resource really exists since the goal is to make it transparent to users. As a result, any logic that first checks whether an account exists before attempting to create it is now obsolete. ### Can users force-create the account resource upfront? Yes. Users can explicitly call functions like `0x1::account::create_account_if_does_not_exist` to create the resource manually, if desired. ### Any behavior change to API? If you rely on the following API behavior, please adjust correspondingly. `GET /accounts/{address}` will never return “404 not found” but the default authentication key and sequence number mentioned above for stateless accounts. Therefore, if it is desired to check whether the account resource exists or not, try `GET /accounts/{address}/resource/0x1::account::Account` ### Do existing accounts get affected? No. Existing accounts with resources already created will continue to work exactly as they do now. Stateless Account behavior only applies to accounts that have not yet created a resource. ### Do dApps / CEX need to change anything? Maybe. Previously, checking whether an account existed often relied on calling APIs that return a 404 error if the account resource was not found. Applications would then use this as a signal to warn users (e.g., "This account does not exist"). Under the new model, all addresses are considered valid, and such 404-based existence checks are no longer reliable or meaningful. However, we are not banning this pattern—developers may still choose to warn users that an account may not have performed any on-chain activity and thus might not have a resource created yet. If you still want to detect whether an account has an associated resource, you can refer to the method described in Q9 or check whether the sequence\_number is 0\. But be aware that with the introduction of orderless transactions, some accounts may only submit transactions that never create a resource, which could result in false negatives. We recommend designing your application to be robust regardless of whether the account resource exists, and to avoid assuming resource presence as a proxy for account existence. Examples: - A wallet might check for an account to see if it’s a new account, and provide a user a warning. With this change, instead a mitigation like Q9 will be needed. - A custodial wallet may send funds to initialize an account with gas. With this change, it will need to check the account’s balance instead of just the account existing. ### Is this compatible with Orderless Transactions? Yes. Orderless Transactions and Stateless Accounts are complementary. Once Orderless Transactions are enabled, sequence numbers will no longer be needed, enabling truly stateless usage. ## Will all accounts become Stateless in the future? No. Stateless Accounts are not a new account type. It simply allows accounts to behave with default logic until the account resource is needed. This lazy resource creation, does not transform existing account state. All accounts can behave in a stateless way by default, but they will still create the standard resource if and when advanced features are used. # AIP-88: Block Epilogue Transactions > Understanding AIP-88 which introduces block epilogue transactions to provide information about executed blocks [AIP-88](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-88.md) covers block epilogue transactions, which are a new type of transaction that give information about the block after it has been executed. These transactions can only be created by the consensus and are not user-initiated. They contain information about gas usage in the block and will contain more information in the future. It replaces the previous `StateCheckpoint` transaction type, which was used to "sometimes" signal the end of a block. The new `BlockEpilogue` transaction is now sometimes created at the end of a block instead, and it is guaranteed to be the last transaction in the block. The only case this does not apply is the last block of an epoch, which will have no `BlockEpilogue` transaction. ## General FAQ ### What is in the Block Epilogue Transaction? The block epilogue transaction contains a `BlockEndInfo` enum. It is purposely designed to be an enum so that it can be extended in the future without breaking existing code. The current version is `V0` and contains the following fields: ```move module 0x1::epilogue { enum BlockEndInfo { V0 { /// Whether block gas limit was reached block_gas_limit_reached: bool, /// Whether block output limit was reached block_output_limit_reached: bool, /// Total gas_units block consumed block_effective_block_gas_units: u64, /// Total output size block produced block_approx_output_size: u64, }, } } ``` These mainly contain information about the gas usage in the block for debugging purposes. The JSON output will look like this: ```json { "version":"1912", "hash":"0x54a8efc93fc94f5b545dadb63da3d4dc192125c717b336dc446d55a5b553913f", "state_change_hash":"0xafb6e14fe47d850fd0a7395bcfb997ffacf4715e0f895cc162c218e4a7564bc6", "event_root_hash":"0x414343554d554c41544f525f504c414345484f4c4445525f4841534800000000", "state_checkpoint_hash":"0x841a43956ca09a02b1c1cdadc65f24c390170aa666015a2e8f7ec5c9d6a3875f", "gas_used":"0", "success":true, "vm_status":"Executed successfully", "accumulator_root_hash":"0x6561976b4560ff25239dffc6cada70e7008dd42fc4d3df2eca6a86b6d2ec384d", "changes":[], "timestamp":"1719263322836578", "block_end_info": { "block_gas_limit_reached":false, "block_output_limit_reached":false, "block_effective_block_gas_units":0, "block_approx_output_size":1163 }, "type":"block_epilogue_transaction" } ``` ## Compatibility FAQ ### What does this mean for my dApp? If you process transactions in your dApp, and expect the last transaction in a block to be a `StateCheckpoint`, you will need to update your code to handle the `BlockEpilogue` transaction instead. Note that, the `BlockEpilogue` transaction is guaranteed to be the last transaction of a block except for the last block of an epoch, which will not have a `BlockEpilogue` transaction. ### What apps are likely to be affected? Apps that index all transactions such as block explorers and centralized exchange indexer processors may be affected. However, most of these are informational and do not affect the core functionality of the dApp. ### What can I do to process the new transaction type? If you're using the Aptos Go SDK or the Aptos TypeScript SDK, you can update to the latest version, which will automatically handle the new transaction type. # Aptos APIs > Access the Aptos blockchain through various APIs including REST API, GraphQL, and specialized endpoints for different use cases import { CardGrid, LinkCard } from '@astrojs/starlight/components'; The Aptos Blockchain network can be accessed by several APIs, depending on your use-case. ## Aptos Fullnode This API - embedded into Fullnodes - provides a simple, low latency, yet low-level way of _reading_ state and _submitting_ transactions to the Aptos Blockchain. It also supports transaction simulation. ## Indexer ## Faucet (Only Testnet/Devnet) The code of each of the above-mentioned APIs is open-sourced on [GitHub](https://github.com/aptos-labs/aptos-core). As such anyone can operate these APIs and many independent operators and builders worldwide choose to do so. ### Aptos Labs operated API Deployments [Aptos Labs](https://aptoslabs.com) operates a deployment of these APIs on behalf of [Aptos Foundation](https://aptosfoundation.org/) for each [Aptos Network](/network/nodes/networks) and makes them available for public consumption. These APIs allow for limited access on a per-IP basis without an API key (anonymous access). To get much higher rate limits you can sign up for an [Geomi](https://geomi.dev/) account. # Aptos Labs Geomi > Access Aptos Labs APIs, gas station services, and no-code indexing through the Geomi developer portal [Geomi](https://geomi.dev) is your gateway to access Aptos Labs provided APIs in a quick and easy fashion to power your dapp. Beyond API access it offers gas station and no code indexing services. Learn more about Geomi at the dedicated [Geomi docs site](https://geomi.dev/docs). # Data Providers > Access Aptos blockchain data through SQL interfaces and analytics dashboards for aggregated data analysis If you want to access aptos blockchain data but don't need it in real-time. We have a few options that will let you access this data using SQL or UIs for building dashboards. This type of data is often used for analytics since it allows for aggregations. ## Review of data endpoints Hitting the full node directly will give the latest data (will be missing historical unless it's an archival full node) using [REST API](/build/apis#aptos-fullnode) Indexer layer on top of this will provide a [GRPC transaction stream](/build/indexer/txn-stream/aptos-hosted-txn-stream) On top of this transaction stream, we've built out some product logic tables that can be queried through [GraphQL](/build/indexer) Since the logic to parse out transaction is [public](https://github.com/aptos-labs/aptos-indexer-processors-v2), some vendors have implemented similar parsing logic to create a subset of tables and made them available to query. ## SQL Tables Indexer defines several processors that create different database tables. ### Core tables These are parsed directly from node API response, one option is to split it out into the following tables: - Blocks - version, block height, epoch, timestamp - Transactions - version, sender, entry function, gas - Signatures - signature types, signer, fee payer address - Events - type and data for events We store data as table items, resources or modules - (write set) changes - change index, change type, resource address - Table items - table key, table handle, key (content and type), value (content and type) - (move) resources - resource address, resource type, data - (move) modules - bytecode for deployed modules ## Vendors of off-chain data Most of our data vendors only provide core datasets. A [subset of vendors](https://aptosfoundation.org/currents/aptos-on-chain-data-capabilities-with-dune-nansen-and-other-providers) is listed below ### Google bigquery public dataset Provides data through [google public data](https://console.cloud.google.com/marketplace/product/bigquery-public-data/crypto-aptos-mainnet-us) ![bq\_sql](~/images/screenshots/bq_sql.png) We also have sample analytics queries [using the above resources](https://github.com/aptos-labs/explorer/tree/main/analytics) ### Dune We have a dashboard here: https://dune.com/aptos/aptos-chain-metrics-overview ### Allium Data source for many downstream vendors such as defillama and rwa.xyz. Raw data is available: https://docs.allium.so/historical-data/supported-blockchains/move-ecosystem/aptos They also have transfers for stablecoins https://docs.allium.so/historical-data/stablecoins#stablecoin-metrics ### Artemis Provides [topline metrics](https://app.artemis.xyz/asset/aptos) as well as chart builder ### Nansen Provides [topline metrics](https://app.nansen.ai/macro/blockchains?chain=aptos) with additional functionality with account. ### Sentio They have a guide here: https://docs.sentio.xyz/docs/aptos Data is found in data source -> external project -> sentio/aptos-overview They also provide stack tracing of transactions ### RWA.xyz Data can be found here: https://app.rwa.xyz/networks/aptos You'll need to make an account to access stablecoin details. ### Flipside Has pivoted from dashboard vendor to more of a vibe coding tool. https://flipsidecrypto.xyz/home/ ## Other vendors We also have some partners who target more enterprise use cases - [Token Terminal](https://tokenterminal.com/resources/articles/aptos-data-partnership) - [The Tie](https://www.thetie.io/insights/news/introducing-aptos-ecosystem-dashboard-and-on-chain-data/) - [Elliptic](https://www.elliptic.co/media-center/elliptic-partners-with-aptos-foundation-as-a-data-integration-provider-to-offer-compliance-screening-and-risk-services-for-aptos-network) # Faucet API > Get free APT tokens on devnet and testnet for development and testing purposes using the faucet API The faucet allows users to get `APT` on devnet. On testnet you can only mint at the [mint page](/network/faucet). It is not available on Mainnet. The endpoints for each faucet are: - Devnet: https://faucet.devnet.aptoslabs.com ## Using the faucet Each SDK has integration for devnet to use the faucet. Below are a few examples, but you can see more information on each individual [SDK's documentation](/build/sdks). ### Using the faucet in a wallet Most wallets, such as [Petra](https://aptosfoundation.org/ecosystem/project/petra) or [Pontem](https://aptosfoundation.org/ecosystem/project/pontem-wallet) will have a faucet button for devnet. See full list of [Aptos Wallets](https://aptosfoundation.org/ecosystem/projects/wallets). ### Using the faucet in the Aptos CLI Once you've [set up your CLI](/build/cli/setup-cli), you can simply call fund-with-faucet. The amount used is in Octas (1 APT = 100,000,000 Octas). ```shellscript filename="Terminal" aptos account fund-with-faucet --account 0xd0f523c9e73e6f3d68c16ae883a9febc616e484c4998a72d8899a1009e5a89d6 --amount 100000000 ``` ### Using the faucet in the TypeScript SDK Here is an example funding the account `0xd0f523c9e73e6f3d68c16ae883a9febc616e484c4998a72d8899a1009e5a89d6` with 1 APT in Devnet. The amount used is in Octas (1 APT = 100,000,000 Octas). ```typescript filename="index.ts" import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk"; const aptos = new Aptos(new AptosConfig({network: Network.Devnet})); aptos.fundAccount({accountAddress: "0xd0f523c9e73e6f3d68c16ae883a9febc616e484c4998a72d8899a1009e5a89d6", amount: 100000000}); ``` ### Using the faucet in the Go SDK Here is an example funding the account `0xd0f523c9e73e6f3d68c16ae883a9febc616e484c4998a72d8899a1009e5a89d6` with 1 APT in Devnet. The amount used is in Octas (1 APT = 100,000,000 Octas). ```go filename="index.go" import "github.com/aptos-labs/aptos-go-sdk" func main() { client, err := aptos.NewClient(aptos.LocalnetConfig) if err != nil { panic(err) } client.Fund("0xd0f523c9e73e6f3d68c16ae883a9febc616e484c4998a72d8899a1009e5a89d6", 100000000) } ``` ### Calling the faucet: Other languages not supported by SDKs If you are trying to call the faucet in other languages, you have two options: 1. Generate a client from the [OpenAPI spec](https://github.com/aptos-labs/aptos-core/blob/main/crates/aptos-faucet/doc/spec.yaml). 2. Call the faucet on your own. For the latter, you will want to build a query similar to this: ```shellscript filename="Terminal" curl -X POST 'https://faucet.devnet.aptoslabs.com/mint?amount=10000&address=0xd0f523c9e73e6f3d68c16ae883a9febc616e484c4998a72d8899a1009e5a89d6' ``` This means mint 10000 [octas](/network/glossary#Octa) to address `0xd0f523c9e73e6f3d68c16ae883a9febc616e484c4998a72d8899a1009e5a89d6`. # Fullnode REST API > Low-level REST API for reading state, submitting transactions, and simulating operations on the Aptos blockchain import { Aside, CardGrid, LinkCard } from '@astrojs/starlight/components'; This API - embedded into Fullnodes - provides a simple, low latency, yet low-level way of reading state and submitting transactions to the Aptos Blockchain. It also supports transaction simulation. For more advanced queries, we recommend using the [Indexer GraphQL API](/build/indexer). ## Fullnode REST API Explorer ## Understanding rate limits As with the [Aptos Indexer](/build/indexer/indexer-api), the Aptos REST API has rate limits based on compute units. You can learn more about how the ratelimiting works by reading the [Geomi docs](https://geomi.dev/docs/admin/billing). ## Viewing current and historical state Most integrations into the Aptos blockchain benefit from a holistic and comprehensive overview of the current and historical state of the blockchain. Aptos provides historical transactions, state, and events, all the result of transaction execution. - Historical transactions specify the execution status, output, and tie to related events. Each transaction has a unique version number associated with it that dictates its global sequential ordering in the history of the blockchain ledger. - The state is the representation of all transaction outputs up to a specific version. In other words, a state version is the accumulation of all transactions inclusive of that transaction version. - As transactions execute, they may emit events. [Events](/network/blockchain/events) are hints about changes in on-chain data. The storage service on a node employs two forms of pruning that erase data from nodes: - state - events, transactions, and everything else While either of these may be disabled, storing the state versions is not particularly sustainable. Events and transactions pruning can be disabled via setting the [`enable_ledger_pruner`](https://github.com/aptos-labs/aptos-core/blob/cf0bc2e4031a843cdc0c04e70b3f7cd92666afcf/config/src/config/storage_config.rs#L141) to `false` in `storage_config.rs`. This is default behavior in Mainnet. In the near future, Aptos will provide indexers that mitigate the need to directly query from a node. The REST API offers querying transactions and events in these ways: - [Transactions for an account](https://api.devnet.aptoslabs.com/v1/spec#/operations/get_account_transactions) - [Transactions by version](https://api.devnet.aptoslabs.com/v1/spec#/operations/get_transaction_by_version) - [Events by event handle](https://api.devnet.aptoslabs.com/v1/spec#/operations/get_events_by_event_handle) ## Reading state with the View function View functions do not modify blockchain state when called from the API. A [View function](https://github.com/aptos-labs/aptos-core/blob/main/api/src/view_function.rs) and its [input](https://github.com/aptos-labs/aptos-core/blob/main/api/types/src/view.rs) can be used to read potentially complex on-chain state using Move. For example, you can evaluate who has the highest bid in an auction contract. Here are related files: - [`view_function.rs`](https://github.com/aptos-labs/aptos-core/blob/main/api/src/tests/view_function.rs) for an example - related [Move](https://github.com/aptos-labs/aptos-core/blob/90c33dc7a18662839cd50f3b70baece0e2dbfc71/aptos-move/framework/aptos-framework/sources/coin.move#L226) code - [specification](https://github.com/aptos-labs/aptos-core/blob/90c33dc7a18662839cd50f3b70baece0e2dbfc71/api/doc/spec.yaml#L8513). The view function operates like the Aptos simulation API, though with no side effects and an accessible output path. View functions can be called via the `/view` endpoint. Calls to view functions require the module and function names along with input type parameters and values. A function does not have to be immutable to be tagged as `#[view]`, but if the function is mutable it will not result in state mutation when called from the API. If you want to tag a mutable function as `#[view]`, consider making it private so that it cannot be maliciously called during runtime. In order to use the View functions, you need to [publish the module](/build/cli/working-with-move-contracts) through the [Aptos CLI](/build/cli). In the Aptos CLI, a view function request would look like this: ```shellscript filename="Terminal" aptos move view --function-id devnet::message::get_message --profile devnet --args address:devnet { "Result": [ "View functions rock!" ] } ``` In the TypeScript SDK, a view function request would look like this: ```typescript filename="index.ts" import { Aptos } from "@aptos-labs/ts-sdk"; const aptos = new Aptos(); const [balance] = aptos.view<[string]>({ function: "0x1::coin::balance", typeArguments: ["0x1::aptos_coin::AptosCoin"], functionArguments: [alice.accountAddress] }); expect(balance).toBe("100000000"); ``` The view function returns a list of values as a vector. By default, the results are returned in JSON format; however, they can be optionally returned in Binary Canonical Serialization (BCS) encoded format. # Fullnode API Reference > Complete API reference documentation for the Aptos Fullnode REST API endpoints and methods {/* */} # Aptos CLI – Install, Setup, and Use the Command-Line Interface > Learn how to install, configure, and use the Aptos CLI to compile Move contracts, interact with the blockchain, run a local network, and manage nodes. import { CardGrid, LinkCard } from '@astrojs/starlight/components'; The Aptos command line interface (CLI) is a tool to help you compile and test Move contracts. It can also help you quickly play with Aptos features on-chain. For more advanced users, the CLI can also be used to run a private Aptos network (to help test code locally) and can be helpful managing a network node. ## 📥 Install the Aptos CLI ## ⚙️ Setup the Aptos CLI ## 🛠️ Using the Aptos CLI # Formatting Move Contracts > Learn how to format and beautify Move smart contract code using the movefmt tool integrated into the Aptos CLI with configuration options. `movefmt` is a formatter tool that makes Move code much easier to write, read, and maintain — greatly improving the development experience on Aptos. ## Installation `movefmt` is integrated into the Aptos CLI. To begin using it, first install it using the CLI update command. ```shellscript filename="Terminal" # Install movefmt for first time usage aptos update movefmt ``` To install a specific version of `movefmt`: ```shellscript filename="Terminal" # Install movefmt with the target aptos update movefmt --target-version ``` The latest release of `movefmt` can be found [here](https://github.com/movebit/movefmt/releases). ## Format your code Similar to compilation and testing, you can use the following command to format the Move package: ```shellscript filename="Terminal" # Format the Move package aptos move fmt ``` Different ways of emitting the formatting result is supported: ```shellscript filename="Terminal" # Format and overwrite all the target move files in the package. # This is the default behavior if `--emit-mode` is not explicitly specified aptos move fmt --emit-mode=overwrite # Print the formatting result to terminal aptos move fmt --emit-mode=std-out # Print the formatting result to new files with the suffix `.fmt.out` in the same directory aptos move fmt --emit-mode=new-file # Print the difference between before and after formatting aptos move fmt --emit-mode=diff ``` `movefmt` also provides different options to configure how the code will be formatted. Here is the default configuration: ``` max_width = 90 # each line can have at most 90 characters indent_size = 4 # the indent is 4 spaces tab_spaces = 4 # each tab is identical to 4 spaces hard_tabs = false # when a tab is inserted, it will be automatically replaced by 4 spaces ``` To override the default option, users can either specify a configuration file `movefmt.toml` and put it in Move package directory or manually specify it in the command line: ```shellscript filename="Terminal" # When formatting the code, set `max_width` to 80 and `indent_size` to 2 aptos move fmt --config max_width=80,indent_size=2 ``` ## Feedback Aptos Labs remains committed to improving the developer experience for builders using Move on Aptos. If you’re interested in shaping the style guidelines for Move, we would love to hear your comments and feedback [here](https://github.com/movebit/movefmt/issues). # Install the Aptos CLI on Linux > Step-by-step instructions to install the Aptos CLI on Linux using shell scripts, package managers, or pre-compiled binaries with troubleshooting guidance. import { Aside, Steps } from '@astrojs/starlight/components'; For Linux, the easiest way to install the Aptos CLI tool is via shell script, although if that does not work, you can also install manually via downloading pre-compiled binaries. The pre-compiled binaries approach is not generally recommended as updating is very manual. # Install via Script 1. In the terminal, use one of the following commands: ```shellscript filename="Terminal" curl -fsSL "https://aptos.dev/scripts/install_cli.sh" | sh ``` Or use the equivalent `wget` command: ```shellscript filename="Terminal" wget -qO- "https://aptos.dev/scripts/install_cli.sh" | sh ``` 2. (Optional) It can be helpful to add the Aptos CLI to a folder in your PATH, or to add it to your PATH directly. - The steps to add a folder to your PATH are shell dependent. - You can run `echo $SHELL` to print the default shell for your machine, then google specific steps to add a folder to your PATH for that shell. 3. Verify the script is installed by opening a new terminal and running aptos help - You should see a list of commands you can run using the CLI. - In the future, this is a helpful resource to learn exactly how each command works. # Install via Package Manager (Optional) ### Arch Linux #### Install via AUR (Arch User Repository) ```shellscript filename="Terminal" git clone https://aur.archlinux.org/aptos-bin.git cd aptos-bin makepkg -si ``` or use an AUR helper like `yay`: ```shellscript filename="Terminal" yay -S aptos-bin ``` # Install via Pre-Compiled Binaries (Backup Method) 1. Go to the . 2. Click the "Assets" expandable menu for the latest release to see the pre-compiled binaries. 3. Download the zip file for Linux. 1. It’ll have a name like: `aptos-cli--Linux-x86_64.zip` or `aptos-cli--Linux-aarch64.zip`. 2. Make sure you choose the right zip file for your computer architecture (x86\_64 for Intel / AMD or aarch64 for ARM). 3. You will likely have to dismiss warnings that this is a suspicious file when downloading. 4. Unzip the downloaded file. 5. Move the extracted Aptos binary file into your preferred folder. 6. Open a terminal and navigate to your preferred folder. 7. Make ~/aptos an executable by running chmod +x ~/aptos. 8. Verify that this installed version works by running ~/aptos help. You should see instructions for how to use all CLI commands. These can be helpful in the future when you are trying to understand how to use specific commands. 9. (Optional) It can be helpful to add the Aptos CLI to a folder in your PATH, or to add it to your PATH directly. - The steps to add a folder to your PATH are shell dependent. - You can run `echo $SHELL` to print the default shell for your machine, then google specific steps to add a folder to your PATH for that shell. # Install the Aptos CLI on Mac > Complete installation guide for the Aptos CLI on macOS using Homebrew, shell scripts, or pre-compiled binaries with upgrade instructions. import { Aside, Steps } from '@astrojs/starlight/components'; For Mac, the easiest way to install the Aptos CLI is with the package manager `brew`. # Installation 1. Ensure you have brew installed https://brew.sh/. 2. Open a new terminal and enter the following commands. ```shellscript filename="Terminal" brew update brew install aptos ``` 3. Open another terminal and run aptos help to verify the CLI is installed. ```shellscript filename="Terminal" aptos help ``` # Upgrading the CLI Upgrading the CLI with brew just takes 2 commands: ```shellscript filename="Terminal" brew update brew upgrade aptos ``` # Install via Script 1. In the terminal, use one of the following commands: ```shellscript filename="Terminal" curl -fsSL "https://aptos.dev/scripts/install_cli.sh" | sh ``` Or use the equivalent `wget` command: ```shellscript filename="Terminal" wget -qO- "https://aptos.dev/scripts/install_cli.sh" | sh ``` 2. (Optional) It can be helpful to add the Aptos CLI to a folder in your PATH, or to add it to your PATH directly. - The steps to add a folder to your PATH are shell dependent. - You can run `echo $SHELL` to print the default shell for your machine, then google specific steps to add a folder to your PATH for that shell. 3. Verify the script is installed by opening a new terminal and running aptos help - You should see a list of commands you can run using the CLI. - In the future, this is a helpful resource to learn exactly how each command works. # Install via Pre-Compiled Binaries (Backup Method) 1. Go to the . 2. Click the "Assets" expandable menu for the latest release to see the pre-compiled binaries. 3. Download the zip file for macOS. 1. It’ll have a name like: `aptos-cli--macOS-x86_64.zip` or `aptos-cli--macOS-arm64.zip`. 2. Make sure you choose the right zip file for your computer architecture (x86\_64 for Intel / AMD or arm64 for ARM). 3. You will likely have to dismiss warnings that this is a suspicious file when downloading. 4. Unzip the downloaded file. 5. Move the extracted Aptos binary file into your preferred folder. 6. Open a terminal and navigate to your preferred folder. 7. Make ~/aptos an executable by running chmod +x ~/aptos. 8. Verify that this installed version works by running ~/aptos help. You should see instructions for how to use all CLI commands. These can be helpful in the future when you are trying to understand how to use specific commands. 9. (Optional) It can be helpful to add the Aptos CLI to a folder in your PATH, or to add it to your PATH directly. - The steps to add a folder to your PATH are shell dependent. - You can run `echo $SHELL` to print the default shell for your machine, then google specific steps to add a folder to your PATH for that shell. # Install Specific Aptos CLI Versions (Advanced) > Advanced guide to build and install specific versions of the Aptos CLI from source code for specialized development needs and custom architectures. import { Steps } from '@astrojs/starlight/components'; If you need a specific version of the Aptos CLI, you can build it directly from the Aptos source code. This installation method is primarily used to interact with specific features on Devnet which may not have made it to Testnet / Mainnet yet. You may also want to follow these steps if you are running an architecture which does not play well with the existing releases / pre-compiled binaries. If you do not need this advanced method, you can find the normal install steps [here](/build/cli). ## Install on macOS / Linux 1. Follow the steps to . 2. Ensure you have cargo installed by following the steps on . 3. Build the CLI tool: cargo build --package aptos --profile cli. The binary will be available at `target/cli/aptos`. 4. (Optional) Move this executable to a place in your PATH. 5. Verify the installation worked by running target/cli/aptos help. These help instructions also serve as a useful detailed guide for specific commands. ## Install on Windows 1. Follow the steps to build Aptos from source . 2. Ensure you have cargo installed by following the steps on . 3. Build the CLI tool: cargo build --package aptos --profile cli. The binary will be available at `target\cli\aptos.exe`. 4. (Optional) Move this executable to a place in your PATH. 5. Verify the installation worked by running target\cli\aptos.exe help. These help instructions also serve as a useful detailed guide for specific commands. # Install the Aptos CLI on Windows > Complete guide to install the Aptos CLI on Windows using PowerShell scripts, package managers, or pre-compiled binaries with troubleshooting tips. import { Aside, Steps } from '@astrojs/starlight/components'; For Windows, the easiest way to install the Aptos CLI tool is via PowerShell script. If that does not work, you can also install manually via pre-compiled binaries. The pre-compiled binaries approach is not generally recommended as updating is very manual. # Install via PowerShell Script 1. In PowerShell, run the install script: ```powershell filename="Terminal" Set-ExecutionPolicy RemoteSigned -Scope CurrentUser; iwr https://aptos.dev/scripts/install_cli.ps1 | iex ``` 2. Verify the script is installed by opening a new terminal and running aptos help. - You should see a list of commands you can run using the CLI. - In the future, this is a helpful resource to learn exactly how each command works. # Install via Package Manager (Optional) ### If you have [Scoop](https://scoop.sh/) installed, you can run the following command to install the Aptos CLI: ```powershell filename="Terminal" scoop install https://aptos.dev/scoop/aptos.json ``` ### If you have [Chocolatey](https://chocolatey.org/) installed, you can run the following command to install the Aptos CLI: ```powershell filename="Terminal" choco install aptos ``` ### If you have [winget](https://winget.run/) installed, you can run the following command to install the Aptos CLI: ```powershell filename="Terminal" winget install aptos ``` # Install via Pre-Compiled Binaries (Backup Method) 1. Go to the . 2. Expand "Assets" to see the pre-compiled binaries. 3. Download the zip file for Windows. - It will have a name like: `aptos-cli--Windows-x86_64.zip` - You will likely have to dismiss warnings that this is a suspicious file when downloading. 4. Unzip the downloaded file. - Move the file to whichever folder you would like to call `aptos` from in the future. 5. Right click, then copy the path to the executable. Ex. `C:\Users\\Downloads\aptos-cli-3.1.0-Windows-x86_64\aptos.exe`. 6. Open PowerShell via the Start Menu. 7. Verify the installation by running the help command. Use the path you copied earlier to call the Aptos CLI. Ex. `C:\Users\\Downloads\aptos-cli-3.1.0-Windows-x86_64\aptos.exe help`. # Managing a Network Node via Aptos CLI > Learn how to manage validator nodes and validator full nodes using the Aptos CLI for staking pool operations and governance voting. If you are running a [validator node or validator full node (VFN)](/network/nodes/validator-node), you can use the CLI to interact with your node. Specifically, you can use the CLI to: 1. [Manage staking pools you own](/network/nodes/validator-node/connect-nodes/staking-pool-operations). 2. [Vote on proposals](/network/nodes/validator-node/connect-nodes/staking-pool-voter). Beyond that, you can run this help command to see more specialized commands the CLI can do relating to operating your node: ```shellscript filename="Terminal" aptos node --help ``` # Running a Public Network (Advanced) > Advanced guide to bootstrap and run a public Aptos network using genesis ceremonies, validator configurations, and blockchain initialization. import { Aside } from '@astrojs/starlight/components'; ## Genesis ceremonies The `aptos` tool supports bootstrapping new blockchains through what is known as a genesis ceremony. The output of the genesis ceremony is the output of move instructions that prepares a blockchain for online operation. The input consists of: - A set of validators and their configuration - The initial set of Move modules, known as a framework - A unique `ChainId` (u8) that distinguishes this from other networks - For test chains, there also exists an account that manages the minting of AptosCoin ## Generating genesis - The genesis organizer constructs a `Layout` and distributes it. - The genesis organizer prepares the Aptos framework's bytecode and distributes it. - Each participant generates their `ValidatorConfiguration` and distributes it. - Each participant generates a `genesis.blob` from the resulting contributions. - The genesis organizer executes the `genesis.blob` to derive the initial waypoint and distributes it. - Each participant begins their `aptos-node`. The `aptos-node` verifies upon startup that the `genesis.blob` with the waypoint provided by the genesis organizer. - The blockchain will begin consensus after a quorum of stake is available. ### Prepare aptos-core The following sections rely on tools from the Aptos source. See [Building Aptos From Source](/network/nodes/building-from-source) for setup. ### The `layout` file The layout file contains: - `root_key`: an Ed25519 public key for AptosCoin management. - `users`: the set of participants - `chain_id`: the `ChainId` or a unique integer that distinguishes this deployment from other Aptos networks An example: ```yaml root_key: "0xca3579457555c80fc7bb39964eb298c414fd60f81a2f8eedb0244ec07a26e575" users: - alice - bob chain_id: 8 ``` ### Building the Aptos Framework From your Aptos-core repository, build the framework and package it: ```shellscript filename="Terminal" cargo run --package framework mkdir aptos-framework-release cp aptos-framework/releases/artifacts/current/build/**/bytecode_modules/* aptos-framework-release ``` The framework will be stored within the `aptos-framework-release` directory. ### The `ValidatorConfiguration` file The `ValidatorConfiguration` file contains: - `account_address`: The account that manages this validator. This must be derived from the `account_key` provided within the `ValidatorConfiguration` file. - `consensus_key`: The public key for authenticating consensus messages from the validator - `account_key`: The public key for the account that manages this validator. This is used to derive the `account_address`. - `network_key`: The public key for both validator and fullnode network authentication and encryption. - `validator_host`: The network address where the validator resides. This contains a `host` and `port` field. The `host` should either be a DNS name or an IP address. Currently only IPv4 is supported. - `full_node_host`: An optional network address where the fullnode resides. This contains a `host` and `port` field. The `host` should either be a DNS name or an IP address. Currently only IPv4 is supported. - `stake_amount`: The number of coins being staked by this node. This is expected to be `1`, if it is different the configuration will be considered invalid. An example: ```yaml account_address: ccd49f3ea764365ac21e99f029ca63a9b0fbfab1c8d8d5482900e4fa32c5448a consensus_key: "0xa05b8f41057ac72f9ca99f5e3b1b787930f03ba5e448661f2a1fac98371775ee" account_key: "0x3d15ab64c8b14c9aab95287fd0eb894aad0b4bd929a5581bcc8225b5688f053b" network_key: "0x43ce1a4ac031b98bb1ee4a5cd72a4cca0fd72933d64b22cef4f1a61895c2e544" validator_host: host: bobs_host port: 6180 full_node_host: host: bobs_host port: 6182 stake_amount: 1 ``` To generate this using the `aptos` CLI: 1. Generate your validator's keys: ```shellscript filename="Terminal" cargo run --package aptos -- genesis generate-keys --output-dir bobs ``` 2. Generate your `ValidatorConfiguration`: ```shellscript filename="Terminal" cargo run --package aptos -- \\ genesis set-validator-configuration \\ --keys-dir bobs \\ --username bob \\ --validator-host bobs_host:6180 \\ --full-node-host bobs_host:6180 \\ --local-repository-dir . ``` 3. The last command will produce a `bob.yaml` file that should be distributed to other participants for `genesis.blob` generation. ### Generating a genesis and waypoint `genesis.blob` and the waypoint can be generated after obtaining the `layout` file, each of the individual `ValidatorConfiguration` files, and the framework release. It is important to validate that the `ValidatorConfiguration` provided in the earlier stage is the same as in the distribution for generating the `genesis.blob`. If there is a mismatch, inform all participants. To generate the `genesis.blob` and waypoint: - Place the `layout` file in a directory, e.g., `genesis`. - Place all the `ValidatorConfiguration` files into the `genesis` directory. - Ensure that the `ValidatorConfiguration` files are listed under the set of `users` within the `layout` file. - Make a `framework` directory within the `genesis` directory and place the framework release `.mv` files into the `framework` directory. - Use the `aptos` CLI to generate genesis and waypoint: ```shellscript filename="Terminal" cargo run --package aptos -- genesis generate-genesis --local-repository-dir genesis ``` ### Starting an `aptos-node` Upon generating the `genesis.blob` and waypoint, place them into your validator and fullnode's configuration directory and begin your validator and fullnode. # Replaying Past Transactions > Learn how to replay historical blockchain transactions locally for debugging, benchmarking, and gas profiling using the Aptos CLI. import { Aside, FileTree } from '@astrojs/starlight/components'; ## Basics You can replay past transactions locally using the `aptos move replay` command. The command is fairly straightforward but it requires you to specify two pieces of required information: - `--network` - This is the network you want to replay on - Possible values: `mainnet`, `testnet`, `devnet` or `` - `--txn-id` - This is the id of the transaction you want to replay - This is also sometimes being referred to as `version` on explorers - Specifically it is NOT the hexadecimal transaction hash Let's use mainnet transaction [581400718](https://explorer.aptoslabs.com/txn/581400718?network=mainnet) (a simple coin transfer transaction) as an example. ```shellscript filename="Terminal" aptos move replay --network mainnet --txn-id 581400718 ```
Output ```shellscript Got 1/1 txns from RestApi. Replaying transaction... { "Result": { "transaction_hash": "0x1ba73d03a0442a845735a17c7be46f3b51e2acb0e5cf68749305c5a17539ac63", "gas_used": 7, "gas_unit_price": 100, "sender": "c94e16736910cc160347d01de345407fe2d350fce5635ac1150319b0fbf5630e", "sequence_number": 14637, "success": true, "version": 581400718, "vm_status": "status EXECUTED of type Execution" } } ```
Alternatively, if you want to simulate a new transaction, check out [Local Simulation, Benchmarking and Gas Profiling](/build/cli/working-with-move-contracts/local-simulation-benchmarking-and-gas-profiling). ## Alternate Modes Similar to local simulations, the replay command can be enhanced with one of the following options: - `--benchmark`: Benchmark the transaction and report the running time(s). - `--profile-gas` Profile the transaction for detailed gas usage. ### Benchmarking ```shellscript filename="Terminal" aptos move replay --network mainnet --txn-id 581400718 --benchmark ```
Output ```shellscript Got 1/1 txns from RestApi. Benchmarking transaction... Running time (cold code cache): 914.821µs Running time (warm code cache): 820.189µs { "Result": { "transaction_hash": "0x1ba73d03a0442a845735a17c7be46f3b51e2acb0e5cf68749305c5a17539ac63", "gas_used": 7, "gas_unit_price": 100, "sender": "c94e16736910cc160347d01de345407fe2d350fce5635ac1150319b0fbf5630e", "sequence_number": 14637, "success": true, "version": 581400718, "vm_status": "status EXECUTED of type Execution" } } ```
It's worth noting that these running times serve only as informational references, as they are contingent upon the specifications of your local machine and may be influenced by noise or other random factors. **If you are aiming to optimize your contract, you should base your decisions on the gas profiling results.** ### Gas Profiling The Aptos Gas Profiler is a powerful tool that can help you understand the gas usage of Aptos transactions. Once activated, it will simulate transactions using an instrumented VM, and generate a web-based report. The gas profiler can also double as a debugger since the report also includes a full execution trace. ```shellscript filename="Terminal" aptos move replay --network mainnet --txn-id 581400718 --profile-gas ```
Output ```shellscript Got 1/1 txns from RestApi. Profiling transaction... Gas report saved to gas-profiling/txn-1ba73d03-0x1-aptos_account-transfer. { "Result": { "transaction_hash": "0x1ba73d03a0442a845735a17c7be46f3b51e2acb0e5cf68749305c5a17539ac63", "gas_used": 7, "gas_unit_price": 100, "sender": "c94e16736910cc160347d01de345407fe2d350fce5635ac1150319b0fbf5630e", "sequence_number": 14637, "success": true, "version": 581400718, "vm_status": "status EXECUTED of type Execution" } } ```
You can then find the [generated gas report](/gas-profiling/sample-report-2/index.html) in the directory gas-profiling: - gas-profiling/ - txn-1ba73d03-0x1-aptos\_account-transfer/ - assets/ - index.html To understand the gas report, please refer to [this section](/build/cli/working-with-move-contracts/local-simulation-benchmarking-and-gas-profiling#understanding-the-gas-report) of the local simulation tutorial. # Running a Localnet via Aptos CLI > Set up and run a local Aptos network for testing and development with Docker, including Node API, Indexer API, and faucet services. import { Aside, Steps } from '@astrojs/starlight/components'; Local networks can be helpful when testing your code. They are not connected to any production Aptos networks like mainnet, but they are useful for three main reasons: 1. **No rate limits:** You can interact with hosted services like the Node API, Indexer API, and faucet with no rate-limits to speed up testing. 2. **Reproducibility:** You can set up specific on-chain scenarios and restart the network from scratch at any point to return to a clean slate. 3. **High availability**: The Aptos devnet and testnet networks are periodically upgraded, during which time they can be unavailable. Local development networks are also always available even if you have no internet access.
# Starting A Local Network 1. Ensure you have the installed. 2. Ensure you have installed. 1. This is exclusively needed for making a production-like environment by running the Indexer API. Many downstream tools such as the Aptos SDK depend on the Indexer API. 2. Docker recommends that you install via [Docker Desktop](https://www.docker.com/products/docker-desktop/) to get automatic updates. 3. Start Docker. 4. Run the following command in a new terminal to start the private network: ```shellscript filename="Terminal" aptos node run-local-testnet --with-indexer-api ``` You should expect to see an output similar to this: ```shellscript filename="Terminal" Readiness endpoint: http://0.0.0.0:8070/ Indexer API is starting, please wait... Node API is starting, please wait... Transaction stream is starting, please wait... Postgres is starting, please wait... Faucet is starting, please wait... Completed generating configuration: Log file: "/Users/dport/.aptos/testnet/validator.log" Test dir: "/Users/dport/.aptos/testnet" Aptos root key path: "/Users/dport/.aptos/testnet/mint.key" Waypoint: 0:397412c0f96b10fa3daa24bfda962671c3c3ae484e2d67ed60534750e2311f3d ChainId: 4 REST API endpoint: http://0.0.0.0:8080 Metrics endpoint: http://0.0.0.0:9101/metrics Aptosnet fullnode network endpoint: /ip4/0.0.0.0/tcp/6181 Indexer gRPC node stream endpoint: 0.0.0.0:50051 Aptos is running, press ctrl-c to exit Node API is ready. Endpoint: http://0.0.0.0:8080/ Postgres is ready. Endpoint: postgres://postgres@127.0.0.1:5433/local_testnet Transaction stream is ready. Endpoint: http://0.0.0.0:50051/ Indexer API is ready. Endpoint: http://127.0.0.1:8090 Faucet is ready. Endpoint: http://127.0.0.1:8081/ Applying post startup steps... Setup is complete, you can now use the local testnet! ``` 5. Wait for the network to start Once the terminal says `Setup is complete, you can now use the local testnet!` the local network will be running.
Common Errors On Network Startup ### Address Already In Use ```shellscript filename="Terminal" panicked at 'error binding to 0.0.0.0:8080: error creating server listener: Address already in use (os error 48)' ``` This means one of the ports needed by the local network is already in use by another process. To fix this on Unix systems, you can: 1. Identify the name and PID of the process by running `lsof -i :8080`. 2. Run `kill ` once you know the PID to free up that port. ### Too many open files error ```shellscript filename="Terminal" panicked at crates/aptos/src/node/local_testnet/logging.rs:64:10: called \`Result::unwrap()\` on an \`Err\` value: Os { code: 24, kind: Uncategorized, message: \"Too many open files\" } ``` This means there were too many open files on your system. On many Unix systems you can increase the maximum number of open files by adding something like this to your `.zshrc`: ```shellscript filename="Terminal" ulimit -n 1048576 ``` ### Docker is not available ```shellscript filename="Terminal" Unexpected error: Failed to apply pre-run steps for Postgres: Docker is not available, confirm it is installed and running. On Linux you may need to use sudo ``` To debug this, try the below fixes: 1. Make sure you have docker installed by running `docker --version`. 2. Ensure the Docker daemon is running by running `docker info` (if this errors saying `Cannot connect to the Docker daemon` Docker is NOT running). 3. Make sure the socket for connecting to Docker is present on your machine in the default location. For example, on Unix systems `/var/run/docker.sock` should exist. 1. If that file does not exist, open Docker Desktop and enable `Settings -> Advanced -> Allow the default Docker socket to be used`. 2. Or, you can find where the Docker socket is by running `docker context inspect | grep Host`, then symlink that location to the default location by running `sudo ln -s /Users/dport/.docker/run/docker.sock /var/run/docker.sock`
As you can see from the example output in step 4, once the local network is running, you have access to the following services: - [Node API](/build/apis/fullnode-rest-api): This is a REST API that runs directly on the node. It enables core write functionality such as transaction submission and a limited set of read functionality, such as reading account resources or Move module information. - [Indexer API](/build/indexer/indexer-api): This is a [GraphQL](https://graphql.org/) API that provides rich read access to indexed blockchain data. If you click on the URL for the Indexer API above, by default [http://127.0.0.1:8090](http://127.0.0.1:8090), it will open the Hasura Console, a web UI that will help you query the Indexer GraphQL API. - [Transaction Stream Service](/build/indexer/txn-stream): This is a gRPC stream of transactions used by the Indexer API and SDK. This is only relevant to you if you are developing a [Indexer SDK](/build/indexer/indexer-sdk) custom processor. - [Postgres](https://www.postgresql.org/): This is the database that the Indexer processors write to. The Indexer API reads from this database. - [Faucet](/build/apis/faucet-api): You can use this to fund accounts on your local network. If you do not want to run any of these sub-components of a network, there are flags to disable them. If you are writing a script and would like to wait for the local network to come up with all services, you can make a GET request to `http://127.0.0.1:8070`. At first this will return http code [503](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503). When it returns [200](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200) it means all the services are ready. For more information on different flags you can pass when starting your local network, or configuration settings such as changing which port certain services run on, run the help command: ```shellscript filename="Terminal" aptos node run-local-testnet --help ```
## Using The Local Network Now that the network is running, you can use it like you would any other network. So, you can create a local profile like this: ```shellscript filename="Terminal" aptos init --profile --network local ``` You can then use that profile for any commands you want to use going forward. For example, if you wanted to publish a Move module like the [`hello_blockchain`](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/hello_blockchain) package to your local network you could run: ```shellscript filename="Terminal" aptos move publish --profile --package-dir /opt/git/aptos-core/aptos-move/move-examples/hello_blockchain --named-addresses HelloBlockchain=local ``` ### Configuring the TypeScript SDK If you want to use the local network with the TypeScript SDK, you can use local network URLs when initializing the client object (`Aptos`): ```tsx import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk"; const network = Network.LOCAL; const config = new AptosConfig({ network }); const client = new Aptos(config); ``` ### Resetting the local network Sometimes while developing it is helpful to reset the local network back to its initial state, for example: - You made backwards incompatible changes to a Move module, and you'd like to redeploy it without renaming it or using a new account. - You are building an [Indexer SDK](/build/indexer/indexer-sdk) custom processor and would like to index using a fresh network. - You want to clear all on chain state, e.g., accounts, objects, etc. To start with a brand new local network, use the `--force-restart` flag: ```shellscript filename="Terminal" aptos node run-local-testnet --force-restart ``` It will then prompt you if you really want to restart the chain, to ensure that you do not delete your work by accident. ```shellscript filename="Terminal" Are you sure you want to delete the existing chain? [yes/no] > yes ``` If you do not want to be prompted, include `--assume-yes` as well: ```shellscript filename="Terminal" aptos node run-local-testnet --force-restart --assume-yes ``` # Setup CLI Initial Configuration > Learn how to configure the Aptos CLI with network settings, profiles, and credentials for secure and efficient blockchain interactions. import { Aside } from '@astrojs/starlight/components'; If you are using the CLI to try things out on-chain, you will need to configure the network, faucet, and credentials you want the CLI to use. This makes using the CLI easier and more secure as you will not be forced to repeatedly copy addresses or private keys. 1. Run `aptos init` and follow the instructions in the command line. ```shellscript filename="Terminal" aptos init ``` ```shellscript filename="Output" Configuring for profile default Enter your rest endpoint [Current: None | No input: https://api.devnet.aptoslabs.com] No rest url given, using https://api.devnet.aptoslabs.com... Enter your faucet endpoint [Current: None | No input: https://faucet.devnet.aptoslabs.com] No faucet url given, using https://faucet.devnet.aptoslabs.com... Enter your private key as a hex literal (0x...) [Current: None | No input: Generate new key (or keep one if present)] No key given, generating key... Account 00f1f20ddd0b0dd2291b6e42c97274668c479bca70f07c6b6a80b99720779696 doesn't exist, creating it and funding it with 10000 coins Aptos is now set up for account 00f1f20ddd0b0dd2291b6e42c97274668c479bca70f07c6b6a80b99720779696! Run `aptos help` for more information about commands { "Result": "Success" } ``` 2. Later, if you want to update these settings, you can do so by running `aptos init` again. 3. The rest of these configuration steps are optional / quality of life. To continue to use the CLI for your specific use case, follow the [usage guide here](/build/cli#%EF%B8%8F-using-the-aptos-cli). ## (Optional) Creating Named Configurations (Profiles) For testing more complicated scenarios, you will often want multiple accounts on-chain. One way to do this is to create a named configuration which we call a profile. To create a profile, run `aptos init --profile `. The configuration you generate will be usable when calling CLI commands as replacements for arguments. For example: ```shellscript filename="Terminal" aptos init --profile bob ``` ```shellscript filename="Terminal" aptos account fund-with-faucet --profile bob ``` ```shellscript filename="Output" { "Result": "Added 100000000 Octas to account 0x63169727b08fc137b8720e451f7a90584ccce04c301e151daeadc7b8191fdfad" } ``` ## (Optional) Setting Up Shell Completion One quality of life feature you can enable is shell auto-completions. 1. Determine which shell you are using (you can run `echo $SHELL` if you are unsure). 2. Look up where configuration files for shell completions go for that shell (it varies from shell to shell). The supported shells are `[bash, zsh, fish, PowerShell, elvish]`. 3. Run the following command with your specific shell and the output file for completions using your shell: ```shellscript filename="Terminal" aptos config generate-shell-completions --shell --output-file ``` Example command for [`oh my zsh`](https://ohmyz.sh/): ```shellscript filename="Terminal" aptos config generate-shell-completions --shell zsh --output-file ~/.oh-my-zsh/completions/_aptos ``` ## (Optional) Global Config By default, the CLI will look for a configuration in `.aptos/config.yaml` in each workspace directory. If you would like to use a shared configuration for all workspaces, you can follow these steps: 1. Create a folder in your home directory called `.aptos` (so it has the path `~/.aptos`). 2. Create a yaml file inside `.aptos` called `global_config.yaml`. 3. Run the command: ```shellscript filename="Terminal" aptos config set-global-config --config-type global ``` You should see: ```json { "Result": { "config_type": "Global" } } ``` # Install the Move Prover > Step-by-step guide to install and set up the Move Prover dependencies for formal verification of Move smart contracts using the Aptos CLI. import { Aside } from '@astrojs/starlight/components'; If you want to use the [Move Prover](/build/smart-contracts/prover), install the Move Prover dependencies after [installing the CLI binary](/build/cli/setup-cli). There are two ways to install Prover dependencies. ## Installation through Aptos CLI (Recommended) 1. [Install the latest Aptos CLI binary](/build/cli/install-cli/install-cli-mac). 2. Execute the command `aptos update prover-dependencies`. ## Installation through `aptos-core` (Not Recommended) 1. See [Building Aptos From Source](/network/nodes/building-from-source) 2. Then, in the checked out aptos-core directory, install additional Move tools:
Linux / macOS 1. Open a Terminal session. 2. Run the dev setup script to prepare your environment: `./scripts/dev_setup.sh -yp` 3. Update your current shell environment: `source ~/.profile`
Windows 1. Open a PowerShell terminal as an administrator. 2. Run the dev setup script to prepare your environment: `PowerShell -ExecutionPolicy Bypass -File ./scripts/windows_dev_setup.ps1 -y`
After installation, you can run the Move Prover to prove an [example](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/hello_prover): ```shellscript filename="Terminal" aptos move prove --package-dir aptos-move/move-examples/hello_prover/ ``` ## Troubleshooting If you encounter errors like the one below when running the command, double-check your Aptos CLI version or verify that you're using the correct `aptos` tool, especially if you have multiple versions installed. ```shellscript filename="Terminal error: unexpected token ┌─ ~/.move/https___github_com_aptos-labs_aptos-core_git_main/aptos-move/framework/aptos-framework/sources/randomness.move:515:16 │ 515 │ for (i in 0..n) { │ - ^ Expected ')' │ │ │ To match this '(' { "Error": "Move Prover failed: exiting with model building errors" } ``` # Start a Move package from a template > Quickly bootstrap new Move projects using built-in templates with the Aptos CLI, including the hello-blockchain template and customization options. import { CardGrid, LinkCard, Steps } from '@astrojs/starlight/components'; import { RemoteCodeblock } from '~/components/RemoteCodeblock'; Follow the steps below to quickly get started. 1. Initialize Run the following to initialize a package using the `hello-blockchain` template: ```shellscript filename="Terminal" aptos move init --name hello_blockchain --template hello-blockchain ``` 2. Start building The template creates a `hello_blockchain.move` file under `sources` to help get you started. 3. See all templates Run the following command to see all templates (and for general help initializing a package): ```shellscript aptos move init --help ``` ### Learn More # Trying Things On-Chain With Aptos CLI > Learn how to interact with the Aptos blockchain using CLI profiles, including account management, transaction sending, and hardware wallet integration. The CLI can be a convenient tool for quickly looking up on-chain data and sending transactions from your accounts. The most common way to specify what accounts you want to interact with is through profiles. You can create a new profile on the cli by running the following command: ```shellscript filename="Terminal" aptos init --profile ``` If any command takes an account, you can pass in the name of a profile instead. If a command implicitly uses the default profile, it will usually have an optional parameter to use a specified profile instead which you can find by running `aptos --help`. With that, the three main things you can use the CLI to do on-chain include: 1. [Looking Up On-Chain Account Info](/build/cli/trying-things-on-chain/looking-up-account-info) 2. [Creating test accounts and sending transactions](/build/cli/trying-things-on-chain/create-test-accounts) 3. [Securely interacting on-chain via a Hardware Ledger](/build/cli/trying-things-on-chain/ledger) # Create Test Accounts and Send Transactions From Aptos CLI > Learn how to create test accounts, fund them with faucet tokens, and send transactions between accounts using the Aptos CLI for testing and development. import { Aside } from '@astrojs/starlight/components'; In general, to make a new account on-chain, you will need to generate keys and then fund the account. On devnet, you can fund a new account by asking a "faucet" account with test Aptos tokens to send them to your account. On testnet you can mint at the [mint page](/network/faucet). Using the CLI, you can generate and fund a test account using: ```shellscript filename="Terminal" aptos init --profile ``` Once you have a funded account you can send coins between accounts with the `transfer` command like this: ```shellscript filename="Terminal" aptos account transfer --account superuser --amount 100 ``` You should see a result like: ```json filename="Output" { "Result": { "gas_used": 73, "balance_changes": { "742854f7dca56ea6309b51e8cebb830b12623f9c9d76c72c3242e4cad353dedc": { "coin": { "value": "10100" }, "deposit_events": { "counter": "2", "guid": { "id": { "addr": "0x742854f7dca56ea6309b51e8cebb830b12623f9c9d76c72c3242e4cad353dedc", "creation_num": "1" } } }, "withdraw_events": { "counter": "0", "guid": { "id": { "addr": "0x742854f7dca56ea6309b51e8cebb830b12623f9c9d76c72c3242e4cad353dedc", "creation_num": "2" } } } }, "b9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb": { "coin": { "value": "9827" }, "deposit_events": { "counter": "1", "guid": { "id": { "addr": "0xb9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "creation_num": "1" } } }, "withdraw_events": { "counter": "1", "guid": { "id": { "addr": "0xb9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "creation_num": "2" } } } } }, "sender": "b9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "success": true, "version": 1139, "vm_status": "Executed successfully" } } ``` This can be useful for manual testing of Move contracts or just to try seeing how the chain works in practice. # Use Hardware Ledger via the Aptos CLI > Learn how to securely interact with the Aptos blockchain using hardware Ledger devices, including setup, key rotation, and transaction signing. import { Aside, Steps } from '@astrojs/starlight/components'; Using a hardware wallet like Ledger is the most secure way to sign transactions on `mainnet` as your private key never leaves your device. ## Initial Setup You will need to do a few steps of configuration for the Aptos CLI and your Ledger device to sign transactions. 1. Ensure you have the Aptos CLI installed. You can install the Aptos CLI by following [these steps](/build/cli) if you have not done so already. 2. Ensure you have done the basic setup for your Ledger device. You can find those steps on [Ledger’s website](https://www.ledger.com/). For example, here are the set up instructions for the [Ledger Nano X](https://support.ledger.com/article/360018784134-zd). 3. Plug your Ledger device into your computer. 4. Install the Aptos App on your Ledger device by following . 5. Unlock your Ledger device and open the Aptos app. 6. Create a new Ledger profile in the Aptos CLI ```shellscript filename="Terminal" aptos init --profile --ledger ``` Then follow the terminal prompts like so: ```text filename="Terminal" Configuring for profile Choose network from [devnet, testnet, mainnet, local, custom | defaults to devnet] No network given, using devnet... Please choose an index from the following 5 ledger accounts, or choose an arbitrary index that you want to use: [0] Derivation path: m/44'/637'/0'/0'/0' (Address: 59836ba1dd0c845713bdab34346688d6f1dba290dbf677929f2fc20593ba0cfb) [1] Derivation path: m/44'/637'/1'/0'/0' (Address: 21563230cf6d69ee72a51d21920430d844ee48235e708edbafbc69708075a86e) [2] Derivation path: m/44'/637'/2'/0'/0' (Address: 667446181b3b980ef29f5145a7a2cc34d433fc3ee8c97fc044fd978435f2cb8d) [3] Derivation path: m/44'/637'/3'/0'/0' (Address: 2dcf037a9f31d93e202c074229a1b69ea8ee4d2f2d63323476001c65b0ec4f31) [4] Derivation path: m/44'/637'/4'/0'/0' (Address: 23c579a9bdde1a59f1c9d36d8d379aeefe7a5997b5b58bd5a5b0c12a4f170431) 0 Account 59836ba1dd0c845713bdab34346688d6f1dba290dbf677929f2fc20593ba0cfb has been already found on-chain --- Aptos CLI is now set up for account 59836ba1dd0c845713bdab34346688d6f1dba290dbf677929f2fc20593ba0cfb as profile ! Run `aptos --help` for more information about commands { "Result": "Success" } ``` In the example, they chose to use the first ledger account by entering `0` after the `aptos init` command. You may choose whichever account you want. **Common errors:** 1. If you see the error `Device Not Found`, make sure to unlock your Ledger then try this step again. 2. If you see the error `Aptos ledger app is not opened`, make sure to open the Aptos app on your Ledger, then try this step again. 7. Finally, you will need to enable blind signing on your Ledger device by following . 1. Blind signing allows you to confirm a smart contract interaction you cannot verify through a human-readable language. 2. This is needed to execute transactions without limitation as some payloads are too big to display. ## Signing Using Ledger After doing the initial setup, you can sign transactions by following these steps: 1. Plug in your ledger. 2. Unlock it. 3. Open the Aptos app. 4. Run the Aptos CLI command which requires a signature. For example, if you wanted to publish a Move package like the [`hello_blockchain`](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/hello_blockchain) demo contract you could follow the above steps then run: ```shellscript filename="Terminal" aptos move publish --profile --named-addresses hello_blockchain= ``` You should see a response like: ```shellscript filename="Terminal" Compiling, may take a little while to download git dependencies... INCLUDING DEPENDENCY AptosFramework INCLUDING DEPENDENCY AptosStdlib INCLUDING DEPENDENCY MoveStdlib BUILDING Examples package size 1755 bytes Do you want to submit a transaction for a range of [139600 - 209400] Octas at a gas unit price of 100 Octas? [yes/no] > yes { "Result": { "transaction_hash": "0xd5a12594f85284cfd5518d547d084030b178ee926fa3d8cbf699cc0596eff538", "gas_used": 1396, "gas_unit_price": 100, "sender": "59836ba1dd0c845713bdab34346688d6f1dba290dbf677929f2fc20593ba0cfb", "sequence_number": 0, "success": true, "timestamp_us": 1689887104333038, "version": 126445, "vm_status": "Executed successfully" } } ``` After you have approved publishing this package you will be prompted to sign the transaction on your Ledger device. Once signed, the package will be published to the network! One error you might run into is `Error: Wrong raw transaction length`. This means that the transaction or package size was too big for your device to sign. Currently the Aptos Ledger app can only support transactions that are smaller than 20kb. The `Ledger Nano S` device has less memory than that, which is why it is more likely to produce this error. ## Authentication key rotation If you have an active account that is not secured using a hardware wallet, then you may wish to rotate the account's authentication key so that it corresponds to a [BIP44 account index] private key held on your Ledger. Alternatively, if you have an account linked with a Ledger hardware wallet that you wish to publish a large package from, you might want to temporarily rotate the account's authentication key to a hot key to avoid memory issues. This tutorial will walk you through both scenarios. 1. Complete the key rotation guide Confirm that you have completed the [key rotation guide](/build/guides/key-rotation). 2. Verify your Ledger is ready 1. Connect and unlock your Ledger. 2. Check what version of the Aptos app you have: `Aptos > About > Version`. 3. If you do not have version `0.6.9` or higher, update it using Ledger Live. 4. Enable blind signing: `Aptos > Settings > Enable Blind Signing`. 3. Start a localnet Start a localnet: ```shellscript filename="Terminal" aptos node run-localnet ``` The localnet is ready when it prints out: ```shellscript filename="Terminal" Applying post startup steps... Setup is complete, you can now use the localnet! ``` 4. Set up localnet hot wallet profile Create a private key corresponding to an authentication key, and thus initial account address, that starts with the vanity prefix `0xaaa`: ```shellscript filename="Terminal" aptos key generate \ --assume-yes \ --output-file private-key-a \ --vanity-prefix 0xaaa ```
Example output ```shellscript filename="Terminal" { "Result": { "PublicKey Path": "private-key-a.pub", "PrivateKey Path": "private-key-a", "Account Address:": "0xaaac71af5f2a4af4ec2639a15799bf9b945afb061c8bee102b636531c1b00eb5" } } ```
Use the private key to initialize a `hot-wallet-1` profile on the localnet: ```shellscript filename="Terminal" aptos init \ --assume-yes \ --network local \ --private-key-file private-key-a \ --profile hot-wallet-1 ```
Example output ```shellscript filename="Terminal" Configuring for profile hot-wallet-1 Configuring for network Local Using command line argument for private key Account 0xaaac71af5f2a4af4ec2639a15799bf9b945afb061c8bee102b636531c1b00eb5 doesn\'t exist, creating it and funding it with 100000000 Octas Account 0xaaac71af5f2a4af4ec2639a15799bf9b945afb061c8bee102b636531c1b00eb5 funded successfully --- Aptos CLI is now set up for account 0xaaac71af5f2a4af4ec2639a15799bf9b945afb061c8bee102b636531c1b00eb5 as profile hot-wallet-1! Run `aptos --help` for more information about commands { "Result": "Success" } ```
5. Rotate the hot wallet key Rotate the authentication key of the hot wallet to use [BIP44 account index] 1000 on your Ledger: ```shellscript filename="Terminal" aptos account rotate-key \ --assume-yes \ --new-derivation-index 1000 \ --profile hot-wallet-1 \ --save-to-profile ledger-wallet-1000 ``` Follow the instructions from the CLI prompt: ```shellscript filename="Terminal" Approve rotation proof challenge signature on your Ledger device ```
Example output ```shellscript filename="Terminal" { "Result": { "message": "Saved new profile ledger-wallet-1000", "transaction": { "transaction_hash": "0x1a6df99651ac170bda10cfb9898fa196321d80a928033791b9d2231f77738bb2", "gas_used": 448, "gas_unit_price": 100, "sender": "aaac71af5f2a4af4ec2639a15799bf9b945afb061c8bee102b636531c1b00eb5", "sequence_number": 0, "success": true, "timestamp_us": 1717986382369736, "version": 186, "vm_status": "Executed successfully" } } } ```
Compare the `hot-wallet-1` and `ledger-wallet-1000` profiles, noting that they have the same `account` address but different `public_key` values: ```shellscript filename="Terminal" aptos config show-profiles --profile hot-wallet-1 aptos config show-profiles --profile ledger-wallet-1000 ```
Example output ```shellscript filename="Terminal" { "Result": { "hot-wallet-1": { "has_private_key": true, "public_key": "0xffb1240fd1267207cc3ed2e1b5386e090a9ca2c844d7f9e0077b3d7dd5d5e430", "account": "aaa271bca468fb8518f73a732a484b29a1bc296ebcb23f15639d4865a5cebe87", "rest_url": "http://localhost:8080", "faucet_url": "http://localhost:8081" } } } { "Result": { "ledger-wallet-1000": { "has_private_key": false, "public_key": "0x20ba83f9b9fdab73b0ace8fda26ce24c98cf55060b72b69cfbd25add6a25d09b", "account": "aaa271bca468fb8518f73a732a484b29a1bc296ebcb23f15639d4865a5cebe87", "rest_url": "http://localhost:8080", "faucet_url": "http://localhost:8081" } } } ```
Since the account is no longer secured by the hot private key, delete the private and public key files. Now that you have successfully rotated the authentication key of the hot wallet, you can delete the profiles too: ```shellscript filename="Terminal" aptos config delete-profile --profile hot-wallet-1 aptos config delete-profile --profile ledger-wallet-1000 ```
Example output ```shellscript filename="Terminal" { "Result": "Deleted profile hot-wallet-1" } { "Result": "Deleted profile ledger-wallet-1000" } ```
6. Recover profile Since you know that you rotated the authentication key of the hot wallet to the Ledger, and since you used the best practice of a [BIP44 account index] offset of 1000, you can easily recover the profile using the [BIP44 account index] alone: ```shellscript filename="Terminal" aptos init \ --assume-yes \ --derivation-index 1000 \ --network local \ --profile ledger-wallet-1000-recovered ```
Example output ```shellscript filename="Terminal" Configuring for profile ledger-wallet-1000-recovered Configuring for network Local Account 0xaaac71af5f2a4af4ec2639a15799bf9b945afb061c8bee102b636531c1b00eb5 has been already found onchain --- Aptos CLI is now set up for account 0xaaac71af5f2a4af4ec2639a15799bf9b945afb061c8bee102b636531c1b00eb5 as profile ledger-wallet-1000-recovered! Run `aptos --help` for more information about commands { "Result": "Success" } ```
Note that this profile corresponds to the specified `0xaaa...` vanity account address: ```shellscript filename="Terminal" aptos config show-profiles --profile ledger-wallet-1000-recovered ```
Example output ```shellscript filename="Terminal" { "Result": { "ledger-wallet-1000-recovered": { "has_private_key": false, "public_key": "0x20ba83f9b9fdab73b0ace8fda26ce24c98cf55060b72b69cfbd25add6a25d09b", "account": "aaac71af5f2a4af4ec2639a15799bf9b945afb061c8bee102b636531c1b00eb5", "rest_url": "http://localhost:8080", "faucet_url": "http://localhost:8081" } } } ```
7. Rotate to new hot private key If you have an account linked with a Ledger hardware wallet that you wish to use for publication of a large package, you'll be unable to sign the package publication transaction due to the Ledger's memory limitations. In this case, you'll want to temporarily rotate to a hot wallet. Start by generating a new private key: ```shellscript filename="Terminal" aptos key generate \ --assume-yes \ --output-file private-key-b \ --vanity-prefix 0xbbb ```
Example output ```shellscript filename="Terminal" { "Result": { "PublicKey Path": "private-key-b.pub", "PrivateKey Path": "private-key-b", "Account Address:": "0xbbbede2b4f1d49eff0b156ab0756889a6f2bb68f215399d5015da9ac45921b47" } } ```
Rotate the authentication key of the account linked with the Ledger to the new private key: ```shellscript filename="Terminal" aptos account rotate-key \ --assume-yes \ --new-private-key-file private-key-b \ --profile ledger-wallet-1000-recovered \ --save-to-profile temporary-hot-wallet ``` Follow the instructions from the CLI prompt: ```shellscript filename="Terminal" Approve rotation proof challenge signature on your Ledger device ``` ```shellscript filename="Terminal" Approve transaction on your Ledger device ```
Example output ```shellscript filename="Terminal" { "Result": { "message": "Saved new profile temporary-hot-wallet", "transaction": { "transaction_hash": "0xe49782e92d8fd824fd6dce8f6ed42a11cf8ee84c201f3aa639c435e737c80eaa", "gas_used": 449, "gas_unit_price": 100, "sender": "aaac71af5f2a4af4ec2639a15799bf9b945afb061c8bee102b636531c1b00eb5", "sequence_number": 1, "success": true, "timestamp_us": 1717986617911082, "version": 631, "vm_status": "Executed successfully" } } ```
Since the CLI profile `ledger-wallet-1000-recovered` is now stale, rename it in case you get interrupted and forget that the private key has been rotated: ```shellscript filename="Terminal" aptos config rename-profile \ --profile ledger-wallet-1000-recovered \ --new-profile-name ledger-wallet-1000-stale ```
Example output ```shellscript filename="Terminal" { "Result": "Renamed profile ledger-wallet-1000-recovered to ledger-wallet-1000-stale" } ```
8. Rotate back to Ledger Once you've signed the large package publication transaction with the hot key, you can then rotate the authentication key back to the corresponding to the private key on the Ledger at index 1000: ```shellscript filename="Terminal" aptos account rotate-key \ --assume-yes \ --new-derivation-index 1000 \ --profile temporary-hot-wallet \ --save-to-profile ledger-wallet-1000 ``` Follow the instructions from the CLI prompt: ```shellscript filename="Terminal" Approve rotation proof challenge signature on your Ledger device ```
Example output ```shellscript filename="Terminal" { "Result": { "message": "Saved new profile ledger-wallet-1000", "transaction": { "transaction_hash": "0x9503819d4ea13bcd9eafed25984807d86d22e8a9837565a7495b54d13890d103", "gas_used": 449, "gas_unit_price": 100, "sender": "aaac71af5f2a4af4ec2639a15799bf9b945afb061c8bee102b636531c1b00eb5", "sequence_number": 2, "success": true, "timestamp_us": 1717986672963544, "version": 742, "vm_status": "Executed successfully" } } } ```
Verify that the `ledger-wallet-1000-stale` and `ledger-wallet-1000` profiles have the same `account` address and `public_key`: ```shellscript filename="Terminal" aptos config show-profiles --profile ledger-wallet-1000-stale aptos config show-profiles --profile ledger-wallet-1000 ``` Delete the `temporary-hot-wallet` and `ledger-wallet-1000-stale` profiles, which you no longer need. ```shellscript filename="Terminal" aptos config delete-profile --profile temporary-hot-wallet aptos config delete-profile --profile ledger-wallet-1000-stale ```
Example output ```shellscript filename="Terminal" { "Result": "Deleted profile temporary-hot-wallet" } { "Result": "Deleted profile ledger-wallet-1000-stale" } ```
Since you no longer need the temporary private key, delete it too. 9. Clean up Delete the remaining test profile: ```shell filename="Terminal" aptos config delete-profile --profile ledger-wallet-1000 ``` Then stop the localnet.
[`account::OriginatingAddress`]: https://github.com/aptos-labs/aptos-core/blob/acb6c891cd42a63b3af96561a1aca164b800c7ee/aptos-move/framework/aptos-framework/sources/account.move#L70 [BIP44 account index]: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki # Look Up On-Chain Account Info Using Aptos CLI > Learn how to query on-chain account information including balances, resources, and Move modules using the Aptos CLI with detailed examples and output explanations. import { Aside } from '@astrojs/starlight/components'; You can look up resources and data an account has on-chain by running the following command: ```shellscript filename="Terminal" aptos account list --account ``` This will show all resources that an account has. For example, below shows the balance as `coin:value`, and the associated coin for the native gas token APT would be `0x1::aptos_coin::AptosCoin`. This is represented in subdivisions, so in this case it's `10^-8` or 8 zeros of decimal points. ```json filename="Output" { "Result": [ { "coin": { "value": "110000" }, "deposit_events": { "counter": "3", "guid": { "id": { "addr": "0xf1f20ddd0b0dd2291b6e42c97274668c479bca70f07c6b6a80b99720779696", "creation_num": "2" } } }, "frozen": false, "withdraw_events": { "counter": "0", "guid": { "id": { "addr": "0xf1f20ddd0b0dd2291b6e42c97274668c479bca70f07c6b6a80b99720779696", "creation_num": "3" } } } } ] } ``` If you’re interested in a specific type of account data, you can specify that with the `--query` parameter. The supported queries are: - `balance` - to see the current balance and a list of deposit and withdrawal events. - `modules` - see the Move contracts that are published on this account. - `resources` - this is what the default command does with no query specified. Here’s an example of what calling with the `--query modules` parameter looks like: ```shellscript filename="Terminal" aptos account list --query modules ``` This will show all modules that an account has. For example: ```json filename="Output" { "Result": [ { "bytecode": "0xa11ceb0b050000000b01000a020a12031c2504410405452d0772da0108cc0240068c030a0a9603150cab03650d90040400000101010201030104000506000006080004070700020e0401060100080001000009020300010f0404000410060100031107000002120709010602130a030106050806080105010802020c0a02000103040508020802070801010a0201060c010800010b0301090002070b030109000900074d657373616765056572726f72056576656e74067369676e657206737472696e67124d6573736167654368616e67654576656e740d4d657373616765486f6c64657206537472696e670b6765745f6d6573736167650b7365745f6d6573736167650c66726f6d5f6d6573736167650a746f5f6d657373616765076d657373616765156d6573736167655f6368616e67655f6576656e74730b4576656e7448616e646c65096e6f745f666f756e6404757466380a616464726573735f6f66106e65775f6576656e745f68616e646c650a656d69745f6576656e74b9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb0000000000000000000000000000000000000000000000000000000000000001030800000000000000000002020a08020b08020102020c08020d0b030108000001000101030b0a002901030607001102270b002b0110001402010104010105240b0111030c040e0011040c020a02290120030b05120e000b040e00380012012d0105230b022a010c050a051000140c030a050f010b030a04120038010b040b050f0015020100010100", "abi": { "address": "0xb9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "name": "Message", "friends": [], "exposed_functions": [ { "name": "get_message", "visibility": "public", "is_entry": false, "generic_type_params": [], "params": [ "address" ], "return": [ "0x1::string::String" ] }, { "name": "set_message", "visibility": "public", "is_entry": true, "generic_type_params": [], "params": [ "signer", "vector" ], "return": [] } ], "structs": [ { "name": "MessageChangeEvent", "is_native": false, "abilities": [ "drop", "store" ], "generic_type_params": [], "fields": [ { "name": "from_message", "type": "0x1::string::String" }, { "name": "to_message", "type": "0x1::string::String" } ] }, { "name": "MessageHolder", "is_native": false, "abilities": [ "key" ], "generic_type_params": [], "fields": [ { "name": "message", "type": "0x1::string::String" }, { "name": "message_change_events", "type": "0x1::event::EventHandle<0xb9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb::Message::MessageChangeEvent>" } ] } ] } } ] } ``` # Working With Move Contracts > Comprehensive guide to compile, test, publish, and run Move smart contracts using the Aptos CLI with examples and best practices. import { Aside } from '@astrojs/starlight/components'; The Aptos CLI is mostly used to compile, test, and formally verify Move contracts. If you have not installed the Aptos CLI yet, you can do so by following the steps here [Install the Aptos CLI](/build/cli#-install-the-aptos-cli). You can jump to specific sections by using the table of contents on the right. To see how to chain together Move contracts on-chain using the CLI, you can follow this ["CLI Arguments" tutorial](/build/cli/working-with-move-contracts/arguments-in-json-tutorial). ## 1. Compiling Move You can compile a Move package by running: ```shellscript filename="Terminal" aptos move compile --package-dir ``` Based on the settings in your `Move.toml` file, you may need to pass in additional information to that compile command. For example, if you look at the [hello\_blockchain example Move contract](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/hello_blockchain), in the `Move.toml` file it specifies a variable named address called `hello_blockchain`. ```toml filename="Move.toml" [addresses] hello_blockchain = "_" ``` So, to compile this, you will need to pass in the value for `hello_blockchain` with the `--named-addresses` parameter. You can use either a full address e.g. `0x123456...7890` or a name of a profile in the CLI e.g. `default` or `superuser`. Below we will use `default` in our example: ```shellscript filename="Terminal" aptos move compile --package-dir aptos-move/move-examples/hello_blockchain/ --named-addresses hello_blockchain=default ``` You can learn more about optional parameters when compiling Move contracts by running `aptos move compile --help`. ## 2. Unit Testing Move Contracts The Aptos CLI can also be used to compile and run unit tests locally by running: ```shellscript filename="Terminal" aptos move test --package-dir ``` This command both compiles and runs tests, so it needs all the same optional parameters you use when compiling. You can learn more about the optional parameters for testing move contracts by running `aptos move test --help`. ### Printing Debugging Information When writing tests, it can be helpful to print out debug information or stack traces. You can do that by using `debug::print` and `debug::print_stack_trace` to print information when you use `aptos move test`. See an example of how they are used in [DebugDemo.move](https://github.com/aptos-labs/aptos-core/blob/main/crates/aptos/debug-move-example/sources/DebugDemo.move). To see the output of testing [DebugDemo.move](https://github.com/aptos-labs/aptos-core/blob/main/crates/aptos/debug-move-example/sources/DebugDemo.move)’s package: 1. Clone `[aptos-core](https://github.com/aptos-labs/aptos-core)`. 2. Navigate to the [debug-move-example](https://github.com/aptos-labs/aptos-core/tree/main/crates/aptos/debug-move-example) by running `cd crates/aptos/debug-move-example`. 3. Run `aptos move test`. You should see: ```shellscript filename="Terminal" Running Move unit tests [debug] 0000000000000000000000000000000000000000000000000000000000000001 Call Stack: [0] 0000000000000000000000000000000000000000000000000000000000000001::Message::sender_can_set_message Code: [4] CallGeneric(0) [5] MoveLoc(0) [6] LdConst(0) > [7] Call(1) [8] Ret Locals: [0] - [1] 0000000000000000000000000000000000000000000000000000000000000001 Operand Stack: ``` For more on how to write unit tests with Move, follow this [Move tutorial](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/move-tutorial) (step 2 focuses on unit tests). ## 3. Generating Test Coverage Reports The Aptos CLI can be used to analyze and improve the testing of your Move modules. To use this feature: To see the code coverage of your tests run the following command from your Move package’s directory: ```shellscript filename="Terminal" aptos move test --coverage ``` If you would like to focus your coverage down to specific packages, you can do so with the `--filter` option. To narrow even further to specific Move modules, use the `--module` parameter. For more detailed / advanced coverage information (such as your test coverage in the compiled bytecode) you can run `aptos move coverage` . With that command, the CLI will prompt you for more details on what specifically you would like more coverage information about. You can learn more about optional parameters for test coverage by running `aptos move test --help` and `aptos move coverage --help`. ## 4. Publishing Move Contracts To publish a Move contract, you will need to run: ```shellscript filename="Terminal" aptos move publish --package-dir ``` Note that when you are publishing on the main network, the credentials you pass into optional parameters like `--named-addresses` will need to reflect accounts on that network instead of test credentials. The package will be published to your default profile in the CLI. You can override that to specify which account to publish to using `--profile` in the command. To generate a new profile for a specific account, use `aptos init --profile ` and follow the prompts. Please also note that when publishing Move modules, if multiple modules are in one package, then all modules in that package must use the same account. If they use different accounts, then the publishing will fail at the transaction level. You can estimate the gas fees associated with publishing your Move contract by using the [Gas Profiler](/build/cli/working-with-move-contracts/local-simulation-benchmarking-and-gas-profiling). {/* TODO: Fix this link */} ## 5. Running Published Contracts Now that you have published your Move package, you can run it directly from the CLI. You will first need to construct your `function-id` by combining: ```jsx :::: ``` You can then pass in args by using the `--args` parameter. As an example, if you were to have published the [hello\_blockchain example package](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/hello_blockchain) to an account with an address `b9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb` you could run its `set_message` function via the following command: ```shellscript filename="Terminal" aptos move run --function-id 0xb9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb::message::set_message --args string:hello! ``` Which should result in: ```json { "Result": { "changes": [ { "address": "b9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "data": { "authentication_key": "0xb9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "self_address": "0xb9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "sequence_number": "3" }, "event": "write_resource", "resource": "0x1::account::Account" }, { "address": "b9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "data": { "coin": { "value": "9777" }, "deposit_events": { "counter": "1", "guid": { "id": { "addr": "0xb9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "creation_num": "1" } } }, "withdraw_events": { "counter": "1", "guid": { "id": { "addr": "0xb9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "creation_num": "2" } } } }, "event": "write_resource", "resource": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>" }, { "address": "b9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "data": { "counter": "4" }, "event": "write_resource", "resource": "0x1::guid::Generator" }, { "address": "b9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "data": { "message": "hello!", "message_change_events": { "counter": "0", "guid": { "id": { "addr": "0xb9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb", "creation_num": "3" } } } }, "event": "write_resource", "resource": "0xb9bd2cfa58ca29bce1d7add25fce5c62220604cd0236fe3f90d9de91ed9fb8cb::Message::MessageHolder" } ], "gas_used": 41, "success": true, "version": 3488, "vm_status": "Executed successfully" } } ``` ## 6. (Optional) Formally Verifying Move Scripts For cases where you want to guarantee that your code works as expected beyond unit testing, you can use the [Move Prover](/build/smart-contracts/prover) to formally verify your Move contract code. You can install the Move Prover by following [these steps](/build/cli/setup-cli/install-move-prover). Once you have installed the Move Prover, you can use it from the Aptos CLI by running: ```shellscript filename="Terminal" aptos move prove --package-dir ``` To learn how to formally verify your code, please follow the in-depth Move tutorial [here](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/move-tutorial) (step 7 and 8 cover how to use the Move Prover and write formal specifications in the example code). # Arguments in JSON Tutorial > Learn how to pass complex arguments to Move functions using JSON format in the Aptos CLI, including vectors, entry functions, view functions, and script functions. import { Aside } from '@astrojs/starlight/components'; ## Package info This section references the [`CliArgs` example package](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/cli_args), which contains the following manifest: ```toml filename="move.toml" [package] name = "CliArgs" version = "0.1.0" upgrade_policy = "compatible" [addresses] test_account = "_" [dependencies] AptosFramework = { git = "https://github.com/aptos-labs/aptos-framework.git", rev = "mainnet", subdir = "aptos-framework" } ``` Here, the package is deployed under the named address `test_account`. ## Deploying the package Start by mining a vanity address for Ace, who will deploy the package: ```shellscript filename="Terminal" aptos key generate \ --vanity-prefix 0xace \ --output-file ace.key ```
Output ```shellscript filename="Terminal" { "Result": { "Account Address:": "0xacef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "PublicKey Path": "ace.key.pub", "PrivateKey Path": "ace.key" } } ```
Store Ace's address in a shell variable, so you can call it inline later on: ```shellscript filename="Terminal" # Your exact address will vary ace_addr=0xacef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46 ``` Fund Ace's account with the faucet (only works on devnet): ```shellscript filename="Terminal" aptos account fund-with-faucet --account $ace_addr ```
Output ```shellscript filename="Terminal" { "Result": "Added 100000000 Octas to account acef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46" } ```
Now publish the package under Ace's account: ```shellscript filename="Terminal" aptos move publish \ --named-addresses test_account=$ace_addr \ --private-key-file ace.key \ --assume-yes ```
Output ```json filename="Terminal" { "Result": { "transaction_hash": "0x1d7b074dd95724c5459a1c30fe4cb3875e7b0478cc90c87c8e3f21381625bec1", "gas_used": 1294, "gas_unit_price": 100, "sender": "acef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "sequence_number": 0, "success": true, "timestamp_us": 1685077849297587, "version": 528422121, "vm_status": "Executed successfully" } } ```
## Entry functions The only module in the package, `cli_args.move`, defines a simple `Holder` resource with fields of various data types: ```move filename="Holder in cli_args.move" module test_account::cli_args { use std::signer; use aptos_std::type_info::{Self, TypeInfo}; use std::string::String; struct Holder has key, drop { u8_solo: u8, bytes: vector, utf8_string: String, bool_vec: vector, address_vec_vec: vector>, type_info_1: TypeInfo, type_info_2: TypeInfo, } ``` A public entry function with multi-nested vectors can be used to set the fields: ```move filename="Setter function in cli_args.move" /// Set values in a `Holder` under `account`. public entry fun set_vals( account: signer, u8_solo: u8, bytes: vector, utf8_string: String, bool_vec: vector, address_vec_vec: vector>, ) acquires Holder { let account_addr = signer::address_of(&account); if (exists(account_addr)) { move_from(account_addr); }; move_to(&account, Holder { u8_solo, bytes, utf8_string, bool_vec, address_vec_vec, type_info_1: type_info::type_of(), type_info_2: type_info::type_of(), }); } ``` After the package has been published, `aptos move run` can be used to call `set_vals()`: ```shellscript filename="Running function with nested vector arguments from CLI" aptos move run \ --function-id $ace_addr::cli_args::set_vals \ --type-args \ 0x1::account::Account \ 0x1::chain_id::ChainId \ --args \ u8:123 \ "hex:0x1234" \ "string:hello, world\! ♥" \ "bool:[false, true, false, false]" \ 'address:[["0xace", "0xbee"], ["0xcad"], []]' \ --private-key-file ace.key \ --assume-yes ```
Output ```json filename="Terminal" { "Result": { "transaction_hash": "0x5e141dc6c28e86fa9f5594de93d07a014264ebadfb99be6db922a929eb1da24f", "gas_used": 504, "gas_unit_price": 100, "sender": "acef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "sequence_number": 1, "success": true, "timestamp_us": 1685077888820037, "version": 528422422, "vm_status": "Executed successfully" } } ```
The function ID, type arguments, and arguments can alternatively be specified in a JSON file: ```json filename="entry_function_arguments.json" { "function_id": "::cli_args::set_vals", "type_args": [ "0x1::account::Account", "0x1::chain_id::ChainId" ], "args": [ { "type": "u8", "value": 123 }, { "type": "hex", "value": "0x1234" }, { "type": "string", "value": "hello, world! ♥" }, { "type": "bool", "value": [ false, true, false, false ] }, { "type": "address", "value": [ [ "0xace", "0xbee" ], [ "0xcad" ], [] ] } ] } ``` Here, the call to `aptos move run` looks like: ```shellscript filename="Running function with JSON input file" aptos move run \ --json-file entry_function_arguments.json \ --private-key-file ace.key \ --assume-yes ```
Output ```json filename="Terminal" { "Result": { "transaction_hash": "0x60a32315bb48bf6d31629332f6b1a3471dd0cb016fdee8d0bb7dcd0be9833e60", "gas_used": 3, "gas_unit_price": 100, "sender": "acef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "sequence_number": 2, "success": true, "timestamp_us": 1685077961499641, "version": 528422965, "vm_status": "Executed successfully" } } ```
## View functions Once the values in a `Holder` have been set, the `reveal()` view function can be used to check the first three fields, and to compare type arguments against the last two fields: ```move filename="View function" struct RevealResult has drop { u8_solo: u8, bytes: vector, utf8_string: String, bool_vec: vector, address_vec_vec: vector>, type_info_1_match: bool, type_info_2_match: bool } #[view] /// Pack into a `RevealResult` the first three fields in host's /// `Holder`, as well as two `bool` flags denoting if `T1` & `T2` /// respectively match `Holder.type_info_1` & `Holder.type_info_2`, /// then return the `RevealResult`. public fun reveal(host: address): RevealResult acquires Holder { let holder_ref = borrow_global(host); RevealResult { u8_solo: holder_ref.u8_solo, bytes: holder_ref.bytes, utf8_string: holder_ref.utf8_string, bool_vec: holder_ref.bool_vec, address_vec_vec: holder_ref.address_vec_vec, type_info_1_match: type_info::type_of() == holder_ref.type_info_1, type_info_2_match: type_info::type_of() == holder_ref.type_info_2 } } ``` This view function can be called with arguments specified either from the CLI or from a JSON file: ```shellscript filename="Arguments via CLI" aptos move view \ --function-id $ace_addr::cli_args::reveal \ --type-args \ 0x1::account::Account \ 0x1::account::Account \ --args address:$ace_addr ``` ```shellscript filename="Arguments via JSON file" aptos move view --json-file view_function_arguments.json ``` ```json filename="view_function_arguments.json" { "function_id": "::cli_args::reveal", "type_args": [ "0x1::account::Account", "0x1::account::Account" ], "args": [ { "type": "address", "value": "" } ] } ``` ```shellscript filename="Terminal" { "Result": [ { "address_vec_vec": [ [ "0xace", "0xbee" ], [ "0xcad" ], [] ], "bool_vec": [ false, true, false, false ], "bytes": "0x1234", "type_info_1_match": true, "type_info_2_match": false, "u8_solo": 123, "utf8_string": "hello, world! ♥" } ] } ``` ## Script functions The package also contains a script, `set_vals.move`, which is a wrapper for the setter function: ```move filename="script" script { use test_account::cli_args; use std::vector; use std::string::String; /// Get a `bool` vector where each element indicates `true` if the /// corresponding element in `u8_vec` is greater than `u8_solo`. /// Then pack `address_solo` in a `vector>` and /// pass resulting argument set to public entry function. fun set_vals( account: signer, u8_solo: u8, bytes: vector, utf8_string: String, u8_vec: vector, address_solo: address, ) { let bool_vec = vector::map_ref(&u8_vec, |e_ref| *e_ref > u8_solo); let addr_vec_vec = vector[vector[address_solo]]; cli_args::set_vals(account, u8_solo, bytes, utf8_string, bool_vec, addr_vec_vec); } } ``` First compile the package (this will compile the script): ```shellscript filename="Compilation" aptos move compile --named-addresses test_account=$ace_addr ```
Output ```json filename="Terminal" { "Result": [ "acef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46::cli_args" ] } ```
Next, run `aptos move run-script`: ```shellscript filename="Arguments via CLI" aptos move run-script \ --compiled-script-path build/CliArgs/bytecode_scripts/set_vals.mv \ --type-args \ 0x1::account::Account \ 0x1::chain_id::ChainId \ --args \ u8:123 \ "hex:0x1234" \ "string:hello, world\! ♥" \ "u8:[122, 123, 124, 125]" \ address:"0xace" \ --private-key-file ace.key \ --assume-yes ```
Output ```json filename="Terminal" { "Result": { "transaction_hash": "0x1d644eba8187843cc43919469112339bc2c435a49a733ac813b7bc6c79770152", "gas_used": 3, "gas_unit_price": 100, "sender": "acef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "sequence_number": 3, "success": true, "timestamp_us": 1685078415935612, "version": 528426413, "vm_status": "Executed successfully" } } ```
```shellscript filename="Arguments via JSON file" aptos move run-script \ --compiled-script-path build/CliArgs/bytecode_scripts/set_vals.mv \ --json-file script_function_arguments.json \ --private-key-file ace.key \ --assume-yes ```
Output ```json filename="Terminal" { "Result": { "transaction_hash": "0x840e2d6a5ab80d5a570effb3665f775f1755e0fd8d76e52bfa7241aaade883d7", "gas_used": 3, "gas_unit_price": 100, "sender": "acef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "sequence_number": 4, "success": true, "timestamp_us": 1685078516832128, "version": 528427132, "vm_status": "Executed successfully" } } ```
```json filename="script_function_arguments.json" { "type_args": [ "0x1::account::Account", "0x1::chain_id::ChainId" ], "args": [ { "type": "u8", "value": 123 }, { "type": "hex", "value": "0x1234" }, { "type": "string", "value": "hello, world! ♥" }, { "type": "u8", "value": [ 122, 123, 124, 125 ] }, { "type": "address", "value": "0xace" } ] } ``` Both such script function invocations result in the following `reveal()` view function output: ```shellscript filename="View function call" aptos move view \ --function-id $ace_addr::cli_args::reveal \ --type-args \ 0x1::account::Account \ 0x1::chain_id::ChainId \ --args address:$ace_addr ``` ```json filename="View function output" { "Result": [ { "address_vec_vec": [["0xace"]], "bool_vec": [false, false, true, true], "bytes": "0x1234", "type_info_1_match": true, "type_info_2_match": true, "u8_solo": 123, "utf8_string": "hello, world! ♥" } ] } ``` # Local Simulation, Benchmarking & Gas Profiling > Learn how to simulate, benchmark, and profile gas usage of Move transactions locally using the Aptos CLI for performance optimization and debugging. import { Aside, FileTree } from '@astrojs/starlight/components'; ## Overview The previous tutorial demonstrates how you can deploy and interact with Move contracts using various CLI commands. By default, those commands send a transaction to the remote fullnode for simulation and execution. You can override this behavior and simulate the transaction locally, by appending one of the following command line options of your preference: - `--local`: Simulate the transaction locally without conducting any further measurements or analysis. - `--benchmark`: Benchmark the transaction and report the running time(s). - `--profile-gas`: Profile the transaction for detailed gas usage. These additional options can be used in combination with the following CLI commands: - `aptos move run` - `aptos move run-script` - `aptos move publish` Alternatively, if you are interested in replaying a past transaction, check out [this tutorial](/build/cli/replay-past-transactions). ## Deploying the Example Contract For demonstration purposes, we will continue to use the [`hello_blockchain`](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/hello_blockchain) package as an example. First, publish the package to devnet or testnet (if you haven't done so already). Change into the package directory. ```shellscript filename="Terminal" cd aptos-move/move-examples/hello_blockchain ``` Then publish the package using the following command. ```shellscript filename="Terminal" aptos move publish --named-addresses hello_blockchain=default --assume-yes ```
Output ```shellscript { "Result": { "transaction_hash": "0xe4ae0ec4ea3474b2123838885b04d7f4b046c174d14d7dc1c56916f2eb553bcf", "gas_used": 1118, "gas_unit_price": 100, "sender": "dbcbe741d003a7369d87ec8717afb5df425977106497052f96f4e236372f7dd5", "sequence_number": 5, "success": true, "timestamp_us": 1713914742422749, "version": 1033819503, "vm_status": "Executed successfully" } } ```
Notice that you do need to have your CLI profile set up properly and bind the named addresses correctly. Please refer to [CLI Configuration](/build/cli/setup-cli) for more details. ## Local Simulation Next, execute the entry function message::set\_message with local simulation enabled using the additional command line option `--local`. This will execute the transaction locally without conducting any further measurements or analysis. ```shellscript filename="Terminal" aptos move run --function-id 'default::message::set_message' --args 'string:abc' --local ```
Output ```shellscript Simulating transaction locally... { "Result": { "transaction_hash": "0x5aab20980688185eed2c9a27bab624c84b8b8117241cd4a367ba2a012069f57b", "gas_used": 441, "gas_unit_price": 100, "sender": "dbcbe741d003a7369d87ec8717afb5df425977106497052f96f4e236372f7dd5", "success": true, "version": 1033887414, "vm_status": "status EXECUTED of type Execution" } } ```
## Benchmarking To measure the running time(s) of your transaction, use the `--benchmark` option. ```shellscript filename="Terminal" aptos move run --function-id 'default::message::set_message' --args 'string:abc' --benchmark ```
Output ```shellscript Benchmarking transaction locally... Running time (cold code cache): 985.141µs Running time (warm code cache): 848.159µs { "Result": { "transaction_hash": "0xa2fe548d37f12ee79df13e70fdd8212e37074c1b080b89b7d92e82550684ecdb", "gas_used": 441, "gas_unit_price": 100, "sender": "dbcbe741d003a7369d87ec8717afb5df425977106497052f96f4e236372f7dd5", "success": true, "version": 1033936831, "vm_status": "status EXECUTED of type Execution" } } ```
It's worth noting that these running times serve only as informational references, as they are contingent upon the specifications of your local machine and may be influenced by noise or other random factors. **If you are aiming to optimize your contract, you should base your decisions on the gas profiling results.** ## Gas Profiling The Aptos Gas Profiler is a powerful tool that can help you understand the gas usage of Aptos transactions. Once activated, it will simulate transactions using an instrumented VM, and generate a web-based report. The gas profiler can also double as a debugger since the report also includes a full execution trace. ### Using the Gas Profiler The gas profiler can be invoked by appending the `--profile-gas` option. ```shellscript filename="Terminal" aptos move run --function-id 'default::message::set_message' --args 'string:abc' --profile-gas ```
Output ```shellscript Simulating transaction locally using the gas profiler... Gas report saved to gas-profiling/txn-d0bc3422-0xdbcb-message-set_message. { "Result": { "transaction_hash": "0xd0bc342232f14a6a7d2d45251719aee45373bdb53f68403cfc6dc6062c74fa9e", "gas_used": 441, "gas_unit_price": 100, "sender": "dbcbe741d003a7369d87ec8717afb5df425977106497052f96f4e236372f7dd5", "success": true, "version": 1034003962, "vm_status": "status EXECUTED of type Execution" } } ```
You can then find the generated gas report in the directory `gas-profiling`: - hello\_blockchain/ - Move.toml - sources/ - gas-profiling/ - txn-XXXXXXXX-0xXXXX-message-set\_message/ - assets/ - index.html `index.html` is the main page of the report, which can view using your web browser. [Sample report](/gas-profiling/sample-report-2/index.html) ### Understanding the Gas Report The gas report consists of three sections that help you to understand the gas usage through different lenses. #### Flamegraphs The first section consists of visualization of the gas usage in the form of two flamegraphs: one for execution & IO, the other for storage. The reason why we need two graphs is that these are measured in different units: one in gas units, and the other in APT. It is possible to interact with various elements in the graph. If you hover your cursor over an item, it will show you the precise cost and percentage. ![gas-profiling-flamegraph-0.png](~/images/gas-profiling-flamegraph-0.png) If you click on an item, you can zoom into it and see the child items more clearly. You can reset the view by clicking the "Reset Zoom" button in the top-left corner. ![gas-profiling-flamegraph-1.png](~/images/gas-profiling-flamegraph-1.png) There is also "Search" button in the top-right corner that allows to match certain items and highlight them. ![gas-profiling-flamegraph-2.png](~/images/gas-profiling-flamegraph-2.png) #### Cost Break-down The second section is a detailed break-down of all gas costs. Data presented in this section is categorized, aggregated and sorted. This can be especially helpful if you know what numbers to look at. For example, the following tables show the execution costs of all Move bytecode instructions/operations. The percentage here is relative to the total cost of the belonging category (Exec + IO in this case). ![gas-profiling-cost-break-down-table.png](~/images/gas-profiling-cost-break-down-table.png) #### Full Execution Trace The final section of the gas report is the full execution trace of the transaction that looks like this: ```text filename="Example execution trace" intrinsic 2.76 85.12% dependencies 0.0607 1.87% 0xdbcb..::message 0.0607 1.87% 0xdbcb..::message::set_message 0.32416 10.00% create_ty 0.0004 0.01% create_ty 0.0004 0.01% create_ty 0.0004 0.01% create_ty 0.0004 0.01% create_ty 0.0008 0.02% imm_borrow_loc 0.00022 0.01% call 0.00441 0.14% 0x1::signer::address_of 0.007534 0.23% create_ty 0.0008 0.02% move_loc 0.000441 0.01% call 0.004043 0.12% 0x1::signer::borrow_address 0.000735 0.02% read_ref 0.001295 0.04% ret 0.00022 0.01% st_loc 0.000441 0.01% copy_loc 0.000854 0.03% load<0xdbcb..::0xdbcb..::message::MessageHolder> 0.302385 9.33% exists_generic 0.000919 0.03% not 0.000588 0.02% br_false 0.000441 0.01% imm_borrow_loc 0.00022 0.01% move_loc 0.000441 0.01% pack 0.000955 0.03% move_to_generic 0.001838 0.06% branch 0.000294 0.01% @28 ret 0.00022 0.01% ledger writes 0.097756 3.01% transaction events state write ops 0.097756 3.01% create<0xdbcb..::0xdbcb..::message::MessageHolder> 0.097756 3.01% ``` The left column lists all Move instructions and operations being executed, with each level of indentation indicating a function call. The middle column represents the gas costs associated with the operations. There is also a special notation `@number` that represents a jump to a particular location in the byte code. (`@28` in the snippet above) This is purely informational and to help understand the control flow. # Multisig Governance Tutorial > Learn how to create and use multisig accounts for governance operations using the Aptos CLI with hands-on examples for transaction proposals and execution. import { Aside } from '@astrojs/starlight/components'; ## Background This section builds upon the [Arguments in JSON tutorial](/build/cli/working-with-move-contracts/arguments-in-json-tutorial). If you have not done that, please complete that tutorial first. This tutorial likewise references the [`CliArgs` example package](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/cli_args). For this example, Ace and Bee will conduct governance operations from a 2-of-2 "multisig v2" account (an on-chain multisig account per [`multisig_account.move`](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-framework/sources/multisig_account.move)) ## Account creation Since Ace's account was created during the [Arguments in JSON](/build/cli/working-with-move-contracts/arguments-in-json-tutorial) tutorial, start by mining a vanity address account for Bee too: ```shellscript filename="Terminal" aptos key generate \ --vanity-prefix 0xbee \ --output-file bee.key ```
Output ```shellscript filename="Terminal" { "Result": { "PublicKey Path": "bee.key.pub", "PrivateKey Path": "bee.key", "Account Address:": "0xbeec980219d246581cef5166dc6ba5fb1e090c7a7786a5176d111a9029b16ddc" } } ```
Store Bee's address in a shell variable, so you can call it inline later on: ```shellscript filename="Terminal" # Your exact address should vary bee_addr=0xbeec980219d246581cef5166dc6ba5fb1e090c7a7786a5176d111a9029b16ddc ``` Fund Bee's account using the faucet: ```shellscript filename="Terminal" aptos account fund-with-faucet --account $bee_addr ```
Output ```shellscript filename="Terminal" { "Result": "Added 100000000 Octas to account beec980219d246581cef5166dc6ba5fb1e090c7a7786a5176d111a9029b16ddc" } ```
Ace can now create a multisig account: ```shellscript filename="Terminal" aptos multisig create \ --additional-owners $bee_addr \ --num-signatures-required 2 \ --private-key-file ace.key \ --assume-yes ```
Output ```shellscript filename="Terminal" { "Result": { "multisig_address": "57478da34604655c68b1dcb89e4f4a9124b6c0ecc1c59a0931d58cc4e60ac5c5", "transaction_hash": "0x849cc756de2d3b57210f5d32ae4b5e7d1f80e5d376233885944b6f3cc2124a05", "gas_used": 1524, "gas_unit_price": 100, "sender": "acef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "sequence_number": 5, "success": true, "timestamp_us": 1685078644186194, "version": 528428043, "vm_status": "Executed successfully" } } ```
Store the multisig address in a shell variable: ```shellscript filename="Terminal" # Your address should vary multisig_addr=0x57478da34604655c68b1dcb89e4f4a9124b6c0ecc1c59a0931d58cc4e60ac5c5 ``` ## Inspect the multisig Use the assorted [`multisig_account.move` view functions](https://github.com/aptos-labs/aptos-core/blob/9fa0102c3e474d99ea35a0a85c6893604be41611/aptos-move/framework/aptos-framework/sources/multisig_account.move#L237) to inspect the multisig: ```shellscript filename="Number of signatures required" aptos move view \ --function-id 0x1::multisig_account::num_signatures_required \ --args \ address:"$multisig_addr" ```
Output ```shellscript filename="Terminal" { "Result": [ "2" ] } ```
```shellscript filename="Owners" aptos move view \ --function-id 0x1::multisig_account::owners \ --args \ address:"$multisig_addr" ```
Output ```shellscript filename="Terminal" { "Result": [ [ "0xbeec980219d246581cef5166dc6ba5fb1e090c7a7786a5176d111a9029b16ddc", "0xacef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46" ] ] } ```
```shellscript filename="Last resolved sequence number" aptos move view \ --function-id 0x1::multisig_account::last_resolved_sequence_number \ --args \ address:"$multisig_addr" ```
Output ```shellscript filename="Terminal" { "Result": [ "0" ] } ```
```shellscript filename="Next sequence number" aptos move view \ --function-id 0x1::multisig_account::next_sequence_number \ --args \ address:"$multisig_addr" ```
Output ```shellscript filename="Terminal" { "Result": [ "1" ] } ```
## Enqueue a publication transaction The first multisig transaction enqueued will be a transaction for publication of the [`CliArgs` example package](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/cli_args). First, generate a publication payload entry function JSON file: ```shellscript filename="Command" aptos move build-publish-payload \ --named-addresses test_account=$multisig_addr \ --json-output-file publication.json \ --assume-yes ```
Output ```shellscript filename="Terminal" { "Result": "Publication payload entry function JSON file saved to publication.json" } ```
Now have Ace propose publication of the package from the multisig account, storing only the payload hash on-chain: ```shellscript filename="Command" aptos multisig create-transaction \ --multisig-address $multisig_addr \ --json-file publication.json \ --store-hash-only \ --private-key-file ace.key \ --assume-yes ```
Output ```shellscript filename="Terminal" { "Result": { "transaction_hash": "0x70c75903f8e1b1c0069f1e84ef9583ad8000f24124b33a746c88d2b031f7fe2c", "gas_used": 510, "gas_unit_price": 100, "sender": "acef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "sequence_number": 6, "success": true, "timestamp_us": 1685078836492390, "version": 528429447, "vm_status": "Executed successfully" } } ```
Note that the last resolved sequence number is still 0 because no transactions have been resolved: ```shellscript filename="Last resolved sequence number" aptos move view \ --function-id 0x1::multisig_account::last_resolved_sequence_number \ --args \ address:"$multisig_addr" ```
Output ```shellscript filename="Terminal" { "Result": [ "0" ] } ```
However, the next sequence number has been incremented because a transaction has been enqueued: ```shellscript filename="Next sequence number" aptos move view \ --function-id 0x1::multisig_account::next_sequence_number \ --args \ address:"$multisig_addr" ```
Output ```shellscript filename="Terminal" { "Result": [ "2" ] } ```
The multisig transaction enqueued on-chain can now be inspected: ```shellscript filename="Get transaction" aptos move view \ --function-id 0x1::multisig_account::get_transaction \ --args \ address:"$multisig_addr" \ u64:1 ```
Output ```shellscript filename="Terminal" { "Result": [ { "creation_time_secs": "1685078836", "creator": "0xacef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "payload": { "vec": [] }, "payload_hash": { "vec": [ "0x62b91159c1428c1ef488c7290771de458464bd665691d9653d195bc28e0d2080" ] }, "votes": { "data": [ { "key": "0xacef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "value": true } ] } } ] } ```
Note from the above result that no payload is stored on-chain, and that Ace implicitly approved the transaction (voted `true`) upon the submission of the proposal. ## Enqueue a governance parameter transaction Now have Bee enqueue a governance parameter setter transaction, storing the entire transaction payload on-chain: ```shellscript filename="Command" aptos multisig create-transaction \ --multisig-address $multisig_addr \ --function-id $multisig_addr::cli_args::set_vals \ --type-args \ 0x1::account::Account \ 0x1::chain_id::ChainId \ --args \ u8:123 \ "bool:[false, true, false, false]" \ 'address:[["0xace", "0xbee"], ["0xcad"], []]' \ --private-key-file bee.key \ --assume-yes ```
Output ```shellscript filename="Terminal" { "Result": { "transaction_hash": "0xd0a348072d5bfc5a2e5d444f92f0ecc10b978dad720b174303bc6d91342f27ec", "gas_used": 511, "gas_unit_price": 100, "sender": "beec980219d246581cef5166dc6ba5fb1e090c7a7786a5176d111a9029b16ddc", "sequence_number": 0, "success": true, "timestamp_us": 1685078954841650, "version": 528430315, "vm_status": "Executed successfully" } } ```
Note the next sequence number has been incremented again: ```shellscript filename="Next sequence number" aptos move view \ --function-id 0x1::multisig_account::next_sequence_number \ --args \ address:"$multisig_addr" ```
Output ```shellscript filename="Terminal" { "Result": [ "3" ] } ```
Now both the publication and parameter transactions are pending: ```shellscript filename="Get pending transactions" aptos move view \ --function-id 0x1::multisig_account::get_pending_transactions \ --args \ address:"$multisig_addr" ```
Output ```shellscript filename="Terminal" { "Result": [ [ { "creation_time_secs": "1685078836", "creator": "0xacef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "payload": { "vec": [] }, "payload_hash": { "vec": [ "0x62b91159c1428c1ef488c7290771de458464bd665691d9653d195bc28e0d2080" ] }, "votes": { "data": [ { "key": "0xacef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "value": true } ] } }, { "creation_time_secs": "1685078954", "creator": "0xbeec980219d246581cef5166dc6ba5fb1e090c7a7786a5176d111a9029b16ddc", "payload": { "vec": [ "0x0057478da34604655c68b1dcb89e4f4a9124b6c0ecc1c59a0931d58cc4e60ac5c508636c695f61726773087365745f76616c7302070000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e740007000000000000000000000000000000000000000000000000000000000000000108636861696e5f696407436861696e49640003017b0504000100006403020000000000000000000000000000000000000000000000000000000000000ace0000000000000000000000000000000000000000000000000000000000000bee010000000000000000000000000000000000000000000000000000000000000cad00" ] }, "payload_hash": { "vec": [] }, "votes": { "data": [ { "key": "0xbeec980219d246581cef5166dc6ba5fb1e090c7a7786a5176d111a9029b16ddc", "value": true } ] } } ] ] } ```
## Execute the publication transaction Since only Ace has voted on the publication transaction (which he implicitly approved upon proposing) the transaction can't be executed yet: ```shellscript filename="Can be executed" aptos move view \ --function-id 0x1::multisig_account::can_be_executed \ --args \ address:"$multisig_addr" \ u64:1 ```
Output ```shellscript filename="Terminal" { "Result": [ false ] } ```
Before Bee votes, however, she verifies that the payload hash stored on-chain matches the publication entry function JSON file: ```shellscript filename="Verifying transaction proposal" aptos multisig verify-proposal \ --multisig-address $multisig_addr \ --json-file publication.json \ --sequence-number 1 ```
Output ```shellscript filename="Terminal" { "Result": { "Status": "Transaction match", "Multisig transaction": { "creation_time_secs": "1685078836", "creator": "0xacef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "payload": { "vec": [] }, "payload_hash": { "vec": [ "0x62b91159c1428c1ef488c7290771de458464bd665691d9653d195bc28e0d2080" ] }, "votes": { "data": [ { "key": "0xacef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "value": true } ] } } } } ```
Since Bee has verified that the on-chain payload hash checks out against her locally-compiled package publication JSON file, she votes yes: ```shellscript filename="Approving transaction" aptos multisig approve \ --multisig-address $multisig_addr \ --sequence-number 1 \ --private-key-file bee.key \ --assume-yes ```
Output ```shellscript filename="Terminal" { "Result": { "transaction_hash": "0xa5fb49f1077de6aa6d976e6bcc05e4c50c6cd061f1c87e8f1ea74e7a04a06bd1", "gas_used": 6, "gas_unit_price": 100, "sender": "beec980219d246581cef5166dc6ba5fb1e090c7a7786a5176d111a9029b16ddc", "sequence_number": 1, "success": true, "timestamp_us": 1685079892130861, "version": 528437204, "vm_status": "Executed successfully" } } ```
Now the transaction can be executed: ```shellscript filename="Can be executed" aptos move view \ --function-id 0x1::multisig_account::can_be_executed \ --args \ address:"$multisig_addr" \ u64:1 ```
Output ```shellscript filename="Terminal" { "Result": [ true ] } ```
Now either Ace or Bee can invoke the publication transaction from the multisig account, passing the full transaction payload since only the hash was stored on-chain: ```shellscript filename="Publication" aptos multisig execute-with-payload \ --multisig-address $multisig_addr \ --json-file publication.json \ --private-key-file bee.key \ --max-gas 10000 \ --assume-yes ```
Output Also pending the resolution of [#8304](https://github.com/aptos-labs/aptos-core/issues/8304), the CLI output for a successful multisig publication transaction execution results in an API error if only the payload hash has been stored on-chain, but the transaction can be manually verified using an explorer.
## Execute the governance parameter transaction Since only Bee has voted on the governance parameter transaction (which she implicitly approved upon proposing), the transaction can't be executed yet: ```shellscript filename="Can be executed" aptos move view \ --function-id 0x1::multisig_account::can_be_executed \ --args \ address:"$multisig_addr" \ u64:2 ```
Output ```shellscript filename="Terminal" { "Result": [ false ] } ```
Before Ace votes, however, he verifies that the payload stored on-chain matches the function arguments he expects: ```shellscript filename="Verifying transaction proposal" aptos multisig verify-proposal \ --multisig-address $multisig_addr \ --function-id $multisig_addr::cli_args::set_vals \ --type-args \ 0x1::account::Account \ 0x1::chain_id::ChainId \ --args \ u8:123 \ "bool:[false, true, false, false]" \ 'address:[["0xace", "0xbee"], ["0xcad"], []]' \ --sequence-number 2 ```
Output ```shellscript filename="Terminal" { "Result": { "Status": "Transaction match", "Multisig transaction": { "creation_time_secs": "1685078954", "creator": "0xbeec980219d246581cef5166dc6ba5fb1e090c7a7786a5176d111a9029b16ddc", "payload": { "vec": [ "0x0057478da34604655c68b1dcb89e4f4a9124b6c0ecc1c59a0931d58cc4e60ac5c508636c695f61726773087365745f76616c7302070000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e740007000000000000000000000000000000000000000000000000000000000000000108636861696e5f696407436861696e49640003017b0504000100006403020000000000000000000000000000000000000000000000000000000000000ace0000000000000000000000000000000000000000000000000000000000000bee010000000000000000000000000000000000000000000000000000000000000cad00" ] }, "payload_hash": { "vec": [] }, "votes": { "data": [ { "key": "0xbeec980219d246581cef5166dc6ba5fb1e090c7a7786a5176d111a9029b16ddc", "value": true } ] } } } } ```
Note that the verification fails if he modifies even a single argument: ```shellscript filename="Failed transaction verification with modified u8" aptos multisig verify-proposal \ --multisig-address $multisig_addr \ --function-id $multisig_addr::cli_args::set_vals \ --type-args \ 0x1::account::Account \ 0x1::chain_id::ChainId \ --args \ u8:200 \ "bool:[false, true, false, false]" \ 'address:[["0xace", "0xbee"], ["0xcad"], []]' \ --sequence-number 2 ```
Output ```shellscript filename="Terminal" { "Error": "Unexpected error: Transaction mismatch: The transaction you provided has a payload hash of 0xe494b0072d6f940317344967cf0e818c80082375833708c773b0275f3ad07e51, but the on-chain transaction proposal you specified has a payload hash of 0x070ed7c3f812f25f585461305d507b96a4e756f784e01c8c59901871267a1580. For more info, see https://aptos.dev/move/move-on-aptos/cli#multisig-governance" } ```
Ace approves the transaction: ```shellscript filename="Approving transaction" aptos multisig approve \ --multisig-address $multisig_addr \ --sequence-number 2 \ --private-key-file ace.key \ --assume-yes ```
Output ```shellscript filename="Terminal" { "Result": { "transaction_hash": "0x233427d95832234fa13dddad5e0b225d40168b4c2c6b84f5255eecc3e68401bf", "gas_used": 6, "gas_unit_price": 100, "sender": "acef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "sequence_number": 7, "success": true, "timestamp_us": 1685080266378400, "version": 528439883, "vm_status": "Executed successfully" } } ```
Since the payload was stored on-chain, it is not required to execute the pending transaction: ```shellscript filename="Execution" aptos multisig execute \ --multisig-address $multisig_addr \ --private-key-file ace.key \ --max-gas 10000 \ --assume-yes ```
Output ```shellscript filename="Terminal" { "Result": { "transaction_hash": "0xbc99f929708a1058b223aa880d04607a78ebe503367ec4dab23af4a3bdb541b2", "gas_used": 505, "gas_unit_price": 100, "sender": "acef1b9b7d4ab208b99fed60746d18dcd74865edb7eb3c3f1428233988e4ba46", "sequence_number": 8, "success": true, "timestamp_us": 1685080344045461, "version": 528440423, "vm_status": "Executed successfully" ```
# create-aptos-dapp - A templating tool for Aptos dapps > Build template projects for dapp developers to easily create front-end and smart contracts on the Aptos network import { Steps, TabItem, Tabs } from '@astrojs/starlight/components'; `create-aptos-dapp` builds a template project for dapp developers to easily create a front-end and a smart contract on the Aptos network. ## Why use create-aptos-dapp? - **Templated Setup**: `create-aptos-dapp` generates predefined end-to-end dapp templates and configuration files for you. It saves manual setup of the project structure, which can be time-consuming and error-prone. - **Contract Directory:** `create-aptos-dapp` generates a `contract` directory that includes the basic structure for Move smart contract modules. - **Best Practices**: `create-aptos-dapp` incorporates best practices and structure recommendations to develop for the Aptos network. - **Built-in Move Commands**: `create-aptos-dapp` includes built-in commands for common tasks, such as initializing the Move compiler, compiling, and publishing smart contracts on-chain. ## Prerequisites - [node and npm](https://nodejs.org/en) (npm ≥ 5.2.0) - [Python 3.6+](https://www.python.org/) ## Using `create-aptos-dapp` 1. Navigate to the directory you want to work in. ```shellscript filename="Terminal" cd your/workspace ``` 2. Install create-aptos-dapp. ```shellscript filename="Terminal" npx create-aptos-dapp@latest ``` ```shellscript filename="Terminal" pnpx create-aptos-dapp@latest ``` ```shellscript filename="Terminal" yarn create aptos-dapp ``` ```shellscript filename="Terminal" pnpm create create-aptos-dapp@latest ``` 3. Follow the CLI prompts. After installing, you will need to answer several questions about your project including: 1. The project's name 2. Which template to use ([see below](#current-templates)) 3. Whether to use Mainnet or Devnet for testing ![cad](~/images/cad-video.gif) ## Templates `create-aptos-dapp` provides you with premade end-to-end dapp templates, i.e. a ready dapp with configurations and a beautiful UI to get you started with creating a dapp on Aptos. The goals of the templates are to: 1. Familiarize users with different Aptos Standards by having an end-to-end dapp template examples. 2. Educate users on how to build a dapp on Aptos from the front-end layer to the smart contract layer and how everything in-between. 3. Provide users with pre-made templates to quickly deploy simple dapps ### Current Templates All current templates are available on [Aptos Learn](https://learn.aptoslabs.com/en/dapp-templates). Read more about specific templates below: - [Boilerplate Template](https://learn.aptoslabs.com/en/dapp-templates/boilerplate-template) - [NFT minting dapp Template](https://learn.aptoslabs.com/en/dapp-templates/nft-minting-template) - [Token minting dapp Template](https://learn.aptoslabs.com/en/dapp-templates/token-minting-template) - [Token staking dapp Template](https://learn.aptoslabs.com/en/dapp-templates/token-staking-template) - [Custom indexer template](https://learn.aptoslabs.com/en/dapp-templates/custom-indexer-template) ## Tools `create-aptos-dapp` utilizes - React framework - Vite development tool - shadcn/ui + tailwind for styling - Aptos TS SDK - Aptos Wallet Adapter - Node based Move commands # Create Aptos Dapp FAQ > Frequently asked questions about using create-aptos-dapp tool and its templates ## Why do we use `import.meta.env`? The template is built in a way that there are pages meant to be accessed only on DEV mode and pages that are meant to be accessed also on PROD mode. For example, “create collection” and “my collections” pages are only meant for local development and can only be accessed on DEV mode while the “public mint” page can be accessed on PROD mode. `import.meta.env` is the `Vite` way to know what is the environment the dapp is running on - DEV or PROD. ## I tried to publish my dapp to a live server but getting `404 error` Might need to update the root route, if you deployed your site to `user-name.github.io/my-repo` then root route should be updated to `my-repo` ## What is Tailwind CSS? Tailwind is a utility-first CSS framework that scans your components for class names and generates a static CSS file containing the corresponding styles at build-time. This framework makes it easy to quickly author styles that are co-located with your component markup without incurring any runtime performance costs. It also helps you to maintain a consistent theme throughout your app that is responsive to light and dark mode. To learn more about Tailwind CSS, please refer to their official [documentation](https://tailwindcss.com/docs/utility-first). ## What is `shadcn/ui`? Shadcn is a collection of accessible components that you can copy and paste into your app through their CLI tool. Since the source files live in your app's codebase, you can customize them as much as you need to. These components are built on top of [Radix UI Primitives](https://www.radix-ui.com/primitives) and are styled with [Tailwind CSS](https://tailwindcss.com/). To learn more about `shadcn/ui`, please refer to their official [documentation](https://ui.shadcn.com/docs). ## How to modify the theme? The theme for this template is split across `tailwind.config.js` and `frontend/index.css`. The Tailwind config declares all of the theme colors, text styles, animation keyframes, border radii, etc. The root CSS file (`index.css`) declares the actual color values for light and dark mode as CSS custom properties (CSS variables), the base radius value, and applies any global CSS required. For example, if you want to make all of the buttons and cards more round in your app, you can increase the base radius value (`--radius`) in `index.css`. If you want to add a new text style, you can define it in the `addTextStyles` function towards the end of `tailwind.config.js`. And if you want to modify the primary color of the app, you can update the HSL color values defined in `index.css`. ## How to add components? Additional components can be added through the `shadcn-ui` CLI. For example, if you wish to add a `Switch` component, you can run the following command: ```shellscript filename="Terminal" npx shadcn-ui@latest add switch ``` This command will create a `switch.tsx` file in your `frontend/components/ui` directory that contains a styled switch component. For a full list of available shadcn components, please refer to the [shadcn component documentation](https://ui.shadcn.com/docs/components). If you need to add a component that's not included in the `shadcn/ui` collection, you're welcome to add your own components under `frontend/components` or within the `frontend/pages` directory if they're specific to the page that you're working on. ## How to add colors? If you're creating your own custom components or adding to the UI in some way, you may need to add some new colors. To add a new color, you must first define the light and dark HSL color values in `frontend/index.css` and then add the new theme color token to the theme defined in `tailwind.config.js`. For more detailed instructions, please refer to the [shadcn documentation on theming](https://ui.shadcn.com/docs/theming). ## How to add dark mode? In an effort to maintain simplicity in the dapp template, only light mode is set up. However, color values are defined for both light and dark mode in the theme. If you wish to add dark mode to your app, you simply have to add the shadcn `ThemeProvider` and `ModeToggle` to your app. Once added, the UI will be fully responsive to both light and dark mode. For detailed instructions on how to achieve this, please refer to the [shadcn dark mode documentation](https://ui.shadcn.com/docs/dark-mode/vite). # Get Started Building on Aptos > Learn how to build on Aptos with smart contracts, indexer queries, SDKs, APIs, and comprehensive developer resources import { CardGrid, LinkCard } from '@astrojs/starlight/components'; import { GraphQLEditor } from '~/components/react/GraphQLEditor'; ## What would you like to learn? ## What developer tools should I use? Here's an interactive example of our [Indexer](/build/indexer) and how you can query for the Current Fungible Asset Balances of an account. More usage examples can be found in [example queries](/build/indexer/indexer-api/fungible-asset-balances). ## Coming from another ecosystem? Quickly ramp up on some of the differences and similarities between Aptos and other ecosystems. ## Do you have any examples? We've got all kinds of examples and guides, catered to what you're looking for. ### End-to-end guides ### Smart Contract guides See the [Smart Contract](/build/smart-contracts) section for more info ### Interactive guides ## How do I setup a full node or validator? # Developer Environment Setup > Set up your development environment for frontend, smart contracts, and full-stack Aptos applications with step-by-step guides import { CardGrid, LinkCard, Steps, TabItem, Tabs } from '@astrojs/starlight/components'; Here is an easy way to setup your environment depending on the type of development. {/* Frontend */} 1. Initialize Frontend Project Here are some examples of popular choices: ```shellscript filename="Terminal" pnpx create-next-app@latest ``` ```shellscript filename="Terminal" pnpx create vite my-aptos-app --template react-ts ``` 2. Install @aptos-labs/ts-sdk ```shellscript npm2yarn npm i @aptos-labs/ts-sdk ``` 3. Setup TS SDK 4. Build your app! The developer setup for using Aptos in your frontend is now complete. Checkout our other tools that streamline the development process {/* Smart Contract */} 1. Install CLI 2. Setup Editor or IDE Add the following extensions to your editor of choice to make Move Development easier 3. Create Smart Contract Navigate to your application folder and initialize a new smart contract by doing: ```shellscript filename="Terminal" aptos move init --name my_todo_list ``` 4. Build, Compile, and Deploy Smart Contract! The developer setup for using Aptos for smart contracts is now complete. For more info see the link to the Dapp tutorial below {/* create-aptos-dapp */} 1. Install create-aptos-dapp Run the below command to install a dApp from a template in seconds: { /* npx */ } ```shellscript filename="Terminal" npx create-aptos-dapp@latest ``` { /* pnpx */ } ```shellscript filename="Terminal" pnpx create-aptos-dapp@latest ``` 2. Follow the prompts Follow the CLI prompts to select a name, [template](/build/create-aptos-dapp#templates), and network for your new dApp. ![cad](~/images/cad-video.gif) 3. Start building and customizing your new dApp! Navigate to your new project and open in your favorite IDE to continue building! Follow the generated `README.md` file for next steps. 4. Continue reading # Ethereum to Aptos Migration Guide > Comprehensive comparison and migration guide for Ethereum developers transitioning to Aptos blockchain development To learn more about the differences and similarities see [Aptos Learn](https://learn.aptoslabs.com/en/tutorials/ethereum-to-aptos-guide/cheat-sheet?workshop=eth-to-aptos) ### High Level Overview | Feature | Ethereum | Aptos | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | | **Smart Contracts** | Solidity, EVM | Move, MoveVM | | **Benefits** | Mature, wide adoption | Scalability, low latency, predictable fees | | **Transaction Fees** | Variable, can be high | Lower and more predictable | | **Account Addresses** | 160-bit | 256-bit | | **Account Structure** | Balance in a single field, uses nonce | Modules and resources, uses sequence number | | **Data Storage** | Patricia Merkle Trees | Global storage with resources and modules | | **Storage Mindset** | Contract-based storage | Account centric mindset for code and data | | **Example Code** | [ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20) | [Fungible Asset](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-framework/sources/fungible_asset.move) | | **Caller ID** | `msg.sender` | `&signer` reference | | **Upgradeability** | Proxy patterns | Direct module upgrades | | **Safety & Security** | Vulnerable to attacks like reentrancy | Mitigates common vulnerabilities | | **Dispatch Type** | Dynamic dispatch | Static dispatch | | **FT Standard** | [ERC-20](https://docs.openzeppelin.com/contracts/4.x/erc20) | [Coin](/build/smart-contracts/aptos-coin) (legacy) and [Fungible Asset](/build/smart-contracts/fungible-asset) | | **NFT Standards** | [ERC-721](https://docs.openzeppelin.com/contracts/4.x/erc721), [ERC-1155](https://docs.openzeppelin.com/contracts/4.x/erc1155) | [Digital Asset](/build/smart-contracts/digital-asset) | | **Blockchain Interaction** | [Ethers.js library](https://docs.ethers.org/v6/) | [Aptos Typescript SDK](/build/sdks/ts-sdk) |
### Comparing Token Standards in Detail | | Solidity | Move (Aptos) | | ---------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Token Structure** | Each token is its own contract. | Every token is a typed `Coin` or `FungibleAsset` using a single, reusable contract. | | **Token Standard** | Must conform to standards like ERC20; implementations can vary. | Uniform interface and implementation for all tokens. | | **Balance Storage** | Balances stored in contract using a mapping structure. | **Resource-Oriented Balance**: Balances stored as a resource in the user's account. Resources cannot be arbitrarily created, ensuring integrity of token value. | | **Transfer Mechanism** | Tokens can be transferred without receiver's explicit permission. | Except for specific cases (like AptosCoin), Tokens generally require receiver's `signer` authority for transfer. |
### Comparing EVM and Move VM in Detail - **EVM**: Known for its flexibility and dynamic dispatch, which allows a wide range of smart contract behaviors. This flexibility, however, can lead to complexities in parallel execution and network operations. - **Move VM**: Focuses on safety and efficiency with a more integrated approach between the VM and the programming language. Its data storage model allows for better parallelization, and its static dispatch method enhances security and predictability.
| | EVM (Ethereum Virtual Machine) | Move VM (Move Virtual Machine) | | ------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | | **Data Storage** | Data is stored in the smart contract's storage space. | Data is stored across smart contracts, user accounts, and objects. | | **Parallelization** | Parallel execution is limited due to shared storage space. | More parallel execution enabled due to flexible split storage design. | | **VM and Language Integration** | Separate layers for EVM and smart contract languages (e.g., Solidity). | Seamless integration between VM layer and Move language, with native functions written in Rust executable in Move. | | **Critical Network Operations** | Implementation of network operations can be complex and less direct. | Critical operations like validator set management natively implemented in Move, allowing for direct execution. | | **Function Calling** | Dynamic dispatch allows for arbitrary smart contract calls. | Static dispatch aligns with a focus on security and predictable behavior. | | **Type Safety** | Contract types provide a level of type safety. | Module structs and generics in Move offer robust type safety. | | **Transaction Safety** | Uses nonces for transaction ordering and safety. | Uses sequence numbers for transaction ordering and safety. | | **Authenticated Storage** | Yes, with smart contract storage. | Yes, leveraging Move’s resource model. | | **Object Accessibility** | Objects are not globally accessible; bound to smart contract scope. | Guaranteed global accessibility of objects. | # Solana to Aptos Migration Guide > Detailed comparison and transition guide for Solana developers moving to Aptos blockchain development To learn more about the differences and similarities see [Aptos Learn](https://learn.aptoslabs.com/en/tutorials/solana-to-aptos-guide/cheat-sheet?workshop=solana-to-aptos) | | Solana | Aptos | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | | **Smart Contracts** | Rust, SVM | Move, MoveVM | | **Transaction Fees** | Low | Low | | **Parallelization** | Pessimistic parallelism, need to declare all write accounts | Optimistic parallelism, chain infers write accounts for you | | **Contract Account Support** | PDA Account | [Object](/build/smart-contracts/objects) or [resource account](/build/smart-contracts/resource-accounts)(encourage to use object instead) | | **Data Storage** | Data stored in account owned by programs | Data stored as resource under user account or object | | **Storage Level** | Program level | Global when stored under object | | **Storage Mindset** | User data stored distributedly under account | User data stored distributedly under object | | **Example Code** | [Todo list contract on Solana](https://github.com/aptos-labs/move-by-examples/tree/main/advanced-todo-list/solana) | [Todo list contract on Aptos](https://github.com/aptos-labs/move-by-examples/tree/main/advanced-todo-list/aptos) | | **Caller ID** | `signer` | `signer` | | **Upgradability** | Program is upgradable | Module is upgradable | | **Dispatch Type** | Static dispatch | Static dispatch | | **FT Standards** | Token program | [Coin](/build/smart-contracts/aptos-coin) (legacy) and [Fungible Asset Standard](/build/smart-contracts/fungible-asset) | | **NFT Standards** | Token program | [Digital Asset Standard](/build/smart-contracts/digital-asset) | | **Blockchain Interaction** | Solana web3.js library | [Aptos Typescript SDK](/build/sdks/ts-sdk) | # Learn from Guides > Comprehensive step-by-step tutorials to help you build on Aptos blockchain, from beginner basics to advanced development patterns import { CardGrid, LinkCard } from '@astrojs/starlight/components'; Welcome to Aptos guides! Whether you're just getting started or building advanced applications, these step-by-step tutorials will help you accomplish specific tasks on the Aptos blockchain. ## Beginner Guides Start your journey with these foundational tutorials: ## Advanced Guides Ready for more complex scenarios? Explore these advanced topics: # Aptos Keyless > Integrate Keyless accounts for seamless user onboarding using social logins instead of traditional private key management. ## Integrate with Aptos Keyless accounts - [Introduction](/build/guides/aptos-keyless/introduction) - [OIDC Support and Configuration](/build/guides/aptos-keyless/oidc-support) - [Integration Guide](/build/guides/aptos-keyless/integration-guide) - [Simple Example](/build/guides/aptos-keyless/simple-example) - [How Aptos Keyless works](/build/guides/aptos-keyless/how-keyless-works) - [Terminology and FAQ](/build/guides/aptos-keyless/other) ## Using an IAM Provider? Integrate with Aptos Federated Keyless - [Federated Keyless](/build/guides/aptos-keyless/federated-keyless) ## Example Visit this page to learn more [Simple Example](/build/guides/aptos-keyless/simple-example)